V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wxd21020
V2EX  ›  Java

Linux 内存使用率缓慢增长原因排查

  •  
  •   wxd21020 · 276 天前 · 4669 次点击
    这是一个创建于 276 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:

    Linux 内存使用率缓慢增长排查,目前有一台服务器,上面部署了 17 个微服务应用,24G8C 的配置,所有应用启动后内存占用率在 45%左右,经过一个月的运行后内存会涨到 75%左右,然后服务器就 hung 住了,连 ssh 都无法连接,已经出现过两次了。

    目前排查方案:

    • 方案 1:将所有应用的 jvm 参数(包括 heap 、noheap 、codecache 、metaspace 、eden space 、old gen 、GC 、Thread )等都存储监控,未发现异常
    • 方案 2:使用阿里 arthas 对各个应用进行查看,也未发现异常

    请问大佬们这种情况改从哪个方向再去排查一下。 目前即使向定位原因。

    接下来会将应用拆分放到多台服务器上。

    63 条回复    2023-08-04 13:52:33 +08:00
    ricwangcom
        1
    ricwangcom  
       276 天前
    微服务的日志把硬盘挤爆了?
    diagnostics
        2
    diagnostics  
       276 天前
    ssh 连不上和内存没多大关系,SSH 后无法用 tab 补全那就是磁盘不足
    wxd21020
        3
    wxd21020  
    OP
       276 天前
    @ricwangcom 磁盘没爆,内存爆了
    wxd21020
        4
    wxd21020  
    OP
       276 天前
    @diagnostics 我感觉是没内存分配了所以 ssh 连不上了,因为重启机器后我查看了所有应用的日志,错误信息都是 OOM ,且没有内存创建 thread
    Weixiao0725
        5
    Weixiao0725  
       276 天前
    按照进程监控内存?这种问题肯定先定位哪个程序引起的问题
    mineralsalt
        6
    mineralsalt  
       276 天前
    内存不可能凭空消失吧, 找到占用内存最多的进程, 排查它不就好了么
    LindsayZhou
        7
    LindsayZhou  
       276 天前
    用 cgroup 限制一下各个服务的内存大小?
    至少不影响服务器本身的运行。
    wxd21020
        8
    wxd21020  
    OP
       276 天前
    @Weixiao0725 最近使用 top 隔几个小时我就会去看一遍,基本上有几个应用一天会长 0.1%,这是目前定位的最后手段了。
    wxd21020
        9
    wxd21020  
    OP
       276 天前
    @mineralsalt 前五个应用占用内存差不太多,5.1,4.9,4.9,4.8,4.6
    wxd21020
        10
    wxd21020  
    OP
       276 天前
    @LindsayZhou java 服务启动的时候倒是设置了 Xmx 。
    Jackliu
        11
    Jackliu  
       276 天前
    内存泄漏
    allenzhangSB
        12
    allenzhangSB  
       276 天前
    看下是不是堆外内存泄露了
    llrasd
        13
    llrasd  
       276 天前
    百度下 glibc 内存泄漏 ;之前我们有这个问题
    wzy44944
        14
    wzy44944  
       276 天前
    服务器没有配置 OOM-kill 吗?可以先配一下,等有进程 oom 重启后,看下 dmesg 就知道是哪个了。可以用 cgroup 限制内存。不过你这个是多个微服务,也可以用一个 docker 跑所有微服务,容器启动参数加--memory 18G ,限制总内存在 18G ,这样 docker 内会 oomkill ,不影响你 ssh 到主机做排查。要复现就在 docker 启动参数再加个 --oom-kill-disable=true
    Ggmusic
        15
    Ggmusic  
       276 天前 via iPhone   ❤️ 1
    @wxd21020 划重点:没有内存创建线程。这种情况下系统的内存是足够的,但是你没法起新线程了,估计是有个 java 进程持续不断创建线程,可以监控下各个进程创建的线程数。https://www.bmc.com/blogs/outofmemory-java-threads/
    crsmk01
        16
    crsmk01  
       276 天前
    贴下 os 版本、jvm 版本、相关的内存参数(堆、栈、Directory Memory 、Code Cache 等)
    1 、是不是在用 docker / k8s 在运行这些微服务应用 ?如果是,贴下 docker 分配的内存 or 微服务 pod 的 request / limit mem
    2 、如果只是一个主机直接跑 java 进程,可以观察一下出问题的时候 sys cpu 是否很高,挑占用内存较高的前三个进程,用 pmap -xp <jvm_pid> 看下结果
    securityCoding
        17
    securityCoding  
       276 天前 via Android
    优先看系统日志找出有问题的进程
    popvlovs
        18
    popvlovs  
       276 天前
    从现象上看,比较赞成#15 的推测,首先线程创建是要消耗内存的(只创建不释放也算一种泄漏,现象符合),另外创建的太多达到操作系统上限后,也会导致操作系统 hung 住无响应
    quan7u
        19
    quan7u  
       276 天前
    监控主机资源,看看文件描述符的增长趋势
    hsymlg
        20
    hsymlg  
       276 天前
    看进程,jvm 监控的里面内存正常,并不代表 java 进程内存是正常的,我记得 java8 的大多数场景 jvm 一旦从 os 那边获取内存,就不愿意会还回去了。可以看看这个 https://stackoverflow.com/questions/30458195/does-gc-release-back-memory-to-os
    leonshaw
        21
    leonshaw  
       276 天前
    Xmx 加起来有多少
    Rv9H
        22
    Rv9H  
       276 天前
    cat /proc/meminfo 是啥?
    echo m > /proc/sysrq-trigger dmesg 输出是啥

    先分析操作系统这边是哪种类型的页面,看是用户态还是内核态的页面
    如果是用户态 cat /proc/<pid>/smap_rollup 分析是哪个进程
    leonshaw
        23
    leonshaw  
       276 天前
    OOM 日志是指 Java 的还是系统的?哪个进程的或者 kill 了哪个进程?
    crsmk01
        24
    crsmk01  
       276 天前
    另外,这些微服务应用用的什么系统用户( root or 普通用户)在跑的 ?有没有监控过操作系统整理的文件描述符、总线程数?
    /proc/sys/fs/file-nr
    /proc/sys/kernel/pid_max
    /proc/sys/kernel/threads-max (结合所有 /proc/<pid>/status | grep -i Threads 总和看下)
    hahastudio
        25
    hahastudio  
       276 天前
    不光要留意线程数,还要看看进程数
    ElvisLiao
        26
    ElvisLiao  
       276 天前
    建议排查下堆外内存泄漏,如果不存在 gzip 之类的流没有关闭的话,我看你的症状大概率是 linux 的 ARENA 区导致的。
    pmap -x <pid>|sort -gr -k2 |less ,看看是不是存在大量的 64M 的内存块。是的话,机器参数强制设置一下 export MALLOC_ARENA_MAX=1
    wxd21020
        27
    wxd21020  
    OP
       276 天前
    @wzy44944 生产环境,没办法大动了,目前就是想着找到原因后将服务分到别的服务器上。
    wxd21020
        28
    wxd21020  
    OP
       276 天前
    @Ggmusic 线程数我也监控了,我目前是看 current 、deadlocked 、timed_waiting 、waiting 类型的线程,目前看没有出现大批量的线程。
    wxd21020
        29
    wxd21020  
    OP
       276 天前
    @quan7u 你说的是 open file descriptors 吗?这个我一直没注意他是用来干什么的。
    wxd21020
        30
    wxd21020  
    OP
       276 天前
    @hsymlg 感谢大佬,我研究一下。
    wxd21020
        31
    wxd21020  
    OP
       276 天前
    @leonshaw 加起来有 10G 左右吧
    wxd21020
        32
    wxd21020  
    OP
       276 天前
    @Rv9H 我去查一下
    wxd21020
        33
    wxd21020  
    OP
       276 天前
    @leonshaw java 服务的,报 OOM 的时候是 17 个服务大概在相同的时间段爆出来的,爆出来的时候 ssh 都连不上去了,没办法 kill 了
    wxd21020
        34
    wxd21020  
    OP
       276 天前
    @tdy218 普通用户,你说的这个目前还没监控,我监控研究一下。
    wxd21020
        35
    wxd21020  
    OP
       276 天前
    @ElvisLiao OK ,我去查一下
    wxd21020
        36
    wxd21020  
    OP
       276 天前
    @tdy218 这个/proc/<pid>/status 下的 thread 我统计过,17 个服务每个都没超过 100.
    opengps
        37
    opengps  
       276 天前   ❤️ 1
    linux 不熟,分享下 windows 平台的经验:对于操作系统,内存的概念可以展开几种分类,你现在排查疑似内存泄漏的目的,需要从“提交内存”下手,而不是只看“专享内存”,一看这俩内存的差额,二看启动时候和泄漏后的差额,对比出来时那个进程,然后再去 dump 分析具体泄漏的线程或者对象
    OblivionStaff
        38
    OblivionStaff  
       276 天前
    磁盘 iops 正常吗
    zhujinlong
        39
    zhujinlong  
       276 天前
    先从操作系统层面检查哪些进程消耗了最多的内存
    me1onsoda
        40
    me1onsoda  
       276 天前
    @wxd21020 #33 都报 oom 了,怎么不分析 dump 文件,gc 日志
    NoKey
        41
    NoKey  
       276 天前
    系统自身没啥问题的情况下,持续监控应用的内存占比,如果应用持续上升,看哪个上升的最多,然后分析呗。占用内存有两种情况,一种是服务有问题,就是内存泄露了,要找出来解决掉;一种是,他就是在一定时间后,要占这么多,占到一定峰值后,不会继续增加,那么这就是看服务自身是不是就需要比较大内存,单独给一台服务器。
    flexbug
        42
    flexbug  
       276 天前
    不如装个 process exporter 监控下每个应用占用
    AlohaV2
        43
    AlohaV2  
       276 天前
    是不是内存碎片太多了? buddyinfo 看一下
    anticipated
        44
    anticipated  
       276 天前
    先加点虚拟内存,防止死机,然后写脚本,记录一下,每几分钟输出各个资源的使用日志,大概几个小时就能找到问题了。
    tin3w5
        45
    tin3w5  
       276 天前
    听起来像是内存泄漏,从经验上来看,大概率是 JVM 的锅。早些年在公有云厂商,大部分的 OOM case 都是开发的 Java 代码写的太烂导致 JVM 内存泄漏。
    想起了之前在公有云厂商的时候,几百个 VIP 客户,用 Java 开发业务的能占一大半。同样是用 Java 开发的,那么几家公司就是经常 OOM 。你帮他诊断出来就是 JVM OOM 了,个别那一两家就非要跟你扯“我这代码在自己的笔记本上就不 OOM ,在你家公有云上就 OOM ,所以就是你家公有云的问题”。还要拉着你一起看 Java 代码……MMP 老子要是 Java 开发那么精通,老子第一个去你们公司把你给替了。
    所以之前我们经常吐槽,Java 程序员的优劣,写小项目看不出来,写大项目就能看出来了。
    wxd21020
        46
    wxd21020  
    OP
       276 天前
    @me1onsoda 分析了,dump 和 gc 都分析了,没发现问题,现在包 OOM 是因为服务器没内存供使用了,而不是 java 服务导致的 OOM
    wushenlun
        47
    wushenlun  
       276 天前 via Android
    是不是 ubuntu20.04 和 22.都有这种 Bug ,,应该是跟平台+系统有关系,我现在跑 fedora 了
    wxd21020
        48
    wxd21020  
    OP
       276 天前
    @wushenlun 我用的红旗
    wxd21020
        49
    wxd21020  
    OP
       276 天前
    @tin3w5 听起来想内存泄露,但是又不想内存泄露。。。。
    bli22ard
        50
    bli22ard  
       276 天前
    每个应用配置 -Xmx ,所有应用-Xmx 相加 < 系统启动内存 - 4G 。 这样让出现 oom , 是 jvm 自己,而不是 os oom 。这样就能找到有问题的那个系统, 然后再这个系统 oom 的时候, 使用 jmap dump 内存,进行分析,看看是哪里发生了问题, 是内存变量, 还是网络连接(包括中间件网络连接)。
    qoo2019
        51
    qoo2019  
       276 天前
    @wxd21020 看下 NUMA ,是不是这块有状况
    yesh0
        52
    yesh0  
       276 天前
    可能可以先配置一个 earlyoom 或者类似的来在临近 oom 的时候把进程杀掉避免 ssh 都上不去的情况?( Linux 内核的 oom killer 不太行,会在真正开杀之前丢掉硬盘缓存卡好长一段时间。)然后就是看 earlyoom 日志看看哪个进程被杀掉了针对性看一下吧。

    earlyoom: https://github.com/rfjakob/earlyoom
    ffw5b7
        53
    ffw5b7  
       276 天前 via Android
    Dump 的文件是不是很小?程序使用了 NIO 吗,是的话看下直接内存
    vivisidea
        54
    vivisidea  
       276 天前
    可能是 kernel pagecache ,我们之前有过类似的问题,跟 jvm 啥的没关系

    echo 3 > /proc/sys/vm/drop_caches

    试试在内存比较高的时候执行这个命令(需要 root 权限)
    cheng6563
        55
    cheng6563  
       276 天前
    ssh 连不上,用云控制台后台的远程连接可以直接连到虚拟机的屏幕上,这时说不定就能连了。
    atlantic2477
        56
    atlantic2477  
       276 天前
    1 、确认应用是否有内存泄漏
    atlantic2477
        57
    atlantic2477  
       276 天前
    1 、确认应用是否有内存泄漏
    2 、应用没有内存泄漏的话排查下内核 slab 各对象内存占用情况

    之前遇到过类似的情况,应用没有内存泄漏,但是容器内存缓慢增加。最后发现是有一个应用每次处理请求都会在临时文件下创建文件然后删除,随着请求量增加导致 slab 中 dentry 对象占用过多内存增加
    wxd21020
        58
    wxd21020  
    OP
       276 天前
    @bli22ard 现在 24G 的服务器内存,Xmx 加起来 10G 左右吧
    wxd21020
        59
    wxd21020  
    OP
       276 天前
    @vivisidea 没 root 权限。。。
    wxd21020
        60
    wxd21020  
    OP
       276 天前
    @atlantic2477 研究一哈,
    @yesh0 生产环境不敢乱搞
    @qoo2019 等我研究一哈
    @cheng6563 目前出现状况就是只能通云控制台进去后重启机器
    感谢兄弟们
    vivisidea
        61
    vivisidea  
       276 天前
    @wxd21020 如果是生产,建议还是把业务流量切走再操作,或者低峰期,drop cache 有一定概率会导致系统 hang 个几秒~几十秒不等,也可能毫无感知

    没有 root 权限就算了。。
    crsmk01
        62
    crsmk01  
       268 天前
    1 、上面说分析 dump 文件的同学都没审题,LZ 说了是 java.lang.OutOfMemoryError: Unable to create new native thread ,而且 LZ 像是做主机运维的 ?不要只盯着服务器内存,可能有误导性;
    2 、可以看下 https://www.cnblogs.com/rexcheny/p/9502248.html 这篇文章;
    3 、昨晚一个客户遇到了一个几乎一样的问题,还没完全排查完,但看第 2 点的文章就比较有用。
    wxd21020
        63
    wxd21020  
    OP
       267 天前
    @tdy218 java 后端,看了你提示的文章,感觉有点相似的味道,前几天我查了到一个服务一直在起线程,这个服务是上传文件服务,里边有个获取进度的功能,没上传一个文件都会起一个 thread ,每个 1S 去查一次进度条。导致这个服务的 timed_waiting 线程达到了一万大几。最近我把这个地方优化了一下,还在观察别的服务。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2996 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 14:14 · PVG 22:14 · LAX 07:14 · JFK 10:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.