jdk下载慢怎么办 jdk下载快速方法

导语:

本文作者为解决一个JDK性能问题,从堆栈分析,到GC分析,再到Safepoint原因分析,最终定位到问题根因与所用的JDK版本有关 。并整理成文,与所有Java相关开发的同学分享此次经验 。
01 问题来了
笔者近期在工作中遇到这样一个问题:某客户新上线了一个Elasticsearch应用,但运行一段时间后就变的特别慢,甚至查询超时 。重启后服务恢复,但每隔3~4小时后问题重现 。
针对这个问题,我身边的同事也帮忙做了简单分析,发现存在大量Merge的线程,应该怎么办呢?根据我之前定位问题的经验,一般通过Thread Dump日志分析,就能找到问题原因的正确方向,然后再分析该问题不断重复的原因 。按照这个思路,问题分析起来应该不算复杂 。But,后来剧情还是出现了波折 。
02 困惑的堆栈日志
因网络隔离原因,只能由客户配合获取Thread Dump日志 。并跟客户强调了获取Thread Dump日志的技巧,每个节点每隔几秒获取一次,输出到一个独立的文件中 。集群涉及到三个节点,我们暂且将这三个节点称之为39,158,211 。问题复现后,拿到了第一批Thread Dump文件:

jdk下载慢怎么办 jdk下载快速方法


从文件的大小,可轻易看出39节点大概率是一个问题节点,它的Thread Dump日志明显大出许多:查询变慢或者卡死,通常表现为大量的Worker Thread忙碌,也就是说,活跃线程数量显著增多 。而在ES(Elasticsearch,以下简称为ES)的默认查询行为下,只要有一个节点出现问题,就会让整个查询受牵累 。
那么我们先对三个节点任选的1个Thread Dump文件的线程总体情况进行对比:
节点名称39158211线程总数366341282RUNNABLE264221162WAITING648892TIME_WAITING283228BLOCKED1000再按线程池进行分类统计:
节点名称39158211Lucene Merge Thread7700http_server_worker646464search494949transport_client_boss286430bulk323232generic1564transport_server_worker275529refresh10510management523warmer555flush555others495451可以发现:39节点上的Lucene Merge Thread明显偏多,而其它两个节点没有任何Merge的线程 。
再对39节点的Thread Dump文件进行深入分析,发现的异常点总结如下:
1. Lucene Merge Thread达到77个,其中一个线程的调用栈如下所示:

jdk下载慢怎么办 jdk下载快速方法


2. 有8个线程在竞争锁定ExpiringCache:

jdk下载慢怎么办 jdk下载快速方法


3. 有8个线程都在做HashMap#hash计算:

jdk下载慢怎么办 jdk下载快速方法


现象1中提到了有77个同时在做Merge的线程,但无法确定这些Merge任务是同时被触发的,还是因为系统处理过慢逐步堆积成这样的状态 。无论如何这像是一条重要线索 。再考虑到这是一个新上线的应用,关于环境信息与使用姿势的调研同样重要:
  • 集群共有3个节点,目前共有500+个Indices 。每个节点上写活跃的分片数在70个左右 。
  • 按租户创建Index,每个租户每天创建3个Indices 。上线初期,写入吞吐量较低 。每个索引在每分钟Flush成的Segment在KB~数MB之间 。
我开始怀疑这种特殊的使用方式:集群中存在多个写活跃的索引,但每分钟的写入量都偏小,在KB至数MB级别 。这意味着,Flush可能都是周期性触发,而不是超过预设阈值后触发 。这种写入方式,会导致产生大量的小文件 。抽样观察了几个索引中新产生的Segment文件,的确每一次生成的文件都非常小 。
关于第2点现象,我认真阅读了java.io.UnixFileSystem的源码:

推荐阅读