java生产环境下性能监控与调优
JVM的参数类型
基于JDK命令行工具的检测
主要内容
JVM的参数类型
标准参数
-help
-server -client
-version -showversion
-cp -classpath
X参数
非标准化参数
-Xint:解释执行
-Xcomp:第一次使用就编译成本地代码
-Xmixed:混合模式,JVM自己来决定是否编译成本地代码
xx参数
非标准化参数
相对不稳定
主要用于JVM调优和Debug
Boolean类型
格式:-XX:[+-]
比如:-XX:+UseConcMarkSweepGC
-XX:+UseG1GC
非Boolean类型
格式:-XX:
比如:-XX:MaxGCPauseMillis=500
XX:GCTimeRatio=19
-Xmx -Xms
不是X参数,而是XX非Boolean类型参数的简写
-Xms等价于-XX:InitialHeapSize
-Xmx等价于-XX:MaxHeapSize
运行时JVM参数查看
查看JVM运行时参数
-XX:+PrintFlagsInitial
-XX:+PrintFlagsFinal
-XX:+UnlockExperimentalVMOptions解锁实验参数
-XX:+UnlockDiagnosticVMOptions解锁诊断参数
-XX:+PrintCommandLineFlags打印命令行参数
=表示默认值
:=被用户或者JVM修改后的值
jps
jinfo
jinfo -flag MaxHeapSize 进程号
jstat查看虚拟机统计信息
类装载
jstat -class 进程号 1000 10
垃圾收集
-gc、-gcutil、-gccause、-gcnew、-gcold
gc输出
S0C、S1C、S0U、S1U:S0和S1的总量与使用量
EC、EU:Eden区总量与使用量
OC、OU:Old区总量与使用量
MC、MU:Metaspace区总量与使用量
CCSC、CCSU:压缩类空间总量与使用量,启用短指针
YGC、YGCT:YoungGC的次数与时间
FGC、FGCT:FUllGC的次数与时间
GCT:总的GC时间
JVM内存结构
S0+S1+EC+EU=Young
OC+OU=Old
Yuong+Old=堆区
Metaspace+CCS+CodeCache=非堆区
JIT编译
-compiler、-printcompilation
jstat -compiler 进程号
输出:编译了多少方法,失败了多少
堆和非堆内存溢出演示
package com.imooc.monitor_tuning.chapter2;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
public class Metaspace extends ClassLoader{
public static List<Class<?>> createClasses(){
List<Class<?>> classes = new ArrayList<>();
for (int i = 0; i < 10000000; ++i) {
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_1,Opcodes.ACC_PUBLIC,"Class"+i,null,"java/lang/Object",null);
MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC,"<init>","()V",null,null);
mw.visitVarInsn(Opcodes.ALOAD,0);
mw.visitMethodInsn(Opcodes.INVOKESPECIAL,"java/lang/Object","<init>","()V");
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(1,1);
mw.visitEnd();
Metaspace test = new Metaspace();
byte[] code = cw.toByteArray();
Class<?> exampleClass = test.defineClass("Class"+i,code,0,code.length);
classes.add(exampleClass);
}
return classes;
}
}
package com.imooc.monitor_tuning.chapter2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@RestController
public class MemoryController {
private List<User> userList = new ArrayList<>();
private List<Class<?>> classList = new ArrayList<>();
//-Xmx32M -Xms32M
//堆内存溢出
@GetMapping("/heap")
public String heap(){
int i = 0;
while(true) {
userList.add(new User(i++, UUID.randomUUID().toString()));
}
}
//-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
//非堆,MateSpace溢出
@GetMapping("/nonheap")
public String nonheap() {
int i = 0;
while (true) {
classList.addAll(Metaspace.createClasses());
}
}
}
导出内存映像文件
如何导出内存映像文件
内存溢出自动导出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
使用jmap命令手动导出
jps -l
jmap -dump:format=b,file=heap.hprof 进程号
jmap+MAT实战内存溢出
MAT分析内存溢出的映像文件
jstack实战死循环与死锁
jstack与线程状态
jstack 进程号 > 文件名.txt
基于JVisualVM的可视化监控
主要内容
监控本地tomcat
监控远程tomcat
修改tomcat的Catalina.sh
JAVA_OPTS=
"
$JAVA_OPTS -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=9004 -
Dcom.sun.management.jmxremote.authenticate=false -
Dcom.sun.management.jmxremote.ssl=false -
Djava.net.preferIPv4Stack=true -
Djava.rmi.server.hostname=10.110.3.62
"
监控普通的JAVA进程
添加JAVA进程启动参数
nohup java -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=9005 -
Dcom.sun.management.jmxremote.authenticate=false -
Dcom.sun.management.jmxremote.ssl=false -
Djava.net.preferIPv4Stack=true -
Djava.rmi.server.hostname=10.110.3.62 -jar monitor_tuning.jar &
使用JVisualVM远程连接JMX线程
基于Btrace的监控调优
Btrace简介
Btrace可以动态地向目标应用程序的字节码注入追踪代码
JavaComplierApi、JVMTI、Agent、Instrumentation+ASM
Btrace安装
新建环境变量BTRACE_HOME
添加Path:%BTRACE_HOME%\bin
例:
@RestController
@RequestMapping("/ch4")
public class Ch4Controller {
@RequestMapping("arg1")
public String arg1(@RequestParam("name")String name) {
return "hello,"+name;
}
}
@BTrace
public class PrintArgSimple {
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter4.Ch4Controller",
method = "arg1",
location = @Location(Kind.ENTRY)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
BTraceUtils.printArray(args);
BTraceUtils.println(pcn+","+pmn);
BTraceUtils.println();
}
}
btrace 20092 PrintArgSimple.java
拦截构造函数、同名函数
使用详解
拦截方法
拦截时机
拦截this、参数、返回值
其他
普通方法@OnMethod(clazz="",method="")
构造函数@OnMethod(clazz="",method="
@BTrace
public class PrintArgSimple {
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter2.User",
method = "<init>"
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
BTraceUtils.printArray(args);
BTraceUtils.println(pcn+","+pmn);
BTraceUtils.println();
}
}
拦截同名函数,用参数区分
@BTrace
public class PrintArgSimple {
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter4.Ch4Controller",
method = "same"
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name,int id){
BTraceUtils.println(pcn+","+pmn+","+name+","+id);
BTraceUtils.println();
}
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name){
BTraceUtils.println(pcn+","+pmn+","+name);
BTraceUtils.println();
}
}
拦截时机
Kind.ENTRY:入口,默认值
Kind.RETURN:返回
Kind.THROW:异常
Kind.Line:行
拦截返回值、异常、行号
返回值
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter4.Ch4Controller",
method = "arg1"
location = @Location(Kind.RETURN)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType result) {
BTraceUtils.println(pcn+","+pmn+","+result);
BTraceUtils.println();
}
异常
@TLS
static Throwable currentException;
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow(@Self Throwable self){
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow1(@Self Throwable self,String s,Throwable cause){
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>"
)
public static void onthrow2(@Self Throwable self,Throwable cause){
currentException = self;
}
@OnMethod(
clazz = "java.lang.Throwable",
method = "<init>",
location = @Location(Kind.RETURN)
)
public static void onthrowreturn(){
if(currentException != null) {
BTraceUtils.Threads.jstack(currentException);
BTraceUtils.println("========");
currentException = null;
}
}
行号
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter4.Ch4Controller",
location = @Location(value=Kind.Line,line=35)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn,int line) {
BTraceUtils.println(pcn+","+pmn+","+line);
BTraceUtils.println();
}
拦截复杂参数、坏境变量、正则匹配拦截
this:@self
入参:可以用AnyType,也可以用真是类型,同名的用真实的
返回:@Return
简单类型:直接获取
复杂类型:反射,类名+属性名
@OnMethod(
clazz = "com.imooc.monitor_tuning.chapter4.Ch4Controller",
method="arg2",
location = @Location(value=Kind.ENTRY)
)
public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn,User user) {
BTraceUtils.printFiles(user);
Field filed2 = BTraceUtils.field("com.imooc.monitor_tuning.chapter2.User","name")
BTraceUtils.println(BTraceUtils.get(filed2, user));
BTraceUtils.println(pcn+","+pmn);
BTraceUtils.println();
}
打印行号:Kind.LINE
打印堆栈:Threads.jstack()
打印环境变量
注意事项
默认只能在本地运行
生产环境下可以使用,但是被修改的字节码不会被还原
主要内容
tomcat远程debug
jdwp
修改bin/startup.sh
exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"
修改bin/catalina.sh的端口或默认使用8000
使用eclipse或idea连接
tomcat-manager监控
低版本开启,高版本默认不开启
步骤conf/tomcat-users.xml添加用户
<role rolename="tomcat"/>
<role rolename="manager-status"/>
<role rolename="manager-gui"/>
<user username="tomcat" password="123456" roles="tomcat,manager-gui,manager-status"/>
conf/Catalina/localhost/manager.xml配置允许的远程连接
<?xml version="1.0" encoding="UTF-8"?>
<Context privileged="true" antiResourceLocking="false"
doBase="${catalina.home}/webapps/manager">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1"/>
</Context>
重启,访问http://127.0.10.1:8080/manager
psi-probe监控
下载地址https://github.com/psi-probe/psi-probe
在目录下mvn clean package -Dmaven.test.skip
将war包放到tomcat的webapps下
同样要修改conf/Catalina/localhost/manager.xml和conf/tomcat-users.xml添加用户
tomcat调优
内存优化
线程优化
配置优化
Nginx性能监控与调优
ngx_http_stub_status监控连接信息
ngxtop监控请求信息
按赚python-pip
yum install epel-release
yum install python-pip
安装ngxtop
pip install ngxtop
nginx-rrd图形化监控
需要安装php
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)