【程序大侠传】应用内存缓步攀升,告警如影随形

news2024/11/20 2:43:23

前序

在武侠编码的江湖中,内存泄漏犹如隐秘杀手,潜伏于应用程序的各个角落,悄无声息地吞噬着系统资源。若不及时发现和解决,必将导致内存枯竭,应用崩溃。

背景:内存泄漏的由来
内存泄漏,乃程序运行过程中,已不再使用的内存块未被及时回收,导致内存使用量不断增加的现象。此问题多发于对象生命周期管理不当之处,如持有对象引用过长,或未能及时释放资源,终致内存枯竭,系统崩溃。

在JVM的世界中,内存泄漏常见于以下几种情况:

  • 静态集合类:如 HashMap、ArrayList 等,若不断向其添加对象而不清理,易造成内存泄漏。
  • 长生命周期对象持有短生命周期对象引用:如单例模式中的对象持有临时对象引用,导致临时对象无法被垃圾回收。
  • 未关闭的资源:如数据库连接、文件流等,若未及时关闭,亦会导致内存泄漏。
  • 监听器与回调函数:未及时移除的监听器或回调函数,可能导致对象无法被回收。

解决方案:内存泄漏的破解之道

  1. 善用工具,探查隐患
    如同侠客需借助兵器,程序员亦需运用内存分析工具,如 jvisualvm、jmap、jhat 等,探查内存使用情况,定位内存泄漏之源。常规步骤如下:

    • 使用 jmap 生成堆转储文件:jmap -dump:live,format=b,file=heap_dump.hprof
    • 使用 jvisualvm 或 Eclipse MAT 分析堆转储文件,查找无法回收的对象。
  2. 优化代码,清理内存
    针对发现的内存泄漏问题,需优化代码,确保对象在不再使用时尽快释放。具体方法如下:

    • 及时清理集合:对于使用完毕的对象,及时从集合中移除。
    • 合理管理对象引用:避免长生命周期对象持有短生命周期对象引用,可使用弱引用(WeakReference)来管理。
    • 关闭资源:对于文件流、数据库连接等资源,在使用完毕后,务必调用 close() 方法关闭。
    • 移除监听器:在适当时机,移除不再需要的监听器或回调函数。
      加强监控,防患未然

如同江湖侠客需时刻警惕,程序员亦需持续监控内存使用情况,防患于未然。可使用监控工具如 Prometheus、Grafana 等,实时查看内存使用情况,及时发现异常。

滴滴滴、滴滴滴…,代码剑宗中的某一处洞府中的告警声不绝于耳,近眼望去,洞府正中央的蒲团上正坐着一位双眼紧闭身材健硕的男子,此男子的旁边还摆放着篮球、杠铃等道具,从洞府的摆布不难看出此男子平日经常锻炼,以至于他的身型较于常人更加挺拔高大。男子听到告警声睁开双眼,男子双眸中充满精光,看来此次闭关男子有了不少收获。听到警告声的男子眼神中闪过了一丝不耐烦,嘴里轻轻碎了一声,然后不紧不慢地从袖中拿出一个圆盘,此圆盘此时一直闪烁着红光,并且一直发出“滴滴滴”的声音,男子用手轻抚手中圆盘,身前映射出一个巨大光影,光影里面有一些画面跟文字,男子大概花了一刻钟时间扫描完光影里的内容。他脸上闪过一丝苦涩,然后说道:“该死的,竟然出现了内存告警”,随即只见男子双手一挥把光影打散,男子站了起来朝着旁边的一个房间走去。

而洞府中的男子就是咱们的男主“阿强”。他之前正坐在蒲团上修炼内功到一个关键时刻,不曾想被圆盘的告警打断,此时的阿强心情不是很美丽…

内存紧急处理

阿强离开洞府的第一件事情就是通过告警身份牌进入“乾坤内存法阵”查看告警的应用阵脚,阿强查看应用的内存情况跟系统的一些指标如下图所示,阿强看到这个内存水位情况就发现了不对劲。应用从晚上03:00开始到目前为止内存一直处于一个缓慢上升状态。不过此时阿强倒也没有因此慌了自己阵脚,阿强根据以前处理类似问题的经验,他先通过“乾坤内存法阵”中的应用内存Dump导出功能先将内存快照给dump下来,然后就将应用的容器进行重启的操作。

实时区间热点图
在这里插入图片描述

实时线程数
在这里插入图片描述
实时gc数量
在这里插入图片描述
实时堆内存信息
在这里插入图片描述
容器实时内存情况
在这里插入图片描述
不久,应用的快照文件就dump了下来,阿强看着dump下来的文件并没有直接去分析而是优先去询问了负责此应用的人询问了一下具体情况。2个时辰后,阿强大概从负责此应用的人口中知道了此应用的基本情况。此应用名叫G服务,是从F服务中拆出来的一个应用,拆出来的G服务的代码内容与G服务是保持一致的,但是G服务的内存表现很稳定,并没有F服务表现出来的内存缓慢爬升的情况,而G服务表现内存缓慢爬升则是随着不断提高流量灰度的一同上升的。其中F服务的一个容器内存情况大致是8台内存16G的云服务器,G服务的容器内存情况是4台8G的云服务器。还有一个值得注意的一个点则是G服务的调用链路由于处于流量切换的过程与在F服务中不同,其区别如:
在这里插入图片描述
其中橙色的线表示G服务从F服务拆分出来后多一次交互,也就是说,在流量切换灰度期间,G服务的流量入口是从F服务通过rpc接口方式接受的。

此时的阿强大概了解了G服务应用的基本情况,接下来要做的事情则是去分析内存缓慢爬升的问题,只见他拿出了一法器,此法器名叫“乾坤内存镜”,此法器的作用就是能够清晰地分析应用内存快照文文件,在使用法器有一个细节问题需要注意的是,如果通过此法器直接去打开内存快照文件,此法器会默认进行fullgc,fullgc后的快照文件如下图:
在这里插入图片描述
fullgc后的快照文件内存大小明显和实际占用不同,如果想让法器打开快照文件不尽兴fullgc,则只需要换一种打开方式,打开方式如下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
此时你应该能看到如下图的内容说明此次打开方式没有尽兴fullgc,我们只需要稍等片刻即可
在这里插入图片描述
通过这种方式打开的快照文件则是如下所示:
在这里插入图片描述
阿强看着解析出来的快照内容,此时展现出来内容是通过内存的实例的数量来进行的排序,其中,char[]占用了1412m大小的内存,粗略看下来没有什么大对象。如果是几年前的阿强,他会傻不拉几地去查看char[]实例的引用,但是此时的阿强已经不是两年前的阿强,经过时长两年半的练习,他踩过数不清的坑,经验告诉他,此时你应该看看第三个实例,阿强此时查看第三个实例的Merged outgoing references,他看到此实例的引用
在这里插入图片描述
然后再进一步跟进String的引用,除了spring的常规引用,发现logback和jackson有引用大量的字符实例。
在这里插入图片描述
在这里插入图片描述
阿强此时通过idea打开了G服务的代码,开始查看起来jackson和logback的代码使用点,2个时辰后,阿强发现了一些奇怪的日志打印,如下:

log.info("业务接口处理请求参数明文,{}, http request method:{}",
                JSON.toJSONString(request.getParams()), methodMapping.getMethod());

上面这种日志打印会将整个请求的入参都打印出来,而且一次请求类似这种打印全部请求入参的日日志大概有5~7次,而由于G服务的承载的业务请求报文都是比较大的,也就是说,每一次请求过来,这种大日子的打印会打印好几次,而这些大而全的日志大部分内容是没用的,并且每次打印生成的字符串每次都是不同的,也就是每次请求在堆内存中生成6~7个大字符对象,这种大字符对象会在堆中频繁创建,会造成youngc很频繁。而youngc过于频繁会造成很多大字符对象进入老年代,导致整个堆内存不断上升。为了验证自己的猜想,阿强尝试着删除G服务中这些大日志的打印,最终发现内存上升的情况有一定的改善(此时的内存已经不会出现缓慢爬坡的情况),但是内存表现相比较F服务还是没有那么好的,因此阿强又只能进一步去分析内存块照文件,2刻钟后,阿强在线程ThreadLocal中发现很多大char[]数组的引用,而这些ThreadLocal都是由rpc线程所持有。
在这里插入图片描述
而rpc底层的序列化正是使用的jackson,而com.fasterxml.jackson.core.util.BufferRecycler 是 Jackson 库中的一个工具类,用于高效地管理和重用缓冲区。在多线程环境中,特别是使用 ThreadLocal 时,确实有可能导致内存泄漏:

  1. ThreadLocal 的生命周期问题:ThreadLocal 变量会与线程的生命周期绑定,如果线程不被回收,ThreadLocal 变量及其引用的对象也不会被回收,可能导致内存泄漏。
  2. 缓冲区的大小和数量:如果缓冲区的大小或数量非常大,且这些缓冲区长期占用内存而不被释放,可能导致内存使用过多,从而引发内存泄漏。
  3. 线程池使用不当:在使用线程池时,如果没有正确管理线程池的生命周期和资源,可能会导致线程无法被回收,进而导致 ThreadLocal 引用的对象无法被回收。

到这里真相大白,而阿强面对涉及基础设施的改造,他有点烦躁。凡是涉及基础设施的改动,任务的难度和解决时间就会成倍增加,因为基础设施的改造流程会拉的比较长。但这个任务是一个紧急的任务,为了快速地将问题处理,那怎么能够不去改造基础设施并解决这个问题呢,阿强脑子在飞速的运转,不多时,阿强心中闪过一丝光亮,他紧皱的眉间也开始舒坦。刚刚的那一丝光亮就是快速解决任务的关键,那就是:“类加载器的双亲委派机制!!”

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

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

相关文章

TensorRT-LLM保姆级教程(三)-使用Triton推理服务框架部署模型

随着大模型的爆火,投入到生产环境的模型参数量规模也变得越来越大(从数十亿参数到千亿参数规模),从而导致大模型的推理成本急剧增加。因此,市面上也出现了很多的推理框架,用于降低模型推理延迟以及提升模型…

redis哨兵启动出现 +sdown master mymaster 192.168.x.x

场景: 搭建好哨兵之后,哨兵一启动,过了30秒就会判断master sdown,但是检查配置是没有问题。 日志: Redis-master启动日志:没看到任何异常,所以master无异常 Redis-哨兵启动日志: …

深度学习技术概览

一、深度学习技术概览 深度学习,作为机器学习的一个分支,其核心在于通过构建多层神经网络模型来模拟人脑的学习过程。与传统的机器学习算法相比,深度学习能够自动从原始数据中提取高级抽象特征,而无需人工进行复杂的特征工程。这…

Java项目实战II基于Java+Spring Boot+MySQL的网上摄影工作室(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者 一、前言 在数字化时代,摄影艺术已不再局限于传统媒介,而是借助互联网平台绽放新的光彩…

基于遗传优化算法的多AGV栅格地图路径规划matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 栅格地图表示 4.2 路径编码 4.3 目标函数 5.完整程序 1.程序功能描述 基于遗传优化算法的多AGV栅格地图路径规划matlab仿真,分别测试单个AGC的路径规划和多个AGV的路径规划…

虹科技术分享 | CAN XL总线测试与译码

CAN XL是第三代控制器局域网协议,建立在经典CAN和CAN FD网络的基础上,并支持向后兼容。它面向车载网络,使用单个差模总线连接多个控制器和传感器。由于高度的耐用性和对布线需求最小的总线拓扑结构,控制器局域网协议越来越多地进入…

虚拟社交的新时代:探索Facebook的元宇宙愿景

随着技术的不断进步,社交媒体的形态也在悄然变化。Facebook(现名Meta)正站在这一变革的前沿,积极探索元宇宙的愿景。元宇宙不仅是虚拟现实(VR)和增强现实(AR)的结合,更是…

Spring Boot房屋租赁系统:技术架构解析

2 关键技术简介 2.1 JAVA技术 Java是一种多用途并且强大的编程语言,可用于开发运行在移动设备、台式计算机以及服务器端的软件。Java已及其流行。Java只要编写一次,无论什么地方都可以运行启动[1]。 Java语言是应用很广泛的语言,用它编写出的…

【JVM原理】运行时数据区(内存结构)

JVM (Java Virtual Machine)原理 文章目录 四、运行时数据区(内存结构)4-1 线程私有区域程序计数器(program counter Register)本地方法栈(Native Method Stacks)Java 虚拟机栈&…

Python办公自动化教程(004):PDF添加水印

1.4 PDF文档水印添加 【1】安装库 pip install reportlab pip install PyPDF2【2】代码 import iofrom PyPDF2 import PdfWriter, PdfReader from reportlab.lib import pagesizes # 页面样式 from reportlab.lib.units import cm from reportlab.pdfbase import pdfmetric…

【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL68

同步FIFO 描述 请设计带有空满信号的同步FIFO,FIFO的深度和宽度可配置。双口RAM的参考代码和接口信号已给出,请在答案中添加并例化此部分代码。 电路的接口如下图所示。端口说明如下表。 接口电路图如下: 双口RAM端口说明: 端口…

828华为云征文|使用Flexus X实例集成ES搜索引擎

目录 一、应用场景 1.1 Flexus X实例概述 1.2 ES搜索引擎 二、安装相关服务 2.1 安装Elasticsearch7.17.0 2.2 安装kibana7.17.0 三、开通安全组规则 四、整体感受 4.1 Flexus X实例 4.2 使用感觉 一、应用场景 1.1 Flexus X实例概述 Flexus X实例是华为云推出的一款…

Windows内核编程基础(2)

上下文环境 应用层应用程序工作在用户模式,内核驱动程序工作在内核模式。这里的用户模式和内核模式是基于CPU的特权环来定义的,CPU提供了0环~3环(ring 0 ~ ring 3)共四个特权环,Windows操作系统使用了其中的0环和3环,0环为内核模…

【深度学习】(7)--保存最优模型

文章目录 保存最优模型一、两种保存方法1. 保存模型参数2. 保存完整模型 二、迭代模型 总结 保存最优模型 我们在迭代模型训练时,随着次数初始的增多,模型的准确率会逐渐的上升,但是同时也随着迭代次数越来越多,由于模型会开始学…

大数据-148 Apache Kudu 从 Flink 下沉数据到 Kudu

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Spring Boot房屋租赁平台:现代化解决方案

1 绪论 1.1 研究背景 中国的科技的不断进步,计算机发展也慢慢的越来越成熟,人们对计算机也是越来越更加的依赖,科研、教育慢慢用于计算机进行管理。从第一台计算机的产生,到现在计算机已经发展到我们无法想象。给我们的生活改变很…

Recaptcha2 图像识别 API 对接说明

Recaptcha2 图像识别 API 对接说明 本文将介绍一种 Recaptcha2 图像识别2 API 对接说明,它可以通过用户输入识别的内容和 Recaptcha2验证码图像,最后返回需要点击的小图像的坐标,完成验证。 接下来介绍下 Recaptcha2 图像识别 API 的对接说…

8.12DoG (Difference of Gaussians)

基本概念 不同尺度的高斯模糊图像之间的差异(DoG),用于边缘检测。函数: cv::GaussianBlur() 结合 cv::Laplacian() 或者自定义DoG实现。 在OpenCV中并没有直接提供一个名为“DoG”(Difference of Gaussians)的函数&a…

【学术会议征稿】第四届人工智能、机器人和通信国际会议(ICAIRC 2024)

第四届人工智能、机器人和通信国际会议(ICAIRC 2024) 2024 4th International Conference on Artificial Intelligence, Robotics, and Communication 第四届人工智能、机器人和通信国际会议(ICAIRC 2024)定于2024年12月27-29日…

css 自定义滚动条样式

* { scrollbar-color: auto !important; scrollbar-width: auto; } //滚动条宽高 ::-webkit-scrollbar { width: 4px; height: 4px; background: transparent; } ::-webkit-scrollbar-thumb { //滑块部分 border-radius: 5px; background-color: rgba(32, 224, 254, 1); } ::-…