一整套线上故障排查技巧,爱了( 四 )
常见的 Young GC、Full GC 日志含义在此就不做赘述了 。 针对 GC 日志 , 我们就能大致推断出 youngGC 与 Full GC 是否过于频繁或者耗时过长 , 从而对症下药 。
我们下面将对 G1 垃圾收集器来做分析 , 这边也建议大家使用 G1-XX:+UseG1GC 。
①youngGC 过频繁
youngGC 频繁一般是短周期小对象较多 , 先考虑是不是 Eden 区/新生代设置的太小了 , 看能否通过调整 -Xmn、-XX:SurvivorRatio 等参数设置来解决问题 。
如果参数正常 , 但是 youngGC 频率还是太高 , 就需要使用 Jmap 和 MAT 对 dump 文件进行进一步排查了 。
②youngGC 耗时过长
耗时过长问题就要看 GC 日志里耗时耗在哪一块了 。 以 G1 日志为例 , 可以关注 Root Scanning、Object Copy、Ref Proc 等阶段 。
Ref Proc 耗时长 , 就要注意引用相关的对象 。 Root Scanning 耗时长 , 就要注意线程数、跨代引用 。
Object Copy 则需要关注对象生存周期 。 而且耗时分析它需要横向比较 , 就是和其他项目或者正常时间段的耗时比较 。
比如说图中的 Root Scanning 和正常时间段比增长较多 , 那就是起的线程太多了 。
文章插图
③触发 Full GC
G1 中更多的还是 mixedGC , 但 mixedGC 可以和 youngGC 思路一样去排查 。
触发 Full GC 了一般都会有问题 , G1 会退化使用 Serial 收集器来完成垃圾的清理工作 , 暂停时长达到秒级别 , 可以说是半跪了 。
FullGC 的原因可能包括以下这些 , 以及参数调整方面的一些思路:
- 并发阶段失败:在并发标记阶段 , MixGC 之前老年代就被填满了 , 那么这时候 G1 就会放弃标记周期 。
这种情况 , 可能就需要增加堆大小 , 或者调整并发标记线程数 -XX:ConcGCThreads 。
- 晋升失败:在 GC 的时候没有足够的内存供存活/晋升对象使用 , 所以触发了 Full GC 。
这时候可以通过 -XX:G1ReservePercent 来增加预留内存百分比 , 减少 -XX:InitiatingHeapOccupancyPercent 来提前启动标记 , -XX:ConcGCThreads 来增加标记线程数也是可以的 。
- 大对象分配失败:大对象找不到合适的 Region 空间进行分配 , 就会进行 Full GC , 这种情况下可以增大内存或者增大 -XX:G1HeapRegionSize 。
- 程序主动执行 System.gc:不要随便写就对了 。
jinfo -flag +HeapDumpBeforeFullGC pid jinfo -flag +HeapDumpAfterFullGC pid
这样得到两份 dump 文件 , 对比后主要关注被 GC 掉的问题对象来定位问题 。网络
涉及到网络层面的问题一般都比较复杂 , 场景多 , 定位难 , 成为了大多数开发的噩梦 , 应该是最复杂的了 。
这里会举一些例子 , 并从 TCP 层、应用层以及工具的使用等方面进行阐述 。
①超时
超时错误大部分处在应用层面 , 所以这块着重理解概念 。 超时大体可以分为连接超时和读写超时 , 某些使用连接池的客户端框架还会存在获取连接超时和空闲连接清理超时 。
读写超时:readTimeout/writeTimeout , 有些框架叫做 so_timeout 或者 socketTimeout , 均指的是数据读写超时 。
注意这边的超时大部分是指逻辑上的超时 。 soa 的超时指的也是读超时 。 读写超时一般都只针对客户端设置 。
连接超时:connectionTimeout , 客户端通常指与服务端建立连接的最大时间 。
服务端这边 connectionTimeout 就有些五花八门了 , Jetty 中表示空闲连接清理时间 , Tomcat 则表示连接维持的最大时间 。
其他:包括连接获取超时 connectionAcquireTimeout 和空闲连接清理超时 idleConnectionTimeout 。 多用于使用连接池或队列的客户端或服务端框架 。
我们在设置各种超时时间中 , 需要确认的是尽量保持客户端的超时小于服务端的超时 , 以保证连接正常结束 。
在实际开发中 , 我们关心最多的应该是接口的读写超时了 。 如何设置合理的接口超时是一个问题 。
如果接口超时设置的过长 , 那么有可能会过多地占用服务端的 TCP 连接 。 而如果接口设置的过短 , 那么接口超时就会非常频繁 。
服务端接口明明 RT 降低 , 但客户端仍然一直超时又是另一个问题 。 这个问题其实很简单 , 客户端到服务端的链路包括网络传输、排队以及服务处理等 , 每一个环节都可能是耗时的原因 。
②TCP 队列溢出
TCP 队列溢出是个相对底层的错误 , 它可能会造成超时、RST 等更表层的错误 。 因此错误也更隐蔽 , 所以我们单独说一说 。
- 发展|我省要求互联网平台坚持依法合规经营 推动线上经济健康规范发展
- 小米|华为成俄罗斯线上销售最受欢迎品牌!小米紧随其后
- 每日|【每日idea 分享】12月1日:带朋友一起网上购物;线上笔记本应用程序
- 商务参赞柏|秘鲁海外馆正式入驻京东国际 秘鲁期待与中国更多线上经贸合作
- 俄罗斯|厉害了!华为手机在俄罗斯线上销量第一
- 俄罗斯|华为,在俄罗斯智能手机线上渠道,销量排名第一
- 渠道|别被马云“忽悠”他因线上卖太好放弃线下,痛失洗衣液霸主
- 优衣|一炮走红的“优衣库”,不但线上店铺常卖空,线下门店数也超日本
- 唐山市人民医院成功举办第五届“加拿大?中国科技与医疗创新论坛”线上分会场活动
- 华为成俄罗斯线上销售最受欢迎品牌!小米紧随其后