生产环境问题定位分析和JVM调优

生产环境下JVM调优

最小堆、最大堆内存设为1G,使用G1垃圾回收器,最长的GC暂停时间设为200毫秒,如果时间过长,会相应调整空间的大小(单位是毫秒),新生代最小比例20%,最大比例30%,

+DisableExplicitGC关闭系统调用GC功能 【System.gc() 默认会触发一次Full Gc】
打印GC及GC详细信息、GC时间戳,在out of memory的情况下的内存dump输出到指定路径,GC日志路径

nohup java -jar -server  -Xms1G  -Xmx1G  -XX:+UseG1GC  -XX:MaxGCPauseMillis=200  -XX:+UnlockExperimentalVMOptions  -XX:G1NewSizePercent=20  -XX:G1MaxNewSizePercent=30  -XX:+DisableExplicitGC  -XX:+PrintGC  
-XX:+PrintGCDetails  -XX:+PrintGCTimeStamps  -XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=/data/www/$project_name/online/logs/oom-error_8000.log                  Xloggc:/data/www/$project_name/online/logs/gc_log_8000.log  ***.jar     > ***.log &
  • 另一种GC日志输出

设置GC日志的路径,%t 会记录当前日期,+UseGCLogFileRotation开启滚动日志,

NumberOfGCLogFiles设置文件数量5个,GCLogFileSize文件大小20M (超过20M,进入下一个文件)

-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log  -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=5  -XX:GCLogFileSize=20M  -XX:+PrintGCDetails  -XX:+PrintGCDateStamps   -XX:+PrintGCCause

JVM调优思路

  1. 常规JVM调优:当 Java 线上出现问题,如 CPU 飙升、负载突高、内存溢出等问题,需要查命令,查网络,然后 top、jps、jstat、jstack、jmap、jhat、hprof 等操作。
  2. 对于OOM Erro dump转储文件、GC日志进行分析,解决问题
  3. 使用 Arthas 轻松定位,图形化界面、迅速解决,及时止损。
  4. https://blog.csdn.net/u013735734/article/details/102930307
  5. 监控: arthas / jconsole / jvisualVM / Jprofiler(最好用)
  6. 线上查找 ( cmdline || arthas )
  7. jstat -gc 动态观察gc情况 stat -gc 4655 500 : 每个500个毫秒打印GC的情况

查看运行的 java 进程信息 (top、jps )

$ jps -mlvV

$ jps -mlvV | grep [xxx]

top 、 top -Hp pid

top 查看所有进程的 CPU、内存状态

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7945 root 20 0 2813304 301908 14000 S 101.3 30.3 20:44.36 java

top -Hp pid 查看指定进程下所有线程的 CPU、内存状态

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7947 root 20 0 2813304 309196 14064 S 93.7 31.0 28:16.02 java

查看GC汇总信息 ( jstat )

  • jstat -gcutil 进程ID

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 99.33 86.40 97.12 94.49 21 2.968 5 1.027 3.996

S0 ---> 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1 ---> 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E ---> 年轻代中Eden(伊甸园)已使用的占当前容量百分比

O ---> old代已使用的占当前容量百分比
M ---> 元数据空间使用比例
CCS ---> 压缩使用比例

YGC ---> 从应用程序启动到采样时年轻代中gc次数
YGCT ---> 从应用程序启动到采样时年轻代中gc所用时间(s)
FGC ---> 从应用程序启动到采样时old代(全gc)gc次数
FGCT ---> 从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT ---> 从应用程序启动到采样时gc用的总时间(s)

  • jstat -gc 动态观察gc情况 stat -gc 4655 500 : 每个500个毫秒打印GC的情况

进程、线程信息并进行分析 (jinfo 、jstack、jmap 、jhat )

  • jinfo pid

    进程和线程的 具体信息

  • jstack

    jstack 定位线程、进程状况

  • jmap -histo 4655 | head -20

    查找有多少对象产生

  • jmap -dump:live,format=b,file=heap.bin pid

    生成dump转储文件,线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)

  • 使用MAT / jhat /jvisualvm 进行dump文件分析
    https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html

  • jhat -J-mx512M xxx.dump
    http://192.168.17.11:7000

分析日志

dump 文件里,值得关注的线程状态有:

  • 死锁,Deadlock(重点关注)

  • 执行中,Runnable

  • 等待资源,Waiting on condition(重点关注)

  • 等待获取监视器,Waiting on monitor entry(重点关注)

  • 暂停,Suspended

  • 对象等待中,Object.wait() 或 TIMED_WAITING

  • 阻塞,Blocked(重点关注)

  • 停止,Parked

    tid指Java Thread id。nid指native线程的id。prio是线程优先级。

    [0x00007f1d2c4be000] 是线程栈起始地址。

    Thread.State:WAITING (parking) 等待,线程挂起中。

    parking to wait for <0x00000000f5dee038>

    本线程肯定是在等待某个条件的发生,来把自己唤醒。其次,SynchronousQueue 并不是一个队列,只是线程之间移交信息的机制,当我们把一个元素放入到 SynchronousQueue 中时必须有另一个线程正在等待接受移交的任务,因此这就是本线程在等待的条件。

dump文件实例分析

https://www.cnblogs.com/zhengyun_ustc/archive/2013/01/06/dumpanalysis.html

"pool-1-thread-34" #41 prio=5 os_prio=0 tid=0x00007f1d501a2000 nid=0x2001 waiting on condition [0x00007f1d2c4be000]
java.lang.Thread.State: WAITING (parking)
? at sun.misc.Unsafe.park(Native Method)

  • parking to wait for <0x00000000f5dee038>
    (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

JVM常用参数详解

  • nohup java -jar -server

设置为服务端模式, 吞吐量优先 -client

  • nohup java -jar project.jar >> log.out 2>&1 &

错误输出和标准输出,追加到log.out

  • nohup java -jar Project.jar >/dev/null 2>log &

标准输出至/dev/null ( 空洞 ),只输出错误信息至log

nohup 不中断运行,与用户终端无关
>> 输出重定向
2>&1 (2)标准错误输出 (>) 重定向到 (&1)标准输出
2>&1 标准错误输出重定向到标准输出
& 标识进程为后台进程

  • -Xms$max_memory -Xmx$max_memory

    指定Xms最小堆,Xmx最大堆的大小,避免每次垃圾回收完成后JVM重新分配内存.

  • -XX:+UseG1GC

    G1垃圾回收器

  • -XX:MaxGCPauseMillis=200

    最长的GC暂停时间,如果时间过长,会相应调整空间的大小(单位是毫秒)

  • -XX:+UnlockExperimentalVMOptions

    有些时候当设置一个特定的JVM参数时,JVM会在输出“Unrecognized VM option”后终止。如果发生了这种情况,你应该首先检查你是否输错了参数。然而,如果参数输入是正确的,并且JVM并不识别,或许需要设置-XX:+UnlockExperimentalVMOptions 来解锁参数

  • -XX:G1NewSizePercent=20 -XX:G1MaxNewSizePercent=30

    新生代最小比例20%,最大比例30%

  • -XX:+DisableExplicitGC

    关闭系统调用GC功能 System.gc() 默认会触发一次Full Gc

  • -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

    打印GC、GC详细信息、GC时间戳

  • -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=/data/www/$project_name/online/logs/oom-error_8000.log

    当出现OOM内存溢出时进行堆转储,并指定具体路径

  • -Xloggc:/data/www/$project_name/online/logs/gc_log_8000.log

    指定GC日志路径

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产环境中配置JVM是非常重要的,可以通过以下几个步骤来完成配置。 首先,需要根据服务器的硬件和操作系统环境来选择合适的JVM参数。其中,最常用的是-Xms和-Xmx参数,用于设定JVM的初始堆和最大堆的大小。根据实际需求和服务器的内存情况,可以适当调整这两个参数的值,以充分利用服务器资源。 其次,需要考虑G1垃圾收集器的使用。G1垃圾收集器是JDK 9及以上版本的默认垃圾收集器,对于大内存和多核心的生产环境非常适用。可以通过设置-XX:+UseG1GC参数来启用G1垃圾收集器,它可以提供更稳定和高性能的垃圾收集。 此外,还可以设置堆内存参数,如-XX:NewSize和-XX:MaxNewSize,用于调整新生代堆内存的大小。可以根据应用程序的特点和负载情况,适当调整这些参数的值,以提高系统的吞吐量和响应性能。 另外,还可以通过设置-XX:ParallelGCThreads参数来指定并行垃圾收集的线程数,以提高垃圾收集的效率。 此外,还可以通过配置JVM参数来开启监控和调优工具,如启用JMX来监控JVM的运行状态,使用JVisualVM进行性能分析和优化。 最后,还可以通过日志参数来记录JVM的运行情况和错误信息,如设置-XX:+PrintGC和-XX:+PrintGCDetails参数来打印垃圾收集的日志信息,以便进行问题排查和优化。同时,还可以设置-XX:+HeapDumpOnOutOfMemoryError参数,在发生内存溢出错误时生成堆转储文件,用于分析内存使用情况和定位潜在的内存泄漏问题。 总之,配置生产环境JVM需要根据服务器的硬件和操作系统环境,以及应用程序的特点和负载情况来选择合适的参数,并通过调优工具和日志来监控和分析JVM的运行情况,以提高系统的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值