一次纠结的线上问题排查之应用优化

这次旷日持久的web 502问题终于画上了句号,在此总结一发,以表纪念与反思。

起因

客户在年前就已经反应网站经常502,当时还有开发任务没太在意,所以每次502就直接重启服务解决。直到年后,批量操作新功能上线,502问题就非常频繁了,几乎一天一次! 在这里自我检讨一下,对问题没有足够的重视也没有足够的警觉,自身处理这类问题的能力也需要加强。

经过

经过各路大神的分析与调试,这是分析过程, 发现是踩到了曾经的一个坑,鉴权拦截器里有用到GuavaCache,没有设置MaxSize和过期时间,而且每次前端请求发过来,cache的key都会重新new一把,导致重复积累对象,内存得不到释放,最后OOM了。这个bug在之后的版本里修复了,但是这个项目用的还是旧版本。在这里吐槽下各种版本混乱,迭代消息滞后的情况。

提几个小小的建议:

  1. 项目依赖的模块完善版本迭代文档,记录每次修复的bug,新的feature等等,内部公开此文档。
  2. 项目依赖的各种starters,工具等,配置没有详细的文档与使用场景说明,建议提供完善文档与demo。
  3. 之前看过阿里的Java开发规范文档,感觉很受用,这里分享一下。

血与泪的教训

根据这此的故障排查经历与个人经验,总结了以下建议:

应用优化建议:

  • GuavaCache 一定要设置好过期时间MaxSize(这次就是因为这个原因)
  • 拆分长方法,一个方法只做一件事
  • 完善日志,配置logback,接口入参各种级别的log,否则出了问题很难定位
   <!--设置日志按天轮转-->
   <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <encoder>
           <pattern>${FILE_LOG_PATTERN}</pattern>
       </encoder>
       <!--在application.yml里配置 logging.file-->
       <file>${LOG_FILE}</file>
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <fileNamePattern>${LOG_FILE}-%d{yyyy-MM-dd}</fileNamePattern>
           <maxHistory>7</maxHistory>
       </rollingPolicy>
   </appender>
  • 配置不要打到jar包中, 做成外部配置文件
  • JVM参数标准化
    -Xmx4096m                                # 指定JVM最大可用内存
    -Xms4096m                                # 指定JVM初始内存,建议与-Xmx保持一致,避免每次GC后JVM重新分配内存
    -XX:-UseGCOverheadLimit                  # 限制使用内存,防止GC overhead limit exceeded
    -XX:+PrintGCDetails                      # 输出详细的GC日志
    -XX:+PrintHeapAtGC                       # 在进行GC的前后打印出堆的信息
    -Xloggc:/var/log/gc/web-gc.log           # 指定GC日志路径
    -XX:+HeapDumpOnOutOfMemoryError          # JVM发生OOM时,自动生成dump文件(对于排查问题很重要)
    -XX:HeapDumpPath=/var/log/gc/oom.hprof   # 指定dump文件路径
  • 事务处理时,校验和组装数据等放到事务之外进行,事务内部只做数据库操作
  • 写代码时先思考,为什么这样写,有没有更好的写法
  • 前端做好严格的校验,不发无效的重复的请求过来
  • 起多份服务做HA
  • 应用环境及各种配置
  • 欢迎补充。。。

排查性能问题步骤:

  • 看页面的加载渲染时间,区分出是前台问题还是后台问题
  • 看后端代码是不是写成shit了,有嵌套查询,或者有很冗余的写法,并打log记录调用时间
  • 看sql是不是写成shit了,该加索引的没加,或者乱加索引
  • 看dubbo调用情况,是否dubbo配置不合理
  • 看服务器之间的网络是否通畅,ping一把
  • 看应用占用的cpu,内存是否合理
  • 看gc日志,是否有OOM情况,使用jstack,jmap等工具监控JVM
  • 终极大法:配置JVM参数在OOM时生成内存的dump文件,再用mat等工具分析。
  • 找到IDEA的一个查看应用内存的插件Memory View,以后定位内存相关问题的时候可以用上一发
    Paste_Image.png
  • 欢迎补充。。。

总结

  1. 注意保存事故现场
  2. 排查问题是要有清晰的思路,对待问题要重视
  3. 多学点JVM知识与排障工具,书到用时方恨少啊!/(ㄒoㄒ)/~~

杨智量

Read more posts by this author.

Subscribe to The Terminus Blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!