记一次OOM问题排查过程
上周运维反馈线上程序出现了OOM,程序日志中的输出为
Exception in thread "http-nio-8080-exec-1027" java.lang.OutOfMemoryError: Java heap space
Exception in thread "http-nio-8080-exec-1031" java.lang.OutOfMemoryError: Java heap space
看线程名称应该是tomcat的nio工作线程,线程在处理程序的时候因为无法在堆中分配更多内存出现了OOM,幸好JVM启动参数配置了-XX:+HeapDumpOnOutOfMemoryError,使用MAT打开拿到的hprof文件进行分析。
第一步就是打开Histogram看看占用内存最大的是什么对象:
可以看到byte数组占用了接近JVM配置的最大堆的大小也就是8GB,显然这是OOM的原因。
第二步看一下究竟是哪些byte数组,数组是啥内容:
可以看到很明显这和HTTP请求相关,一个数组大概是10M的大小。
第三步通过查看GC根查看谁持有了数组的引用:
这符合之前的猜测,是tomcat的线程在处理过程中分配了10M的buffer在堆上。至此,马上可以想到一定是什么参数设置的不合理导致了这种情况,一般而言tomcat不可能为每一个请求分配如此大的buffer。
第四步就是检查代码里是否有tomcat或服务器相关配置,看到有这么一个配置:
max-http-header-size: 10000000
至此,基本已经确定了八九不离十就是这个不合理的最大http请求头参数导致的问题。
到这里还有3个疑问:
- 即使一个请求分配10M内存,堆有8GB,难道当时有这么多并发吗?800个tomcat线程?
- 参数只是设置了最大请求头10M,为什么tomcat就会一次性分配这么大的buffer呢?
- 为什么会有如此多的tomcat线程?感觉程序没这么多并发。
先来看问题1,这个可以通过MAT在dump中继续寻找答案。
可以打开线程视图,搜索一下tomcat的工作线程,发现线程数量的确很多有401个,但是也只是800的一半:
再回到那些大数组的清单,按照堆分配大小排序,往下看:
可以发现除了有10008192字节的数组还有10000000字节的数组,查看引用路径可以看到这个正好是10M的数组是output buffer,区别于之前看到的input buffer:
好吧,这就对了,一个线程分配了输入输出两个buffer,占用20M内存,一共401个线程,占用8GB,所以OOM了。
还引申出一个问题为啥有这么多工作线程,
再来看看问题2,这就需要来找一下源码了,首先max-http-header-size是springboot定义的参数,查看springboot代码可以看到这个参数对于tomcat设置的是MaxHttpHeaderSize:
然后来看看tomcat源码:
进一步看一下input buffer:
buffer大小是MaxHttpHeaderSize+ReadBuffer大小,后者默认是8192字节:
<attribute name="socket.appReadBufSize" required="false">
<p>(int)Each connection that is opened up in Tomcat get associated with
a read ByteBuffer. This attribute controls the size of this buffer. By
default this read buffer is sized at <code>8192</code> bytes. For lower
concurrency, you can increase this to buffer more data. For an extreme
amount of keep alive connections, decrease this number or increase your
heap size.</p>
</attribute>
这也就是为什么之前看到大量的buffer是10008192字节的。显然还有一批内容是空的10000000字节的buffer应该是output buffer,来看看源码:
嗯这是一个header buffer,所以正好是10000000字节。
至于问题3,显然我们的应用程序是配置过最大线程的(查看配置后发现的确,我们配置为了2000,好吧有点大),否则也不会有401个工作线程(默认150),如果当时并发并不大的话就一种可能,请求很慢,虽然并发不大,但是因为请求执行的慢就需要更多线程,比如TPS是100,但是平均RT是4s的话,就是400线程了。这个问题的答案还是可以通过MAT去找,随便看几个线程可以发现很多线程都在等待一个外部服务的返回,这说明外部服务比较慢,去搜索当时的程序日志可以发现有很多"feign.RetryableException: Read timed out executing的日志"。。。。追杀下游去!慢点,我们的feign的timeout也需要再去设置一下,别被外部服务拖死了。
记一次OOM问题排查过程的更多相关文章
- 记一次oom问题排查
大家好,我是大彬~ 今天给大家分享最近出现的OOM问题. 上周五早上,测试同学反馈测试环境的子系统服务一直超时,请求没有响应. 收到这个问题之后,我有点纳闷,最近这个系统也没有改动代码逻辑,怎么会突然 ...
- 解Bug之路-记一次中间件导致的慢SQL排查过程
解Bug之路-记一次中间件导致的慢SQL排查过程 前言 最近发现线上出现一个奇葩的问题,这问题让笔者定位了好长时间,期间排查问题的过程还是挺有意思的,正好博客也好久不更新了,就以此为素材写出了本篇文章 ...
- 解Bug之路-记一次存储故障的排查过程
解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...
- 记一次生产环境Nginx日志骤增的问题排查过程
摘要:众所周知,Nginx是目前最流行的Web Server之一,也广泛应用于负载均衡.反向代理等服务,但使用过程中可能因为对Nginx工作原理.变量含义理解错误,或是参数配置不当导致Nginx工作异 ...
- JAVA本地环境启动OOM问题排查
1.问题描述 每次启动信息报错如下: 2.排查过程 2.1起初怀疑是堆内存不够: 将本地队内存调整由-Xms512M,-Xmx1024M,改成与测试环境相同1536M,还是失败 如上图报错中有noti ...
- 记一次NoHttpResponseException问题排查
上传文件程序会有一定的概率提示错误,错误率大概在1%以下,错误信息是:org.apache.http.NoHttpResponseException , s3-us-west-1.amazonaws. ...
- 一次kibana服务失败的排查过程
公司在kubernetes集群上稳定运行数月的kibana服务于昨天下午突然无法正常提供服务,访问kibana地址后提示如下信息: 排查过程: 看到提示后,第一反应肯定是检查elasticsearch ...
- 坑爹坑娘坑祖宗的87端口(记一次tomcat故障排查)
原贴如下 坑爹坑娘坑祖宗的87端口(记一次tomcat故障排查) 虽然我用的是PHPstudy部署的dedecms,还是一样栽倒这个坑里了. 总结经验:本地测试使用8000~9000的端口比较安全.
- 记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?)
记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?) 前几天帮客户优化一个数据库,那个数据库的大小是6G 这麽小的数据库按道理不会有太大的性能问题的, ...
随机推荐
- 2016 ACM-ICPC EC-Final题解
题目链接 A. Number Theory Problem 题意:给你一个数N,求形如2k-1且小于2N的数中有多少能被7整除. 解法:观察二进制位找规律,答案是N/3. #include<bi ...
- [转]NME Android目标中文输入问题完美解决!
最近研究了一下haxe,发现蛮牛逼的,转几篇知识帖 haXe开发笔记:中文问题的小结 * .hx源文件中如果包含中文,要保存成UTF-8编码才能够正确被haXe编译器解析,是否包含BOM(Byte O ...
- FS系统开发设计(思维导图)
FS系统开发设计(思维导图) 最近做了一个小系统,公司应急,要对各个部门进行费用成本核算分摊,做运维,苦于无奈,简简单单的设计了一下,模仿用友ERP软件,首先对DB进行了初步设计,总体如下: 未完 ...
- mysql之 mysql数据库压力测试工具(mysqlslap)
mysqlslap是从MySQL的5.1.4版开始就开始官方提供的压力测试工具.通过模拟多个并发客户端并发访问MySQL来执行压力测试,同时提供了较详细的SQL执行数据性能报告,并且能很好的对比多个存 ...
- java中io的详解
注:本文全篇转载于:http://blog.csdn.net/taxueyingmei/article/details/7697042,觉得讲的挺详细,就借过来看看,挺不错的文章. 先贴一张图 Jav ...
- php之laravel学习
http://laravel-china.github.io/php-the-right-way/#composer_and_packagist laravel 添加 dingoapi路由插件 并运用 ...
- Doubango开源项目
compv Insanely fast computer vision library for ARM and x86 devices (Up to #50 times faster than Ope ...
- SpringMVC 之URL请求到Action的映射(1)
URL路径映射 1.1.对一个action配置多个URL映射: @RequestMapping(value={"/index", "/hello"}, meth ...
- MySQL 数据库 练习题
一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号: 3.查询平均成绩大于60分的同学的学号和平均成绩: 4.查询所有 ...
- Ubuntu中vi命令的使用
指今说明: 进入 vi 的命令vi filename: 打开或新建文件,并将光标置于第一行首 vi +n filename: 打开文件,并将光标置于第n行首 vi + filename: 打开文件,并 ...