JVM实战(31)——内存溢出之请求超时

一、简介

本章,我们将通过实际案例讲解一个Web应用的内存溢出问题,该内存溢出问题的排查涉及Tomcat的一些底层原理,最终排查发现是由于请求超时问题导致,我们先来看下系统的背景。

1.1 系统背景

生产环境的一个系统发生告警,拿到生产日志后出现如下字样:
Exception in thread "http-nio-8080-exec-1089" java.lang.OutOfMemoryError:Java heap space

很明显,Java堆内存区域发生了内存溢出异常。特别要注意的是http-nio-8080-exec-1089,由于当时系统部署在tomcat中(8080端口),所以上面这段日志的意思就是tomacat工作线程在处理请求时发生了内存溢出异常。

为什么会是tomcat的工作线程发生异常? 这就涉及tomcat的一些基本原理。

1.2 tomcat基本原理

首先,我们明确一点 Tomcat运行时本身就是一个JVM进程 ,我们写好的程序打包后放到tomcat的指定目录下,程序中的各种类会由Tomcat加载到它的JVM内存区域中,然后由tomcat来执行我们程序中的类:

tomcat有许多自己的工作线程,它们默认会监听8080端口。8080端口上收到的请求会均匀分配给这些工作线程,工作线程接收到请求后负责调用程序自身的Servlet进行处理。上述异常日志中的http-nio-8080-exec-1089,说白了就是上图中的tomcat工作线程,因为它负责调用Spring中的一大堆代码,发现运行时堆内存不够了,所以就抛出了异常。

Spring Boot应用可以把web容器直接内嵌在我们打包后的程序中,但本质还是一样的。

二、问题分析

知道了系统的大致情况,我们就要用MAT来分析下事故现场的堆内存快照了(线上系统记得加上JVM参数-XX:+HeapDumpOnOutOfMemoryError)。

2.1 内存快照

我们分析内存快照,首先要找到占用堆内存最大的对象。我们发现有一大堆byte[]数组占据了大约8G的内存,而当时线上机器给Tomcat的JVM堆内存也是8G。这说明,tomcat工作线程在处理请求时大量创建了这些byte[]数组,直接把堆内存占满了,从而导致内存溢出。

然后,我们继续分析这些byte[]数组到底是个啥,通过MAT找了很多类似下面这样的数组,每个10MB,一共约800个,总量约8G:

通过MAT的引用分析,发现这些数组都被一个名为org.apache.tomcat.util.threads.TaskThread的Tomcat类引用着,这个一看就是Tomcat自己的线程类。MAT可以查看当前JVM中有哪些线程存在,我们发现上述种tomcat线程一个约400个,每一个引用着2个byte[]数组。

也就是说: 400个tomcat工作线程同时在处理请求,每个线程创建了2个10MB的byte[]数组,结果就总共创建了8G的数组,进而导致了内存溢出 。

2.2 请求超时

根据上述分析,我们的脑海里应该有这样一副流动画面:1秒钟内来了400个请求,导致tomcat的400个工作线程同时开始处理请求,每个线程在处理请求时会创建2个10MB的byte[]数组对象,用于自用,结果瞬间把8G内存空间占满,触发内存溢出异常

但是,我们通过监控系统发现,事故现场的QPS只有100,而不是400!出现这种情况只有一种可能,请求超时了,每个请求的处理时间达到4s,这样4s内400个工作线程会在同时工作,进而导致上述问题。

那么现在就剩下两个问题:

  1. 每个tomcat工作线程创建的2个10MB的byte数组究竟是啥?
  2. 程序哪里出现了大量超时?

先来看第一个,tomcat的配置文件中有一个max-http-header-size:10000000配置,根据查阅tomcat文档我们知道,这个是tomcat工作线程为请求和响应创建的数组,可以适当调小些,但是10MB也在合理范围内。所以,问题的根本原因就是程序超时。

我们通过程序日志发现,有大量的Timeout Exception字样,这是程序在通过RPC调用其他系统接口时抛出的,然后通过RPC超时参数配置发现,超时时间刚好是4s!

也就是说,在某一段时间内,某个外部依赖系统刚好挂掉了,导致我们系统通过RPC调用它的接口时出现大量超时,而在超时的4s内,工作线程会hang住,从而引发内存溢出,所以 这个4s请求超时的配置是根本原因 。

三、系统优化

分析清楚了问题原因,优化就很简单了,直接将超时时间改为1s就可以了。这样的话,每秒100个请求过来,每个拥有2个byte数组,那总共就是2G,不会将JVM堆内存占满,然后超过1s就超时,请求结束。

超时时间的配置要根据系统运行时模型合理配置。除此之外,一些核心系统,必须要有熔断、降级、限流的机制,可以通过Hystrix来实现,没有接触过的读者可以参阅Hystrix官方资料了解。

四、总结

本章,我们通过一个实际案例分析了因为请求超时引起的内存溢出问题,以及相应的排查思路。解决这类问题的思路其实都是一致的,需要一步步去分析,在实践中积累经验,举一反三。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/347864.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux/Doctor

Enumeration nmap 已知目标开放了22,80,8089端口,扫描详细情况如下 可以看到对外开放了22,80,8089三个端口 TCP/80 SSTI 访问80端口,有一个infodoctors.htb的电子邮件,点击其他的也没有什么反应,猜测有可能需要域名访问 在/et…

day32WEB 攻防-通用漏洞文件上传二次渲染.htaccess变异免杀

本章节知识点: 1 、文件上传 - 二次渲染 2 、文件上传 - 简单免杀变异 3 、文件上传 -.htaccess 妙用 4 、文件上传 -PHP 语言特性 前置知识: 后门代码需要用特定格式后缀解析,不能以图片后缀解析脚本后门代码 ( 解析漏洞除外 ) 如&…

C++ day 1

思维导图 使用C编写一个程序&#xff0c;输入一个字符串&#xff0c;统计大小写字母、数字、空格和其他符号的个数 #include <iostream>using namespace std;int main() {int capital 0;int lower 0;int digit 0;int spaces 0;int others 0;cout << "请…

人工智能时代:让AIGC成为你的外部智慧源(文末送书)

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 什么是AIGC?二. AIGC如何运作&#xff1f;2.1 步骤一&#xff1a;收集数据2.…

web前端javascript笔记——(14)Navigator 、History、Location

Navigator <!DOCTYPE html><head><meta charset"UTF-8"><title></title><style></style><script type"text/javascript">/*DOM文档对象&#xff0c;通过js操作网页BOM 浏览器对象BOM可以使我们通过JS来操…

谷歌公布一个可以让 AI 进行自我判断输出内容正确性的模型训练框架 ASPIRE

谷歌开发了一款名为 ASPIRE 的训练框架&#xff0c;旨在增强人工智能&#xff08;AI&#xff09;模型的选择性预测能力。这款框架为模型引入了 “可信度” 机制&#xff0c;即模型会输出一系列答案&#xff0c;并为每个答案赋予一个正确概率评分。通过这种方式&#xff0c;ASPI…

day2 C++

封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <iostre…

mysql生成最近24小时整点最近30天最近12个月时间临时表

文章目录 生成最近24小时整点生成最近30天生成最近12个月 在统计的时候需要按时间来展示&#xff0c;但是数据的时间不一定是连续的&#xff0c;那就需要在代码里面生成连续的时间&#xff0c;然后按时间匹配到对应的数据&#xff0c;这样比较麻烦&#xff0c;可以在sql中使用连…

写点东西《检查和更新NPM包》

写点东西《检查和更新NPM包》 检查和更新 NPM 包 TL;DR&#xff1b; 用于检查和更新软件包的 NPM 命令# [](#npm-outdated)npm outdatednpm updatenpm update --save-dev --savenpm update -g npm-check-updates 检查和更新软件包的命令npm install -g npm-check-updatesnpx np…

蓝桥杯备赛 week 1 —— DP 背包问题

目录 &#x1f308;前言&#x1f308;&#xff1a; &#x1f4c1; 01背包问题 分析&#xff1a; dp数组求解&#xff1a; 优化&#xff1a;滚动数组&#xff1a; &#x1f4c1; 完全背包问题 &#x1f4c1; 总结 &#x1f308;前言&#x1f308;&#xff1a; 这篇文章主…

gin框架开发基础功能实践汇总

gin定位&#xff1a;一款高性能的go web框架 基本实践一次搞定&#xff01; 目录 项目结构 main.go&#xff08;多组路由&#xff09; 以order.go测试GET各请求 以customer.go测试POST/PUT请求 调用目标API前先校验(多处理器) 多路由API执行前校验 项目结构 main.go&…

Webpack5 基本使用 - 3(完结)

环境区分 可以定义多个配置文件&#xff0c;通过 webpack-merge 合并配置文件。 安装 webpack-merge yarn add webpack-merge公共配置 // webpack.common.js const path require(path) const HtmlWebpackPlugin require(html-webpack-plugin)module.exports {entry: path…

牛客——都别吵吵了,我才是签到(质因数分解和统计质因数次数)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 陶陶刚上一年级&#xff0c;今天数学课上老师教了乘法和除法&#xff0c;老师留了一道课后习题&#xff0c;陶陶很快地写完了&#xff0c;现在想请你帮助他检查一下是否和答案一致。…

Ubuntu 申请 SSL证书并搭建邮件服务器

文章目录 Log 一、域名连接到泰坦&#xff08;Titan&#xff09;电子邮件二、NameSilo Hosting 避坑三、Ubuntu 搭建邮件服务器1. 环境准备2. 域名配置3. 配置 Postfix 和 Dovecot① 安装 Nginx② 安装 Tomcat③ 申请 SSL 证书&#xff08;Lets Encrypt&#xff09;④ 配置 pos…

ORA-12528: TNS: 监听程序: 所有适用例程都无法建立新连

用了网上的办法&#xff1a; 1、修改listener.ora的参数,把动态的参数设置为静态的参数,红色标注部分 位置D:\oracle\product\10.2.0\db_1\NETWORK\ADMIN SID_LIST_LISTENER (SID_LIST (SID_DESC (SID_NAME PLSExtProc) (ORACLE_HOME D:\oracle\produ…

C++练习题1-9

文章目录 NO1、选出妃子、宫女和嬷嬷No2、根据数字判断月份No3、循环计数No4、循环选数No5、玩转字符No6、计算字符串长度No7、显示字符串中的字符No8、字符串反转No9、二维数组的应用 NO1、选出妃子、宫女和嬷嬷 其他要求&#xff1a; 超女用结构体表示不要嵌套if输入所有数据…

博物馆环境监控系统的需求是怎么来的???

一、博物馆环境基本调研和识别需求 在环境监测软件的需求中&#xff0c;首要任务是进行深入的基本调研。这包括把握已有的环境监测技术、标准与法规&#xff0c;以及用户的实际操作过程和困惑。积极与环保局、科研院所、公司等沟通&#xff0c;可搜集很多原始记录&#xff0c;…

MySQL的SQL分类与数据类型

MySQL是一款广泛使用的关系型数据库管理系统&#xff0c;开源、免费且跨平台&#xff0c;常用于存储、管理和检索结构化数据&#xff0c;并通过SQL语言支持高效的数据操作与管理。 文章目录 何为SQLSQL分类DDLDMLDCLTCLDQL MySQL的数据类型数值型日期型字符串型二进制型其他类型…

网安培训第一期——sql注入+文件

文章目录 sql inject报错注入time盲注联合查询万能密码拦截和过滤ascii注入流程base64查询的列名为mysql保留关键字key 文件上传ffuf脚本要做的三件事网络端口进程用户权限文件文件包含文件下载XSS跨站请求攻击csrf跨站请求伪造 sql inject 判断输入字段是字符串还是数字 方法…

【GitHub项目推荐--开源小游戏】【转载】

01 回合制生存游戏 Cataclysm-DDA 是一款回合制生存游戏&#xff0c;背景设置在后世界末日的世界中。虽然有些人将其描述为“僵尸游戏”&#xff0c;但《大灾变》远不止这些。努力在一个严酷、持久、程序生成的世界中生存。 为食物、设备寻找一个死去的文明的残余物。或者&am…