暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

排查Linux下内存占用过高但无法找到对应内存占用进程的问题【测试成功】

巴韭特锁螺丝 2023-10-09
271

一、问题背景

    某项目运行内存占用异常。

    [root@JiJian bakend]# free -m
    total used free shared buffers cached
    Mem: 15886 15431 455 24 34 2461
    -/+ buffers/cache: 12934 2951
    Swap:         8071          2       8069

    二、问题排查

    1、查询进程内存占用情况,并排序,未发现异常:

    ps aux --sort=-%mem | awk '{print $2, $6/1024 " MB", $11}' | head -n 11

      [root@JiJian bakend]#   ps aux --sort=-%mem | awk '{print $2, $6/1024 " MB", $11}' | head -n 11
      PID 0 MB COMMAND
      1159 765.434 MB usr/lib/jvm/java-1.8.0-amazon-corretto//bin/java
      2964 503.453 MB opt/kaspersky/kesl/libexec/kesl
      5057 394.562 MB usr/sbin/mysqld
      3838 42.2266 MB opt/kaspersky/klnagent64/sbin/klnagent
      2951 34.9102 MB usr/bin/Xorg
      3827 32.3945 MB opt/kaspersky/klnagent64/sbin/klnagent
      2871 29.1055 MB usr/bin/python
      2865 27.4727 MB usr/bin/python
      3741 27.1797 MB /temp/YLMonitor/YLMonitor
      639 26.4492 MB /usr/lib/systemd/systemd-journald


      2、查询特定进程的虚拟内存占用情况

      ps -p 1159 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'

        [root@JiJian bin]# ps -p 1159 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
        765.301 MB 10326.3 MB /usr/lib/jvm/java-1.8.0-amazon-corretto//bin/java
        [root@JiJian bin]# ps -p 2964 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
        503.496 MB 1311.21 MB /opt/kaspersky/kesl/libexec/kesl
        [root@JiJian bin]# ps -p 5057 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
        394.562 MB 1608.03 MB /usr/sbin/mysqld
        [root@JiJian bin]# ps -p 3741 -o rss,vsz,cmd --sort=-rss,-vsz --no-headers | awk '{print $1/1024,"MB",$2/1024,"MB",$3}'
        27.1797 MB 709.848 MB /temp/YLMonitor/YLMonitor

            可以看到,存在某java程序占用虚拟内存超过10G,该进程或许存在问题。

        三、相关措施【待验证】

        Java进程占用的内存过大,可以考虑以下一些优化措施:

        1. 调整堆内存大小:通过修改Java虚拟机的-Xms
          -Xmx
          参数来调整堆内存大小。减小堆内存大小可以降低内存占用,但需要确保应用程序仍能正常运行。可以通过监控应用程序的内存使用情况来进行调整。

        2. 检查代码:分析应用程序代码,查找内存泄漏或不必要的对象引用。确保在使用完对象后将其及时释放,以避免内存泄漏。

        3. 选择合适的垃圾收集器:根据应用程序的性能需求选择适当的垃圾收集器。某些垃圾收集器可能会更有效地管理内存,并减少内存占用。

        4. 使用内存分析工具:使用工具如Java VisualVM、MAT(Memory Analyzer Tool)等来分析内存使用情况,识别内存泄漏和性能瓶颈。

        5. 减少线程数量:减少不必要的线程和线程池的使用,因为每个线程都会占用一定的内存。

        6. 优化数据结构:选择合适的数据结构和集合类型,以减少内存占用。

        7. 升级到更高版本的Java:一些Java版本可能会提供更好的内存管理和性能优化,考虑升级到最新的Java版本。

        8. 考虑使用压缩类指针:Java 8及更高版本支持使用压缩类指针来减小元数据(Metaspace)的内存占用。

        9. 定期进行性能测试和监控:持续监控应用程序的内存使用情况,并定期进行性能测试,以确保内存占用在可接受范围内。


        四、临时解决、待观察【测试成功】

        1、先查看内存信息:cat /proc/meminfo

          [root@JiJian ~]# cat /proc/meminfo
          MemTotal: 16267700 kB
          MemFree: 2694716 kB
          MemAvailable: 3140684 kB
          Buffers: 35500 kB
          Cached: 749144 kB
          SwapCached: 1328 kB
          Active: 1662432 kB
          Inactive: 985644 kB
          Active(anon): 1231376 kB
          Inactive(anon): 657568 kB
          Active(file): 431056 kB
          Inactive(file): 328076 kB
          Unevictable: 0 kB
          Mlocked: 0 kB
          SwapTotal: 8265724 kB
          SwapFree: 8263416 kB
          Dirty: 0 kB
          Writeback: 0 kB
          AnonPages: 1862316 kB
          Mapped: 366572 kB
          Shmem: 25508 kB
          Slab: 121064 kB
          SReclaimable: 49432 kB
          SUnreclaim: 71632 kB
          KernelStack: 9792 kB
          PageTables: 66476 kB
          NFS_Unstable: 0 kB
          Bounce: 0 kB
          WritebackTmp: 0 kB
          CommitLimit: 16399572 kB
          Committed_AS: 2940700 kB
          VmallocTotal: 34359738367 kB
          VmallocUsed: 181448 kB
          VmallocChunk: 34346814608 kB
          HardwareCorrupted: 0 kB
          AnonHugePages: 1224704 kB
          HugePages_Total: 0
          HugePages_Free: 0
          HugePages_Rsvd: 0
          HugePages_Surp: 0
          Hugepagesize: 2048 kB
          DirectMap4k: 219072 kB
          DirectMap2M: 7120896 kB
          DirectMap1G: 11534336 kB


          2、查看Linux系统内核slab分配器信息。

          3、查看dentry(目录项缓存)的信息。

                  cat /proc/sys/fs/dentry-state 

            [root@JiJian ~]#  cat /proc/sys/fs/dentry-state 
            23582  10007  45  0  0  0

            4、释放系统内存。

            echo 2 > /proc/sys/vm/drop_caches

            5、查看释放后的内存占用情况,可以看到恢复正常。

              [root@JiJian ~]# free -m
              total used free shared buffers cached
              Mem: 15886 13252 2633 24 34 706
              -/+ buffers/cache: 12511 3375
              Swap:         8071          2       8069


              五、命令区别

              echo 3 > /proc/sys/vm/drop_caches
              echo 2 > /proc/sys/vm/drop_caches
              都是用于清空Linux内核中的文件系统缓存(页缓存、目录项缓存和inode缓存)的命令,但它们的行为略有不同:

              1. echo 3
                > /proc/sys/vm/drop_caches

                • 这个命令清空文件系统缓存,并且会清空目录项缓存、inode缓存以及页缓存。

                • 它将释放大部分文件系统缓存,包括已缓存的文件数据和文件元数据。

                • 这个命令通常在进行性能基准测试之前使用,以确保测试不受之前缓存的影响,或者在系统性能问题时可能需要释放缓存以解决问题。

              2. echo 2
                > /proc/sys/vm/drop_caches

                • 这个命令清空文件系统缓存,但只清空页缓存,不会影响目录项缓存和inode缓存。

                • 它只会释放已缓存的文件数据,而不会影响文件元数据(目录项和inode)。

                • 这个命令在需要释放文件数据缓存时使用,但保留文件系统元数据,这对于某些应用和工作负载可能很有用。

              通常情况下,echo 3 > /proc/sys/vm/drop_caches
              用于清空全部文件系统缓存,而 echo 2 > /proc/sys/vm/drop_caches
              用于清空文件数据缓存。选择使用哪个取决于具体需求,例如你是否需要保留目录项缓存和inode缓存。在生产环境中,请谨慎使用这些命令,因为清空缓存可能会对性能产生一些瞬时影响。


              文章转载自巴韭特锁螺丝,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论