首页 > 系统相关 >一次压力测试引起的内存溢出排查(apollo)

一次压力测试引起的内存溢出排查(apollo)

时间:2023-11-06 17:24:08浏览次数:32  
标签:SpringValueRegistry SpringValueProcessor 配置 排查 bean 内存 apollo

项目从nacos配置中心适配apollo后,线上压测运行4个小时,内存告警,FGC达到了惊人的100+次

拿到压测dump文件使用mat分析发现com.ctrip.framework.apollo.spring.property.SpringValueRegistry占比达到91.68%,很明显SpringValueRegistry导致的内存泄漏

 找到了导致内存泄漏的原因,那么为什么会导致内存泄漏呢

1、SpringValueRegistry是apollo保存配置的注册类,实现了配置的热更新

  在 Apollo 控制台进行配置修改并发布后,对应的 client 端拉取到更新后,会调用到 com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener#onChange 方法

        在调用 onChange 会收到对应的修改的配置信息 ConfigChangeEvent, 其中包含改动的 key 和 value, 则改动流程如下

    根据改动的配置的 key 从 springValueRegistry 找到对应的关联到这个 key 的 Spring Bean 信息,如果找不到则不处理

    根据找到的 Spring Bean 信息,进行对应关联配置的更新

2、SpringValueRegistry的配置时如何注册的

 

  在启动的时候,apollo客户端会注册SpringValueProcessor到spring容器中,下面是SpringValueProcessor的类图,BeanPostProcessor的实现类ApolloProcessor中对postProcessAfterInitialization方法进行了实现,该方法是Bean生命周期中最后一个执行的方法,所以这里处理bean的属性注入是最终的

   SpringValueProcessor中具体实现了Apollo对Value注解的处理,对value字段进行判断,并注册到自己的处理类中去处理,源码如下,只会对@Value注解注解到的属性和方法进行处理

 3、apollo中属性注册的背景上述做了简单的介绍,在我们的项目是如何引起内存泄漏的呢

  

  在项目存在了很多获取prototype模式bean的逻辑,在这些bean存在比较多的@Value注解,这就导致了只要获取一次这些bean都要执行一次springbean的整个生命周期流程,必然就会执行到SpringValueProcessor,也就会解析bean中的@Value注解的属性值并注册到SpringValueRegistry中。

  在300并发下大概每秒会创建3000个SpringValue,随着时间的推移会有越来越多的SpringValue对象被创建,占用了大量的内存。虽然SpringValueRegistry中定时清理过期的策略,但是在高并发下也于事无补,最后导致大量的FGC,系统卡顿,MQ消息堆积。

解决方法:在我们项目中没有使用配置热更新的策略,所以修改方案也很简单直接重写apollo中ConfigPropertySourcesProcessor类去掉SpringValueProcessor的注册,阻止后续逻辑的执行。

修复后:压测,FGC次数正常,内存使用正常

 

 

 

标签:SpringValueRegistry,SpringValueProcessor,配置,排查,bean,内存,apollo
From: https://www.cnblogs.com/banzhuandang/p/17813206.html

相关文章

  • Linux下内存buff/cache占用过多问题解决
    在Linux下经常会遇到buff/cache内存占用过多问题,如果buff/cache占用过大的,free空闲内存就很少,影响使用;通常内存关系是:普通机器:total=used+free虚拟机器:total=used+free+buff/cache这个时候可以看到buff/cache占用的内存非常大,这个时候可以使用一下命令去清除一下cache内存echo1>......
  • 用户态内存映射
    内存映射不仅仅是物理内存和虚拟内存之间的映射,还包括将文件中的内容映射到虚拟内存空间。这个时候,访问内存空间就能够访问到文件里面的数据。而仅有物理内存和虚拟内存的映射,是一种特殊情况。对于堆的申请来讲,mmap是映射内存空间到物理内存。如果一个进程想映射一个文件到自己的......
  • JavaScript内存管理——隐藏类
    根据JavaScript所在的运行环境,有时候需要根据JavaScript引擎采取不同的性能优化策略。如果代码非常注重性能,那么隐藏类对我们是非常重要的。比如以下的代码:functionUser(){this.name="UserName";}letuser1=newUser();leruser2=newUser();在上面的代码中......
  • python的内存泄漏及垃圾回收机制
    python内存泄漏的几种场景: 一,如果打开一个文件,不关闭,是不是就是内存泄漏了? 在Python中,打开的文件对象会一直存在内存中,直到显式地关闭文件或者程序结束时才会被清理。因此,如果打开了一个文件但没有关闭它,那么这个文件对象会一直占用内存,导致内存泄漏。为了避免内存泄漏问题......
  • 内存分配
    arena这块区域最大,明显就是用来存放我们最终的对象,里面分成了一个个8K大小的房间,每个房间我们称为page。(这里虽然写了它是512G,但是你心里要有B数,你电脑根本没这么大的内存,其实操作系统只是给了你地址而已)同时几个page组合在一起的大房间又叫做mspan(这个是golang中内存管理的基本......
  • 对象内存图的过程
     单一对象1.由于TestStudent中含有main方法,因此TestStudent类先以字节码形式进入方法区,里面包含main方法2.虚拟机调用该类中的main方法,main方法进入栈内存中3.main方法中先创建对象stu,调用了student类,Student类字节码文件进入方法区4.创建了对象stu,在堆内存中开辟对象stu......
  • JavaScript内存管理
    在使用垃圾回收的编程环境中,开发者通常无须关心内存管理。不过,JavaScript运行在一个内存管理与垃圾回收都很特殊的环境。分配给浏览器的内存通常比分配给桌面软件的要少很多,分配给移动浏览器的就更少了。这更多出于安全考虑而不是别的,就是为了避免运行大量JavaScript的网页耗......
  • 云服务器的CPU利用率,外网出带宽使用率,内存利用率,磁盘利用率
    云服务器的CPU利用率、外网出带宽使用率、内存利用率和磁盘利用率是用于监测服务器性能和资源使用情况的关键指标,它们各自代表不同方面的服务器运行状态:CPU利用率:CPU(中央处理单元)利用率表示服务器的处理器单元的使用情况。它表示服务器上正在运行的进程或任务对CPU资源的占用程度......
  • 全网首发 Python3 实现快读(按字符读入(省内存专用
    全网首发Python3实现快读(按字符读入(省内存专用来源:https://www.luogu.com.cn/discuss/724761此题卡内存,如果按照Python常用的input().split()方法会MLE。因为input()一次读入大量字符串,占用内存极大。于是打算按照C++的快读逻辑写一个Python3的快读。然而并没有......
  • linux使用top命令java进程占用65%内存和160%CPU,是因为什么咋解决?
    Java进程占用大量内存和CPU的原因可能有多种,以下是一些可能的原因和解决方法:内存泄漏:Java应用程序可能存在内存泄漏,即未正确释放不再使用的内存。您可以使用Java内存分析工具(如VisualVM、MAT等)来检测和分析应用程序的内存使用情况,并查找潜在的内存泄漏问题。一旦发现内存泄漏,您可以......