# 背景

话务量环境发现接口响应变慢,由于话务量环境啥业务都在做,没法根据业务来直接判断是哪个业务引发的

# 定位

# 1. jstat -gcutil

先用 jstat -gcutil 查看一下 垃圾收集的情况,发现老年代 使用率有点高
GC 次数和时间也比较多,可以判断肯定一直在 FullGC

# 2. jmap -heap pid

用这个也只能看出用的内存比较多
然后就自己来了一次 fgc, jmap -histo:live pid
执行完,再执行 jmap -heap pid, 没啥变化,
这时候推断,jvm 中没有垃圾,可能是那个业务 记录缓存 (Map 这种), 数据太多了,
不过 jmap -histo:live 这个也挺偶然的,可能是有线程并没执行完,所以没被当成垃圾,这一步得出的结论还不足以,定位出是哪一块的问题

# 3. 取 heapdump 来看

jmap -dump:format=b,file=/home/xxx/sch/my.dump pid
取下来用 visualvm 来分析,用 MAT 也可以,只是 visualvm 不用安装,自己电脑一般都有,看了一下,发现 String, SimpleMessage, LinkedBlockingQueue$Node 特别多,代码走读一下,发现原来是线程池的数据
进一步看,原来是无界队列,消费的速度,赶不上生产的速度了,从而触发 FGC, 再继续下去,应该就 OOM 了

# 解决方案

问题定位到了,改队列类型不太敢改,前人用这个应该是有道理的,着重看了一下,处理的代码,发现下面有锁,用的 synchronize, 给改成了 Lock 锁,粒度也给降低了,打个补丁上话务量环境,验证没有啥问题,解决,后面还优化了一版,加了批量处理的逻辑,发现队列中有太多,就走批量的逻辑