线上 OOM 频发,MyBatis 有坑...

news2025/1/24 14:47:20

图片

继上次线上 CPU 出现了报警,这次服务又开始整活了,风平浪静了没几天,看生产日志服务的运行的时候,频繁的出现 OutOfMemoryError,就是我们俗称的 OOM,这可还行!

频繁的 OOM 直接会造成服务处于一个不可用的情况,最严重的一天,它重启了 5 次。我通过 Skywalking 查看链路调用,基本全报红了,基本处于一个瘫痪状态,因为生产该服务是分布式部署,k8s 故障恢复当即对该服务进行重启,因为是 B 端的产品,先让公司业务能用起来了,保证服务的正常使用,然后紧急查看问题。

当然这个问题很多同事不会排查,老板就让我亲自动手了。既然分配给我了,咱高低给它查出来,并且修复了。

OutOfMemoryError出现的原因

先来了解下OutOfMemoryError出现的原因,无非就是两类堆内存空间不足、元空间不足。

  1. 堆内存空间不足:意味着程序存在一直有引用的对象(强引用),主要对象在引用的状态就无法被GC回收,撑爆了-Xmx堆拓展的最大值,内存不足自然就会触发堆内存溢出。

  2. 元空间:Java 8 引入了元空间概念,代替了之前堆的永久代,由于元空间属于堆外内存,不需要有对象引用,通过指针的方式表示类和元数据,之所以引用元空间就是一种 JDK 的升级优化,避免了永久代的内存溢出。详细内容参见https://t.zsxq.com/0fdOtNgEQ

常见堆内存溢出的几种情况

  1. 查询数据库返回的数据量过大,加载到内存中导致内存溢出;

  2. 代码中出现死循环情况,导致大对象一直被引用不能被 GC 回收;

  3. 资源链接池、io 流在使用完没有进行手动释放;

  4. 静态集合类里面存在引用对象,始终存在引用关系,没有进行清除;

以上属于常见的几种堆内存溢出的场景,当然有时候我们的遇到的问题都是稀奇古怪的问题,常见的问题总是很少能遇到…

现象分析

根据生产环境的报错日志来看,这边属于 Mybatis 报出的一个内存溢出情况,通过去看 Mybatis 源码发现,底层也是通过一些集合类来存放拼接的 sql,那么当然也有可能出现堆内存溢出,而且在 sql 体积比较大的情况下,接收 sql 的集合就会变的非常大,如果回收不了那么就会导致内存溢出。

图片

内存

由于我们 docker 容器里面没有一些 jstack、jmap 的工具,并且 dump 文件也没有进行保存…导致我无法通过看线程高占用内存的对象,来分析具体是什么操作发生的内存溢出,这就难了… 于是只能去网上搜搜看了,没想到真的给到我一些启发,并且有点思路大概知道是哪里的问题。

老天真的赏饭吃,我搜到了一篇关于惨遭 DruidDataSource 和 Mybatis 暗算的 OOM 文章。看起来,和我的情况很像。

给我带来了新的启发,这是 Mybatis 带来的 OOM。主要是因为 Mybatis 拼接 SQL 的时候生成的占位符和参数对象,存放在 Map 里,当 SQL 的参数多导致 SQL 太长的时候,Map 持有这些 SQL 时间较长,并且多线程同时操作,这时候内存占用就很高,从而发生 OOM。

Mybatis源码分析

通过对DynamicContext类源码查看,DynamicContext 又一个 ContextMap 类型的参数

bindings,继承了 HashMap 相当于一个Map集合,接着看这个类中的 getBindings 方法,看到了 ForEachSqlNode 这类调用了 getBindings 方法,简单的说就是 ForEachSqlNode 通过 getBindings 方法,将 SQL 参数和参数的占位符统一 put 到 ContextMap 这个集合里面,主要是这里面的参数和占位符无法被 GC 回收,并发查询量多的情况下就会导致 OOM。

图片

Mybatis源码分析

图片

Mybatis源码分析

图片

Mybatis源码分析

情景复现

随后我做了线上场景的复现,通过将 SQL 语句的拼接,将 IN 里面的参数变大,然后创建 50 个线程进行执行,将 JVM 堆内存设为-Xmx256m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError

图片

OOM 复现

图片

OOM 复现

这里看控制台打印的日志,服务在频繁的进行 Full GC,导致 OOM。

图片

频繁的Full GC

总结

既然发现了问题出现的原因,接下来就是对代码 SQL 进行优化,尽量避免在 sql 拼接的时候体积过大。这里告诫我们代码不能乱写,SQL 语句也不能随意写啊,有时候把问题想的过于简单确实会带来不可预知的风险。

另外,docker 中也配置了 oom 留存 dump 文件。后面如果万一再出现故障,也不至于太被动。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编程小白的自学笔记十(python爬虫入门二+实例代码详解)

系列文章目录 编程小白的自学笔记九(python爬虫入门代码详解) 编程小白的自学笔记八(python中的多线程) 编程小白的自学笔记七(python中类的继承) 编程小白的自学笔记六(python中类的静态方法…

pandas 笔记:pivot_table 数据透视表

1 基本使用方法 pandas.pivot_table(data, valuesNone, indexNone, columnsNone, aggfuncmean, fill_valueNone, marginsFalse, dropnaTrue, margins_nameAll, observedFalse, sortTrue)2 主要参数 dataDataFramevalues要进行聚合的列index在数据透视表索引(index…

flask基本用法小白教程+按钮跳转到指定页面+python和pip安装(后附)

一、flask学习教程: 1.1 基本程序: 大家可以在pycharm中复制如下代码,先感受一下flask的基本用法: 点击链接可进入浏览器查看程序运行的结果,在127.0.0.1:5000后面添上/test1/等设定的文字,可查看不同函…

Python生成exe文件运行出现黑框闪退如何查看运行bug?

cmd进行回车 第一:进入到可执行exe文件目录,如下图所示 第二:输入可执行文件名,然后就会出现报错提示

(转载)BP神经网络的非线性系统建模(matlab实现)

1案例背景 在工程应用中经常会遇到一些复杂的非线性系统,这些系统状态方程复杂,难以用数学方法准确建模。在这种情况下,可以建立BP神经网络表达这些非线性系统。方法把未知系统看成是一个黑箱,首先用系统输入输出数据训练BP神经网络,使网络能够表达该未知函数,然后用训练好的 B…

【外卖系统】环境的搭建

搭建数据库 1.创建数据库,名字叫reiggie 2.导入数据库 创建Maven项目 1.创建项目 2.检查项目新建的是否有问题 3.导入pom.xml文件 4.导入application.yml文件 在从gittee上down的代码的基础上,修改一下端口号,数据库的名称什么的 …

(数组与矩阵) 剑指 Offer 29. 顺时针打印矩阵 ——【Leetcode每日一题】

❓ 剑指 Offer 29. 顺时针打印矩阵 难度:简单 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5] 示例 2: 输…

DP转HDMI方案芯片-CS5218/CS5263/CS5363/CS5463详细参数对比说明

CS5218/CS5263/CS5363/CS5463都可用于设计DP转HDMI转接线方案,但几者间不管封装还是功能参数都有差异,如下介绍对比下: CS5218 DP to HDMI(4K30HZ) ,CS5218管脚定义参数说明和设计电路图: ​ ​ CS5263 DP to HDMI 4…

Kubernetes_1.27.3_Harbor结合Nacos实战

Nacos 实战 作者:行癫(盗版必究) 一:Nacos简介 1.简介 ​ Nacos是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台;Nacos 致力于帮助您发现、配置和管理微服务;Nacos 提供了一组简单易用的特…

计讯物联5G千兆网关TG463在电力智能巡检机器人的应用功能解析

项目背景 随着国家智能电网建设加速推进,投资规模持续扩大,我国电网智能化、信息化不断提高,传统的电力运维与管理模式早已不能满足智能电网快速发展的需求。因此,在5G无线通信、人工智能、物联网、云计算、大数据、电力等前沿技术…

Error: The client is unauthorized due to authentication failure.解决办法

进入到neo4j的安装目录 修改neo4j.conf配置文件 把红框的注释#去掉保存后,重新运行neo4j,问题解决

【Python统计与数据分析实战_01】位置与分散程度的度量

数据描述性分析 1.描述统计量1.1 位置与分散程度的度量1.1.1 例子一 单维数组1.1.2 例子二 多维数组 1.2 关系度量1.3 分布形状的度量1.3.1 统计量:偏度和峰度 1.4 数据特性的总括 1.描述统计量 数据的统计分析分为统计描述和统计推断两部分。前者通过绘制统计图、…

Vue3.0的设计目标是什么?做了哪些优化?

一、设计目标 不以解决实际业务痛点的更新都是耍流氓,下面我们来列举一下Vue3之前我们或许会面临的问题 随着功能的增长,复杂组件的代码变得越来越难以维护 缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制 类型推断不够友好 bundle的时间太久了 而 Vue3 经过长达…

RuoYi-Vue/vue项目访问 webpack 中定义的变量

前言 RuoYi-Vue 3.8.4 webpack 中定义的变量 vue.config.js 中定义的 webpack 的变量 在html页面中&#xff0c;如何访问 webpack 的变量 <title><% webpackConfig.name %></title>参考&#xff1a;ruoyi-ui/public/index.html 文件

【分布式训练】基于Pytorch的分布式数据并行训练

基于Pytorch的分布式数据并行训练 动机为什么要并行分布数据&#xff1f;现有资料的不足 Outline整体框架图带解释的最小demo示例没有multiprocessing开启multiprocessing 分布式训练启动方式混合精度训练&#xff08;采用apex&#xff09; 参考资料 简介&#xff1a; 在PyTorc…

一则 MySQL 参数设置不当导致复制中断的故障案例

本文分享了一个数据库参数错误配置导致复制中断的问题&#xff0c;以及对参数配置的建议。 作者&#xff1a;秦福朗 爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。热爱互联网&#xff0c;会摄影、懂厨艺&#xff0c;不会厨艺的 DBA 不是好司机&…

Linux学习之运算符

是赋值运算符&#xff0c;可以把一个变量设置上特定的值&#xff0c;而算术运算符就包括加减乘除&#xff08;、-、*、/&#xff09;&#xff0c;需要使用expr这个命令进行运算。 expr 5 7可以计算出来5与7的和&#xff0c;使用echo $?可以看到expr 5 7这个命令的返回值是0&…

神经网络正则化之BN/LN/GN的原理

1. BN层原理 torch.nn.BatchNorm2d(num_features, eps1e-05, momentum0.1, affineTrue, track_running_statsTrue,deviceNone,dtypeNone) 为什么用BN? 加速训练。之前训练慢是因为在训练过程中&#xff0c;整体分布逐渐往非线性函数的取值区间的上下限端靠近(参考sigmoid函数…

10.6.5 【Linux】分区命令: split

如果你有文件太大&#xff0c;导致一些携带式设备无法复制的问题&#xff0c;split可以将一个大文件&#xff0c;依据文件大小或行数来分区&#xff0c;可以将大文件分区成为小文件&#xff0c;快速有效。 将文件分区的话&#xff0c;使用-b size来将一个分区的文件限制其大小&…

软件测试岗位之我所思我所见

从业以来&#xff0c;见过很多人&#xff0c;看过很多事。唯独“测试”我觉得是我自己选的路。所以现在这个时间点&#xff0c;我想分享下我对测试的看法&#xff1a; 1、测试 &#xff1a;“轻松” “劳累” 作为一个测试&#xff0c;你可以轻松的没有下限&#xff0c;也可…