您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    再顺手的线上缺点,都逃不过这些高效排查套路(2)
    时间:2021-08-31 12:25 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    再顺手的线上缺点,都逃不过这些高效排查套路

    图3

    经过上图,可以看到JVM各个区域所运用的内存大小,主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol等,各部分作用如下:

    Class:加载的类与办法信息,其实就是 metaspace,包含两部分:一是 metadata,被-XX:MaxMetaspaceSize限制最大大小,另外是 class space,被-XX:CompressedClassSpaceSize限制最大大小;

    Thread:线程与线程栈占用内存,每个线程栈占用大小受-Xss限制,但是总大小没有限制。在x64的JVM中,Xss默以为1024K,所以假设你的运用开启了1000个线程,那么这个Thread区占用将是1024M,所以普通我们会把Xss设置为256K即满足要求;

    Code:JIT 即时编译后(C1C2 编译器优化)的代码占用内存,受-XX:ReservedCodeCacheSize限制;

    GC:渣滓回收占用内存,例如渣滓回收需求的 CardTable,标记数,区域划分记载,还有标记 GC Root 等等,都需求内存。这个不受限制,普通不会很大,但也有例外,图3是27G的堆内存,运用G1渣滓回收器,你能看到GC区居然占用了3.8G的内存;

    Compiler:C1 C2 编译器本身的代码和标记占用的内存,这个不受限制,普通不会很大;

    Internal:命令行解析,JVMTI 运用的内存,这个不受限制,普通不会很大;

    Symbol: 常量池占用的大小,字符串常量池受-XX:StringTableSize个数限制,总内存大小不受限制;

    我们需求需求留意的是Class、Thread、GC几个区域的大小。图4是各种JVM渣滓回收器消耗内存的比例,留意这部分外存是堆内存之外的:

    再顺手的线上缺点,都逃不过这些高效排查套路

    图4

    实际证明,G1的内存开支甚至能占到堆内存的20%,当然这不是本文要讨论的内容,感兴味的读者可以去阅读《JVM G1源码剖析和调优》一书查看相关内容。

    针对下面的各个区域大小做加法,看一下能否接近于RSS的大小,假设是,祝贺你可以到此完毕了。后续你需求做的就是针对内存占用比较大的JVM区去做优化,这里就不详细引见了。

    假设不是,很遗憾,你进入到了最难啃的环节,继续往下看吧。

    注:开启NativeMemoryTracking会形成5%的功用下降,用完记得修正JVM参数并重启永世封锁,或许可以经过以下命令暂时封锁:jcmd vm.native_memory stop 。

    4. 堆外内存能否用量太多

    堆外内存也是比较容易被疏忽的一个区域,尤其是网络通讯十分频繁的运用,这种运用往往少量运用Java NIO,而NIO为了提高效率,往往会央求很多的堆外内存。确认这个区域用量能否过大,最直接的办法是先查看能否是DirectByteBuffer或许MappedByteBuffer运用了较多的堆外内存。

    假设你的效劳器曾经开启了远程JMX,你可以经过ops提供的jmx查询工具去查询,也可以经过jdk自带的工具(比如jconsole、jvisualvm)查询,如图5所示:

    再顺手的线上缺点,都逃不过这些高效排查套路


    图5

    假设未开启远程JMX,可以经过jmxterm(https://docs.cyclopsgroup.org/jmxterm)工具在本地形式下查询以下两项内容确认用量:

    java.nio:name=direct,type=BufferPool 

     

    java.nio:name=mapped,type=BufferPool 

    假设确认上述堆外内存运用过多,那么可以经过在jvm参数中设置-XX:MaxDirectMemorySize这个参数控制一下,由于经过DirectByteBuffer分配的堆外内存,默许是不会控制这个区域的内存用量的。

    假设上述内存用量不大,那我们就需求祭出终极杀器jemalloc来做进一步剖析了。这里触及的内容比较多,受限于文章篇幅限制,就不展开描画了。

    经过jemalloc的搜集到的数据,我们基天分够定位到堆外内存成绩的缘由。

    5. 总结

    上述的4个步骤,基天分够处置大少数的RSS占用高的成绩了。当然事无相对,没有一种药是包治百病的。我们追求的基本目的是,经过成绩排查的套路化,协助工程师理清思绪,少走弯路,以提高成绩排查的效率。

    三、成绩排查的工具化

    复盘一下上述的成绩排查进程,我们用到了很多的命令和第三方工具,整个进程还是工程师驱动命令行和工具。假设对命令参数不熟习,或本地没有安装相应的工具,那这种套路化的教程也只能在一定水平上提高效率。在这个套路的基础上,我们能否可以转变思绪,以工具为主,工程师辅佐,来提高排查成绩的效率呢?让我们来尝试一下。

    1. 流程梳理

    先来梳理工具的执行流程以及每个步骤需求做的事情,与第二节保持分歧性,本节也划分红4个子步骤。

    1)确认堆内存能否太大

    第一步要做的事情比较多,梳理如下:

    Java进程pid:运用jps -v列出java进程列表,由用户选择详细的进程;

    获取运转环境的物理内存和剩余内存(free -m)

    Java进程的堆内存用量(jcmd GC.heap_info)

    Java进程GC状况(jstat-gcutil);

    获取到上述信息后,判别堆内存能否太大。

    2)能否存在少量ARENA区

    经过pmap命令获取内存分配列表,辅以awk命令提取内存信息,据此判别能否存在少量ARENA区。

    3)非堆内存能否开支过大

    此步骤需求在JVM启动脚本中添加启动参数并重新启动进程,关于标准化的运转环境来说,在知道了启动脚本位置和启动命令的状况下,是可以经过工具来完成参数的修正和进程启动。假设不能知道启动脚本所在位置,我们可以复制当行进程的JVM参数来完成进程的启动。

    当JVM进程启动完成,再次进入工具,我们就能借助于Native Memory Tracking的结果来判别以后环节能否存在成绩。

    4)堆外内存能否用量太多 (责任编辑:admin)