来自:crossoverJie


目录:

  • 写在前面

  • 生产现象

    • 定位问题

    • 解决办法

  • 本地模拟

    • 内存分析

  • 总结

写在前面

之前或多或少分享过一些内存模型、对象创建之类的内容,其实大部分人看完都是懵懵懂懂,也不知道这些的实际意义。

直到有一天你会碰到线上奇奇怪怪的问题,如:

  • 线程执行一个任务迟迟没有返回,应用假死。

  • 接口响应缓慢,甚至请求超时。

  • CPU 高负载运行。

这类问题并不像一个空指针、数组越界这样明显好查,这时就需要刚才提到的内存模型、对象创建、线程等相关知识结合在一起来排查问题了。

正好这次借助之前的一次生产问题来聊聊如何排查和解决问题。

生产现象

首先看看问题的背景吧:我这其实是一个定时任务,在固定的时间会开启 N 个线程并发的从 Redis 中获取数据进行运算。

业务逻辑非常简单,但应用一般涉及到多线程之后再简单的事情都要小心对待。果不其然这次就出问题了。

现象:原本只需要执行几分钟的任务执行了几个小时都没退出。翻遍了所有的日志都没找到异常。

于是便开始定位问题之路。

定位问题

既然没办法直接从日志中发现异常,那就只能看看应用到底在干嘛了。最常见的工具就是 JDK 自带的那一套。

这次我使用了 jstack 来查看线程的执行情况,它的作用其实就是 dump当前的线程堆栈。

当然在 dump 之前是需要知道我应用的 pid 的,可以使用 jps -v 这样的方式列出所有的 Java 进程。

当然如果知道关键字的话直接使用 ps aux|grep java 也是可以的。

拿到 pid=1523 了之后就可以利用 jstack 1523 > 1523.log 这样的方式将 dump 文件输出到日志文件中。

如果应用简单不复杂,线程这些也比较少其实可以直接打开查看。但复杂的应用导出来的日志文件也比较大还是建议用专业的分析工具。

我这里的日志比较少直接打开就可以了,因为我清楚知道应用中开启的线程名称,所以直接根据线程名就可以在日志中找到相关的堆栈:


所以通常建议大家线程名字给的有意义,在排查问题时很有必要。

其实其他几个线程都和这里的堆栈类似,很明显的看出都是在做 Redis 连接。

于是我登录Redis查看了当前的连接数,发现已经非常高了,这样Redis的响应自然也就变慢了。

接着利用 jps -v 列出了当前所以在跑的 Java 进程,果不其然有好几个应用都在查询 Redis,而且都是并发连接,问题自然就找到了。

解决办法

所以问题的主要原因是:大量的应用并发查询 Redis,导致 Redis 的性能降低。

既然找到了问题,那如何解决呢?

  • 减少同时查询 Redis 的应用,分开时段降低 Redis 的压力。

  • 将 Redis 复制几个集群,各个应用分开查询。但是这样会涉及到数据的同步等运维操作,或者由程序了进行同步也会增加复杂度。

目前我们选择的是第一个方案,效果很明显。

本地模拟

上文介绍的是线程相关问题,现在来分析下内存的问题。

以这个类为例:

https://github.com/crossoverJie/Java-Interview/blob/master/src/main/java/com/crossoverjie/oom/heap/HeapOOM.java

启动参数如下:

1-Xms20m2-Xmx20m3-XX:+HeapDumpOnOutOfMemoryError4-XX:HeapDumpPath=/Users/xx/Documents

为了更快的突出内存问题将堆的最大内存固定在 20M,同时在 JVM 出现 OOM 的时候自动 dump 内存到 /Users/xx/Documents(不配路径则会生成在当前目录)。

执行之后果不其然出现了异常:


同时对应的内存 dump 文件也生成了。

内存分析

这时就需要相应的工具进行分析了,最常用的自然就是 MAT 了。

我试了一个在线工具也不错(文件大了就不适合了)

  • http://heaphero.io/index.jsp

上传刚才生成的内存文件之后:


因为是内存溢出,所以主要观察下大对象:


也有相应提示,这个很有可能就是内存溢出的对象,点进去之后:


看到这个堆栈其实就很明显了:在向 ArrayList 中不停的写入数据时,会导致频繁的扩容也就是数组复制这些过程,最终达到 20M 的上限导致内存溢出了。

更多建议

上文说过,一旦使用了多线程,那就要格外小心。

以下是一些日常建议:

  • 尽量不要在线程中做大量耗时的网络操作,如查询数据库(可以的话在一开始就将数据从从 DB 中查出准备好)

  • 尽可能的减少多线程竞争锁。可以将数据分段,各个线程分别读取

  • 多利用 CAS+自旋 的方式更新数据,减少锁的使用

  • 应用中加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp 参数,在内存溢出时至少可以拿到内存日志

  • 线程池监控。如线程池大小、队列大小、最大线程数等数据,可提前做好预估

  • JVM 监控,可以看到堆内存的涨幅趋势,GC 曲线等数据,也可以提前做好准备

总结

线上问题定位需要综合技能,所以是需要一些基础技能。如线程、内存模型、Linux 等。

当然这些问题没有实操过都是纸上谈兵;如果第一次碰到线上问题,不要慌张,反而应该庆幸解决之后你又会习得一项技能。

长按二维码 ▲

订阅「架构师小秘圈」公众号

如有启发,帮我点个在看,谢谢↓

一次线上生产问题的全面复盘 【定位-分析-解决】相关推荐

  1. 真实版“删库跑路”?程序员蓄意破坏线上生产环境!

    作者 | 阿文 责编 | 伍杏玲 出品 | 程序人生(ID:coder_life) 作为程序员经常相互开玩笑说,公司要是把我逼急了,大不了我们"删库跑路",这是一句玩笑话,没想到会 ...

  2. 真实版“删库跑路”?程序员蓄意破坏线上生产环境

    作者 | 阿文 责编 | 伍杏玲 出品 | 程序人生(ID:coder_life) 作为程序员经常相互开玩笑说,公司要是把我逼急了,大不了我们"删库跑路",这是一句玩笑话,没想到会 ...

  3. 记一次线上环境 redis偶尔连接超时报错 解决

    记一次线上环境 redis偶尔连接超时报错 解决 贴出本地控制台日志 说实话,很痛苦,跟进很久了,一直认为的jvm程序所使用的配置的连接池框架问题 因为程序为 springboot 2 spring ...

  4. 一次jvm导致线上内存占用过高问题定位

    背景:8G物理内存,8核CPU,jvm使用的G1垃圾回收器. 问题:线上内存占用告警,内存占用超过85%,且现象一直持续. 分析 看一下jvm启动参数配置: -Xms6144m -Xmx6144m - ...

  5. 线上CPU100%及应用OOM的排查和解决过程

    点击上方☝,轻松关注! 及时获取有趣有料的技术文章 " 最近工作又遇到几次线上告警的问题,排查基本上就是cup100%以及内存OOM问题,再分享一下之前遇到这类问题排查的一些思路和过程,希望 ...

  6. mysql内存爆_线上MySQL机器内存爆掉原因分析与解决

    现象: 阿里金融某业务的MySQL机器的内存每隔几天就会增长,涨上去后,却不下来.累积后内存爆掉. 分析: 此业务是间隔的对MySQL有大访问,其它时间几乎无访问.排查发现,内存涨时,一般会有MySQ ...

  7. 排查Java线上服务故障的方法和实例分析

    2019独角兽企业重金招聘Python工程师标准>>> 前言 作为在线系统负责人或者是一个技术专家,你可能刚刚接手一个项目就需要处理紧急故障,或者被要求帮忙处理一些紧急的故障,这个时 ...

  8. 线上阿里云mysql慢_MySQL · 案例分析 · RDS MySQL线上实例insert慢常见原因分析-阿里云开发者社区...

    概述 insert慢是经常被问到的问题,笔者尝试在本文中对这个问题做一个分类梳理,列举的线上例子会做简化,希望对读者有所启发. 注意:因为阿里云MySQL线上实例还是以RDS 5.6为主体,本文的分析 ...

  9. 一次线上紧急事故的处理复盘

    版权声明: 本公众号发布的所有文章,未特殊署名,均属于原创,版权归本公众号所有. 转载请参阅公众号的:<转载授权>. 一.前言 之前有个周末,公司的 App 产品,导致线上的所有版本,都无 ...

最新文章

  1. 未来城市的无人机送货系统是怎样的?
  2. Java基础—IO流
  3. 并行计算实战-双调排序
  4. Android 弱引用和软引用
  5. Struts2知识点总结
  6. iptables高级应用实例
  7. html怎么设置顶部布局,html – CSS位置:固定没有顶部给出意想不到的布局?
  8. 【转】Elasticsearch+Django搜索引擎(一)
  9. 全球数字高程数据(DEM)详解,还有地形晕渲、等高线等干货
  10. 我行我素购物管理系统(面向对象)
  11. Windbg程序调试系列1-常用命令说明Mex扩展使用总结
  12. php 银联支付-app
  13. 100以内奇数的平方和
  14. 1.100个房产测量常见问题  2. 现有的商用房产测绘软件 3.问题_拔剑-浆糊的传说_新浪博客...
  15. Word恢复忘记保存的文件(打开任意.asd文件)
  16. vue大屏可视化自适应完美方案
  17. Xamarin 设置ListView组头的高度
  18. Visium空间转录组
  19. stm32正常运行流程图_stm32初始化流程图解析
  20. 虹软人脸识别SDK接入Milvus实现海量人脸快速检索

热门文章

  1. luogu P3306 [SDOI2013] 随机数生成器(BSGS,数列求通项,毒瘤特判)
  2. java如何重写_java中如何重写一个方法
  3. java汉字转换成拼音_Java代码将汉字转换成拼音
  4. 在小程序中实现 Mixins 方案
  5. 使用RecycleView实现无限滚动的日历
  6. Unix系统编程()虚拟内存管理
  7. 输出值(1)初始化输出值
  8. 今天做项目时,用到了好多关于js的知识点,有的忘记了,然后晚上回来自己整理一番,明天继续整理。哈哈,分享给大家。...
  9. 基于easyui开发Web版Activiti流程定制器详解(五)——Draw2d详解(一)
  10. 手机QQ重构移动社交市场