Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >skywalking内存泄露排查

skywalking内存泄露排查

作者头像
龟仙老人
发布于 2020-12-15 06:45:11
发布于 2020-12-15 06:45:11
4.3K00
代码可运行
举报
文章被收录于专栏:捉虫大师捉虫大师
运行总次数:0
代码可运行

背景介绍

最近写的关于dubbo内存泄露稍微复杂了一点,很多人表示看不明白,想到之前遇到的比较简单的内存泄露问题,更容易入门,于是拿出来分享一下。

为了做微服务的熔断降级限流,引入了sentinel组件,对于sentinel引入到公司内部使用只是做了一些简单的定制化,如持久化配置规则,监控数据收集展示,后台登录权限整合等等。

在功能验证通过的情况下,也做了压测,性能符合要求,于是就推上了生产做线上灰度。刚开始没问题,直到有一天线上配置了一条降级规则,并且触发了,监控告警就炸了锅。

开始是服务出现大量慢请求,后来服务完全僵死。查看监控,慢请求很多,cpu飙升,full GC频繁,内存占满,日志中也出现了java.lang.OutOfMemoryError,可以断定是内存问题了。

问题排查

由于当时对系统的操作只有开启了降级规则,于是立马删除规则并重启,系统恢复,但并没有保存一份内存的dump文件。想着如果问题能复现就好查了,在当初的预发机器上试了一下,并没有复现。思前想去,难道跟机器有关?于是线上摘下一台机器来,配置规则,稍微压测一下,果然出现了问题。

能复现就好办,赶紧dump内存,很多人不知道怎么dump java的内存文件,可以使用jdk自带的jmap命令来dump,使用jmap dump内存时会触发一次full GC,所以线上使用要谨慎,full GC保证了dump出来内存里的对象都是存活的(无法释放)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
jmap -dump:format=b,file=dump.bin ${pid}

dump出来后的内存如果太大,可以使用tar命令压缩一下再下载到本地分析。分析工具使用eclipse的插件mat,它的官方地址如下

https://www.eclipse.org/mat/ eclipse mat

从dump文件可以看到dubbo的线程每个都占用了2%的内存,该应用设置了200个线程,理论上已经把内存撑爆了。展开一个线程看看

该dubbo线程中存在一个很大的StringBuilder对象,将其值复制出来,发现这个字符串竟然有200MB,其中只有第一行不一样,后面都是重复的字符串。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
com.alibaba.csp.sentinel.slots.block.SentinelRpcException: com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
com.alibaba.csp.sentinel.slots.block.flow.FlowException
...

查看dubbo的源码也没有发现有这个属性,只知道跟sentinel有关。

线索难以查出真相,很多时候就是这样,内存泄露问题从内存本身只能分析出一点线索,不足以找出真相,除非它是个非常简单的问题。

以经验来看,内存泄露问题都会伴随着cpu升高,因为内存不够使用触发full GC,但full GC又无法释放内存,恶性循环,所以一开始并没有去看cpu的问题。抱着试一试的态度再次复现了现场,并用jstack命令打印出线程栈,想看看除了GC线程外还有没有线程占用了cpu

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
jstack ${pid} > jstack.txt

果然发现了问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"DubboServerHandler-127.0.0.1:20880-thread-200" #532 daemon prio=5 os_prio=0 tid=0x00007f264c1f8000 nid=0x581a waiting for monitor entry [0x00007f25bae09000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at org.apache.skywalking.apm.agent.core.context.util.ThrowableTransformer.printExceptionInfo(ThrowableTransformer.java:57)
    at org.apache.skywalking.apm.agent.core.context.util.ThrowableTransformer.convert2String(ThrowableTransformer.java:34)
    at org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan.log(AbstractTracingSpan.java:152)
    at org.apache.skywalking.apm.agent.core.context.trace.ExitSpan.log(ExitSpan.java:112)
    at org.apache.skywalking.apm.agent.core.context.trace.ExitSpan.log(ExitSpan.java:38)
    at org.apache.skywalking.apm.plugin.dubbo.DubboInterceptor.dealException(DubboInterceptor.java:124)
    at org.apache.skywalking.apm.plugin.dubbo.DubboInterceptor.handleMethodException(DubboInterceptor.java:115)
    at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:97)
    at ...

从堆栈发现是skywalking一直在执行Arrays.copy,skywalking简单来说是一款采集分布式调用链的组件,它的原理是针对java代码中的“调用“处进行字节码增强,达到对业务零侵入获取调用信息,github地址如下

https://github.com/apache/skywalking skywalking

这就解释了为什么压测时发现不了这个问题,因为压测机没有部署skywalking。

找到这个堆栈基本就算问题解决了,接着去看代码就行。

在skywalking上报exception时会把栈都放到StringBuilder中,但是这里出现了bug,在stackTrace为空的时候,就会出现循环append,直到内存耗尽

同时,也在github上找到了对这个bug的修复,这里是使用的skywalking版本太老导致

https://github.com/apache/skywalking/pull/2931 skywalking bug修复

这个bug,对于stackTrace不为空的trace时,只能记录两层exception,对于stackTrace为空的trace直接OOM,也就是说sentinel因为限流降级抛出的异常stackTrace为空。这里给出sentinel的BlockException部分代码,它重写了fillInStackTrace方法,直接返回this。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class BlockException extends Exception {
  @Override
  public Throwable fillInStackTrace() {
      return this;
  }
  ...
}

这个方法默认实现是借助native方法,这里重写后直接返回this,则是不记录栈信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Fills in the execution stack trace. This method records within this
 * {@code Throwable} object information about the current state of
 * the stack frames for the current thread.
 *
 * <p>If the stack trace of this {@code Throwable} {@linkplain
 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 * writable}, calling this method has no effect.
 *
 * @return  a reference to this {@code Throwable} instance.
 * @see     java.lang.Throwable#printStackTrace()
 */
public synchronized Throwable fillInStackTrace() {
    if (stackTrace != null ||
        backtrace != null /* Out of protocol state */ ) {
        fillInStackTrace(0);
        stackTrace = UNASSIGNED_STACK;
    }
    return this;
}

private native Throwable fillInStackTrace(int dummy);

我们也知道如果异常栈太深会影响性能,对于sentinel这种需要非常高性能的组件直接去掉异常栈信息不失为一种优化性能的“黑科技”。这也给我们一个提醒,压测系统性能时不光要考虑正常情况,也需要考虑异常情况。如果压测一个系统能抗住5000qps的正常请求,抛出异常只能承受2000qps,那么正常压测出的5000在实际生产中可能是达不到的。

总结

  • 内存泄露问题伴随着cpu,错误率,GC频繁等问题
  • 内存泄露最重要的是拿到现场内存dump文件,并用工具结合源码分析
  • 如果第二条解决不了问题,则需要寻找新的突破口,比如jstack等
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 捉虫大师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
Lynis 是Unix/Linux等操作系统的一款安全审计工具,它可以发现基于Linux系统中的恶意软件和安全漏洞。Lynis是免费开源的服务器审计工具,一旦审计完成,我们可以审查结果、警告和建议,然后我们可以根据它实现我们的安全策略。它将显示一个报告,该报告可以被分成几个部分。
民工哥
2022/10/27
1.1K0
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
如何在Ubuntu 16.04上使用Lynis执行安全审计
Lynis是一个基于主机的开源安全审计应用程序,可以评估Linux和其他类型UNIX操作系统的安全配置文件和状态。
黑色技术
2018/07/24
2.7K0
CentOS7下使用开源安全审计工具Lynis
Lynis是一款Linux系统的安全审计以及加固工具,能够进行深层次的安全扫描,其目的是检测潜在的时间并对未来的系统加固提供建议。
yuanfan2012
2020/11/26
1.8K0
如何有效阻止 90% 服务器攻击
很多服务器时不时地被黑掉。因此,我决定编写一个简短的教程,向您展示如何轻松地保护您的Linux服务器。
网罗开发
2021/02/26
1.7K0
Linux系统常用基础命令
touch -t 0712250000 file1 修改一个文件或目录的时间戳 - (YYMMDDhhmm)
用户8418197
2021/03/27
1.5K0
安全审计报告问题:安全审计报告生成失败,无法分析
是山河呀
2025/02/09
1860
如何在 Centos8 中安装 Lynis审计工具
Lynis 还附带一些审计配置文件,该文件确定或说明应如何执行安全审计。配置文件位于 /etc/lynis 目录中。
用户9239730
2021/11/29
3860
安全审计工具选择问题:安全审计工具选择不当,无法满足需求
是山河呀
2025/02/09
1420
20个可能你不知道Linux网路工具
如果要在你的系统上监控网络,那么使用命令行工具是非常实用的,并且对于 Linux 用户来说,有着许许多多现成的工具可以使用,如: nethogs, ntopng, nload, iftop, iptraf, bmon, slurm, tcptrack, cbm, netwatch, collectl, trafshow, cacti, etherape, ipband, jnettop, netspeed 以及 speedometer。 鉴于世上有着许多的 Linux 专家和开发者,显然还存在其他的网络
小小科
2018/05/04
1.7K0
20个可能你不知道Linux网路工具
lynis安装和扫描Linux的安全漏洞
  今天客户的服务器出了点问题需要排查具体的原因,在德国朋友的建议下用Lynis进行扫描,Lynis是Linux系统中的审计工具,能够对Linux系统的安全进行检测,在对系统进行扫描检测后,会生成安全报告。如何安装呢?随ytkah一起来看看
ytkah
2019/11/26
1.3K0
你知道吗,Artifactory还可以管理SUSELinux系统的依赖
提到SUSE系统大家应该都用过,尤其是在金融领域。大部分都是使用SUSELinux系统。当SUSE系统缺少组件时,安装也是相当的麻烦。
JFrog杰蛙科技
2020/12/04
8290
你知道吗,Artifactory还可以管理SUSELinux系统的依赖
Airgorah:一款功能强大的WiFi安全审计工具
Airgorah是一款功能强大的WiFi安全审计工具,该工具可以轻松发现和识别连接到无线接入点的客户端,并对特定的客户端执行身份验证攻击测试,捕捉WPA握手包,并尝试破解接入点的密码。在该工具的帮助下,广大研究人员可以对无线接入点和客户端的安全性进行检测和验证。
FB客服
2024/04/01
2970
Airgorah:一款功能强大的WiFi安全审计工具
Linux系统中安装及管理程序的最佳实践与教程
hide
2025/04/27
1800
Linux系统中安装及管理程序的最佳实践与教程
浅谈Linux下dpkg、apt-get、yum和rpm命令的区别
小编最近一直进行国产化输入法测试,国产化系统基本上都是基于Linux搭建来的,不同系统安装输入法的命令也是不一样;比如uos(统信)系统用dpkg或者apt-get来安装,而中标麒麟则是用yum或者rpm来安装,那么它们到底有什么区别那?
用户5521279
2020/12/11
7.9K0
浅谈Linux下dpkg、apt-get、yum和rpm命令的区别
系统漏洞:系统存在已知的安全漏洞
使用强制访问控制系统(如 SELinux 或 AppArmor)来增强系统安全性。
是山河呀
2025/02/06
1460
安全补丁管理
使用审计工具(如 auditd)记录系统活动,确保补丁管理过程的透明性和可追溯性。
是山河呀
2025/02/03
1310
安全审计问题:安全审计工具使用不当,导致审计数据不准确
示例:编辑 /etc/logrotate.d/audit 文件,设置日志轮转策略:
是山河呀
2025/02/06
3380
5 种 Linux 安装包管理工具中文手册!抓紧看,别再说不会了,丢人。。。
包管理系统除了安装软件外,它还提供了工具来更新已经安装的包。包存储库有助于确保你的系统中使用的代码是经过审查的,并且软件的安装版本已经得到了开发人员和包维护人员的认可。
民工哥
2022/10/27
1.2K0
5 种 Linux 安装包管理工具中文手册!抓紧看,别再说不会了,丢人。。。
Linux软件包管理:yum和apt比较
📌 猫头虎博主在此! 在Linux世界中,软件包管理是一项基本技能。不同的发行版使用不同的包管理工具,而yum和apt是其中最受欢迎的两个。这篇文章将为你详细解析这两个强大的工具,帮助你更好地理解它们的优势和适用场景。当然, 我在文章中融入了一些热门关键词,确保每一位Linux爱好者都能找到这篇宝藏文章。与我一同,探索Linux软件包管理的奥秘!
猫头虎
2024/04/09
7040
【Linux探索学习】第六弹——Linux的工具(一):Ubuntu系统下的软件包管理器
注意:本文是所讲解的内容是在Ubuntu系统下进行操作的,centos系统下相关操作略有不同
GG Bond1
2024/10/19
2410
【Linux探索学习】第六弹——Linux的工具(一):Ubuntu系统下的软件包管理器
推荐阅读
相关推荐
超牛逼!这款轻量级 Linux 系统自动安全审计工具真强大
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验