|不起眼的YGC,居然对应用的RT影响这么大( 二 )


使用jmap查看年轻代对象占用空间情况,排名靠前的有多个org.apache.tomcat.util.buf包下的对象 , 比如ByteChunk、CharChunk、MessageBytes等 , 以及响应涉及的一些临时对象列表 。 其中ByteChunk等即tomcat响应输出相关类
|不起眼的YGC,居然对应用的RT影响这么大
本文插图

至此问题明确 , 超大响应包(50K)在发送到网卡的过程中 , 需要经过从用户态user space拷贝到内核态 kernel space , 然后在拷贝到网卡进行发送(像netty等的零拷贝针对的就是这种拷贝) , 加上响应体查询过程中 , 涉及的大量临时对象list , 在高并发场景下 , 就导致年轻代内存占满 , 然后频繁gc(后续在合适的时间会压测该接口) , 这里还有一个点 , 很多人以为ParNewGC不会stop the world , 其实是会的 。 频繁ParNewGC造成用户线程进入阻塞状态 , 让出CPU时间片 , 最终导致连接处理等待 , 接口的RT变高 。 整个排查过程 , 鹰眼 , idb性能监控等可视化监控平台帮助真的很大 , 否则到处去查日志得查的晕头转向了 。
经验总结

  1. 接口设计 , 需要避免超大响应体出现 , 分而治之 , 将一个大接口拆分为多个小接口 。
  2. 缓存设计 , 像这个服务一样 , 一个请求带来将近40次DB查询的 , 需要考虑在服务端进行缓存(当时偷懒了 , 要求调用方去做缓存) 。
  3. 性能设计 , 要对自己负责系统的性能了如指掌 , 可以通过压测等手段得到自己系统的天花板 , 否则 , 某一个接口hang住 , 会导致整个应用的可用性出现问题 。
  4. 流量隔离 , 内部应用和外部流量之间 , 需要进行流量隔离 , 即使通过缓存 , 也有缓存击穿的问题 。
  5. 口头说的东西都不靠谱 , 要落在文档上 , 还需要检查执行情况 。
作者:吴志炜
来源:https://www.jianshu.com/p/e4d70be7fc1e


推荐阅读