一次 ES-APM 导致的概率性大量线程阻塞问题排查( 二 )
可以看到 CountedCompleter 类经过多次转换 , 从几 k 大小变为了 100k 以上 , 继续转换还变得更大 , 代码变得更复杂 , ASM 注入字节码的时间会变得越来越长 , 表现出来的现象就是:
- 持有锁的线程花在转换类的时间会越来越长
- 相应的 , 等待锁的线程将要等待更久的时间
[06:15:32][http-nio-18880-exec-49]done:class java.util.stream.Nodes$CollectorTask time:313306[06:15:33][http-nio-18880-exec-45]done:class java.util.stream.Nodes$ToArrayTask$OfRef time:496233...[06:15:50][http-nio-18880-exec-17]done:class java.util.stream.Nodes$ToArrayTask$OfRef time:183171075...[06:16:54][http-nio-18880-exec-27]done:class java.util.stream.Nodes$ToArrayTask$OfRef time:817135481...[06:22:51][http-nio-18880-exec-59]done:class java.util.stream.Nodes$CollectorTask time:43873324975...可以看到等锁的线程 , 有的等了 400 多秒 , bytebuddy 字节码注入的时间也在快速增大 , 后面甚至要几分钟 。验证为了侧面印证前面的分析过程 , 可以验证这样的情况:第一次只有一个请求 , 没有用户造成的并发情况 , 让并发相关的类都快速注入完成 , 再来做压测 , 看看还会不会出问题 。 步骤如下:
- 第一步 , 等服务启动完 , 使用 curl 请求 , 先请求一次接口 。
- 然后使用 ab 或者 jmeter 疯狂来压那个接口 , 看看接口的响应情况 。
解决办法最简单的解决是业务暂时去掉 parallelStream , 有坑先绕过 。 还有一个不成熟的改法 , 也不知道对不对:把 synchronized 同步块里的鸡肋二次判断 contains 前面加一行获取最新 appliedInstrumentations 的逻辑 , 如下所示 , 如果已经转换过了 , 就可以跳过后面的逻辑了 。
文章插图经过重新打包 ES-APM 进行测试 , 确实解决了这个场景下的问题 。
小结【一次 ES-APM 导致的概率性大量线程阻塞问题排查】出问题的时候 , 不要怀疑自己 , 大胆的怀疑框架吧 , ES-APM 这个调用超级频繁的代码中有一个类锁性能好不到哪里去 , 有很大的改善空间 。 好了 , 落班 。
作者:挖坑的张师傅
链接:
- 统计|多久才能换一次手机?统计机构数据有点意外
- 不让|12月第一次统计手机热卖榜 前三果然不让人失望
- 鼓励|(经济)商务部:鼓励引导商务领域减少使用塑料袋等一次性塑料制品
- SVIP|QQ开放QID身份号:SVIP也只能花10元修改一次
- 研发|全球目光紧盯英国,倪光南又一次发出警告:必须阻止这一场交易
- 最惨|这是 iPhone 12 被黑最惨的一次!
- 产业|新主导力量来了,上海如何实现一次“革命性重塑”?
- 三星|三星工厂良品率堪忧导致5G芯片全报废,高通总裁惊叹华为科技
- 一次尼康式的升级 写在尼康Z 6II/Z 7II发布之际
- QQ开放QID身份号:SVIP也只能花10元修改一次
