环境监控"/>
JVM 生产环境监控
.html
目录
1. 基于JDK命令行工具的监控
1. 参数分类
1.1 标准参数
1.2 X参数
1.3 XX参数
2. 查看JVM运行时参数
3. JPS
4. JINFO
5. JSTAT
6. 内存溢出实战
7. 死循环与死锁 实战
7.1 死循环问题定位 CPU占用高
7.2 死锁问题
8. VisualVm插件
9. Btrace
9.1 Btrace简介
10. Tomcat性能监控与调优
10.1 tomcat远程debug
10.2 tomcat-manager监控
10.3 psi-probe监控
10.4 tomcat优化
10.4.1 线程优化
10.4.2 配置优化
11. Nginx 性能监控与调优
11.1 ngx_http_stub_status 监控连接信息
11.2 nginxtop 监控请求信息
11.3 nginx-rrd 图形化监控
11.4 nginx优化
12. JVM调优
12.1 GC调优
12.1.1 垃圾回收算法
12.1.2 垃圾收集器
12.1.3 CMS垃圾收集器
12.1.4 G1 垃圾收集器
13. 可视化工具分析GC日志
14. Java代码优化
14.1 常用代码优化方法
1. 基于JDK命令行工具的监控
1. 参数分类
1.1 标准参数
JVM各个版本中不变的,相对稳定的
例如 -help 、-server、-client -version 、-showversion、-cp、-classpath
1.2 X参数
非标准参数,各个JVM版本可能会发生变化
- -Xint 解释执行
- -Xcomp 第一次使用就编译成本地代码
- -Xmixed 混合模式、JVM自己来决定是否编译成本地代码
1.3 XX参数
属于实验性的、相对不稳定、主要用于JVM调优和Debug
- Boolean类型
格式 -XX: [ +- ] <name> 表示启用或者禁用name属性
比如 -XX:+UseG1GC 启用G1垃圾收集器
- 非Boolean类型
格式 -XX: <name> = <value> 表示name属性的值是value
比如 -XX: GCTimeRatio=19
-Xmx -Xms 是XX参数
-Xmx 等价于 -XX:InitialHeapSize(初始化堆大小)
-Xms 等价于 -XX:MaxHeapSize(最大化堆大小)
2. 查看JVM运行时参数
- -XX:+PrintFlagsInitial 查看初始值
- -XX:+PrintFlagsFinal 查看最终值
- -XX:+UnlockExperimentalVMOptions 解锁实验参数
- -XX:+UnlockDiagnosticVMOptions 解锁诊断参数
= 是初始值
:= 是修改过的值
3. JPS
查看所有Java进程
参数
-l 显示 main的 全限定名
more see .html
4. JINFO
打印指定Java进程的Java配置信息
例1 jinfo -flag MaxHeapSize 13836
打印指定进程的最大值
例2 jinfo -flags 13836
打印指定进程的所有修改过的值
more see .html#BCGEBFDD
5. JSTAT
查看jvm的统计信息
例1 jstat -class 3176 1000(时间/毫秒) 10 (次数)
GC
官网可以查到每个参数的意义
6. 内存溢出实战
6.1 内存溢出时自动导出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
6.2 使用jmap手动导出
jmap -dump:format=b,file=a.hprof 13836
7. 死循环与死锁 实战
线程状态
- NEW 新建的
- RUNNABLE 运行中的
- BLOCKED 阻塞的
- WAITING 等待的
- TIMED_WAITING 限时等待
- TERMINATED 终止的
see more .html
7.1 死循环问题定位 CPU占用高
-
找到程序的pid
-
查看进程内的所有线程 top -p 7930 -H
-
找到占用CPU最多的线程
-
printf "%x" pid ( 将线程 pid 转换为16进制数)
-
执行jstack pid 查看线程信息
-
在输出的文件内 find 刚才转出来的16进制数 就可以定位到一个线程的堆栈信息
-
完成
7.2 死锁问题
- 找到应用程序的pid
- jstack pid
- 直接看最末尾 就可以发现 found 1 deadlock
- 完成
8. VisualVm插件
点击菜单栏 工具 -> 插件
访问 VisualVM: Plugins Centers
选择对应的版本 将属兔中的连接复制到下面中
即可以按照插件了!
9. Btrace
9.1 Btrace简介
Btrace可以动态地向目标应用程序的字节码注入追踪代码
下载地址 .3.11.3
学习地址
10. Tomcat性能监控与调优
10.1 tomcat远程debug
vim bin/startup.sh 在末尾的 start 前加 jpda
远程调试必须保证和服务器上有相同的代码,然后打断点
工具的配置
eclipse
- 在eclipse中,点击 run configuration
- 在左侧的列表选择 RemoteApplication
- 填入 host / port (port 是 catalina.sh里配置的端口,默认为8000)
- 然后 apply debug
idea
- 点击菜单栏的 run
- 点击 EditConfiguration
- 点击 + 号
- 点击 Remote
- 修改 host / port
- apply / OK
10.2 tomcat-manager监控
tomcat自带,低版本默认开启,开版本未开启
文档 docs/manager-howto.html
步骤
- conf/tomcat-users.xml 添加用户
- conf/catalina/localhost/manager.xml(文件不存在,要自己新建) 配置允许的远程连接
- 重启
- 访问 127.0.0.1:8080/manager
10.3 psi-probe监控
github地址 GitHub - psi-probe/psi-probe: Advanced manager and monitor for Apache Tomcat, forked from Lambda Probe
10.4 tomcat优化
- 内存优化
- 线程优化
- 配置优化
10.4.1 线程优化
文档 docs/config/http.html
- maxConnections 最大连接数
- acceptCount 请求???
- maxThread 同一个时间 可以处理的线程数
- minSpareThreads 最小空闲的工作线程 不要太小
10.4.2 配置优化
文档 docs/config/host.html
- autoDeploy 默认为true , 当程序启动的时候是否定期检查是否有新的应用程序从而来自动部署 生产环境改为false
- 如果是jsp , 可以禁用掉session
并发大的时候用apr连接器
11. Nginx 性能监控与调优
nginx.conf 配置文件 注释
#user nobody; # 运行nginx的用户
worker_processes 1; # nginx的工作进程数#error_log logs/error.log; # 错误日志地址
#error_log logs/error.log notice;
#error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024; # 每一个工作进程可以启用 1024 个连接
}http {include mime.types; default_type application/octet-stream; # 二进制流#log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # 输出日志的格式# '$status $body_bytes_sent "$http_referer" '# '"$http_user_agent" "$http_x_forwarded_for"';#access_log logs/access.log main; # 输出日志的地址 后面是格式名称(main)sendfile on; #tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65; # 默认跟浏览器有65秒的长连接#gzip on;server{ # 定义一个serverlisten 81; # 监听 81端口server_name localhost; # servernamelocation /index1 { # 相当于 context-pathroot D:\homeworlk\admin_7001; # 文件地址index index.html index.htm; # index位置}# 配置监控连接信息location = /nginx_status{stub_status on; access_log off;allow 127.0.0.1; #配置权限deny all;}}
11.1 ngx_http_stub_status 监控连接信息
添加配置
# 配置监控连接信息location = /nginx_status{ # 访问这个路径nginx_status stub_status on; access_log off;allow 127.0.0.1; #配置权限deny all;}
11.2 nginxtop 监控请求信息
网址 GitHub - lebinh/ngxtop: Real-time metrics for nginx server
安装
# 1.安装python-pip
yum install epel-release
yum install python-pip# 2.安装nginxtop
pip install ngxyop
使用
# 指定配置文件
ngxtop -c /etc/nginx/nginx.conf# 查询状态是 200
ngxtop -c /etc/nginx/nginx.conf -i 'status' == '200'# 查询访问最多ip
ngxtop -c /etc/nginx/nginx.conf -g remote_addr
11.3 nginx-rrd 图形化监控
基于状态监控做(ngx_http_stub_status )
安装请百度
11.4 nginx优化
1. 配置工作线程数和并发连接数
worker_processes: 4 # 有多少个cpu就配多少
events{worker_connections 1024 # 每一个进程打开的最大连接数,包含了nginx与client和nginx与upstream之间的连接multi_accept on; # 可以一次建立多个连接use epoll; # 使用 epoll 网络模型
}
nginx -t 命令可以查看配置语法是否正确
2. 配置长连接
vim conf/nginx.conf
... 百度吧
3. 配置压缩
gzip on;
12. JVM调优
12.1 GC调优
命令
- -Xms -Xmx 最小、大堆内存
- -XX:NewSize、-XX:MaxNewSize 新生代区域 最小、最大(Young区)
- -XX:MetaspaceSize -XX:MaxMetaspaceSize metaSpace的最小、最大(MethodArea区)
- -XX:+UseCompressedClassPointers 启用压缩指针、短指针、32位指针。启用后会产生ccs
- -XX:CompressedClassSpaceSize 设置压缩类空间大小
- -XX:InitialCodeCacheSize (codeCache初始大小)
- -XX:ReservedCodeCacheSize (codeCache最大大小)
12.1.1 垃圾回收算法
-
思想 枚举根节点、做可达性分析
-
根节点 类加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量等等
对象分配
- 对象优先在eden区分配
- 大对象直接进入老年代 -XX:PretenureSizeThreshold (指定大对象的阈值)
- 长期存活对象进入老年代
-XX:+PrintTenuringDistribution 发生youngGC的时候打印age info
-XX:TargetSurvivorRatio
每进过一次yongGC,存活的对象的age+1,等年龄达到( -XX:MaxTenuringThreshold)岁就会进入old区,
12.1.2 垃圾收集器
- 串行收集器(单线程) serial、servialOld(-XX:UseSerialGC、-XX:UseSerialOldGC)
- 并行收集器(吞吐量优先、server模式下默认启用)Parallel Scavenge、Parallel Old (-XX:+UseParallelGC、-XX:+UseParallelOldGC)
- 并发收集器(停顿时间优先) CMS(-XX:+UseConcMarkSweepGC - old区、-XX:+UseParNewGC - young区) G1(-XX:+UseG1GC)
并行 VS 并发
- 并行(Parallel ) 指多条垃圾收集器并行工作、但此时用户线程任然处于等待状态。适合科学计算、后台处理、弱交互场景
- 并发(Concurrent)指用户线程与垃圾收集器线程同时执行(但不一定是并行的、可能会交替执行)垃圾收集器线程在执行的时候不会停顿用户程序的运行。适合对响应时间有要求的场景、比如web
停顿时间 VS 吞吐量
- 停顿时间 垃圾收集器做垃圾回收中断应用执行的时间(-XX:MaxGCPauseMillis)
- 吞吐量 花在垃圾收集的时间和花在应用程序时间的占比。(-XX:GCTimeRatio = n,垃圾收集时间占 1/1+n)
如何选择垃圾收集器
- 优先调整堆的大小让服务器自己来选择
- 如果内存小于100M,使用串行收集器
- 如果是单核、并且没有停顿时间的要求、串行或者JVM自己选
- 如果允许停顿时间超过1秒、选择并行或者JVM自己选
- 如果响应时间最重要、并且不能超过一秒、使用并发收集器
12.1.3 CMS垃圾收集器
cms的缺点
- CPU敏感
- 浮动垃圾
- 空间碎片
CMS相关参数
- -XX:ConcGCThreads 并发的GC线程数
- -XX:UseCMSCompactAtFullCollection FullGC之后做压缩
- -XX:CMSFullGCsBeforeCompaction 多少次FullGC之后做压缩一次
- -XX:CMSInitialtingOccupancyFraction 触发GC
- -XX:+UseCMSInitiatingOccupancyOnly 是否动态调
- -XX:+CMSScavengeBeforeRemark FullGC之前先做YGC
- -XX:+CMSClassUnloadingEnabled 启用回收Perm区(jdk1.7)
12.1.4 G1 垃圾收集器
大于等于6g内存时间 停顿时间小于0.5 m
G1的几个概念
- STAB:Snapshot-At-The-Beginning,他是通过RootTracing得到的,GC开始时候存活对象的快照
- RSet :记录了其他Region中的对象引用本Region中对象的关系,属于point-into结构(谁引用了我的对象)
YoungGC:
- 新对象进入Eden区
- 存活对象拷贝到Survivor区
- 存活时间到达年龄阈值时,对象晋升到old区
MixedGC:
- 不是FullGC,回收所有Young和部分Old区
- Global Concurrent Marking
1. Initial marking phase:标记GC Root, STW
2. RootRegionScanningPhase:标记存活region
3.ConcurrentMarkingPhase:标记存活对象
4.RemarkPhase:重新标记,STW
5.CleanupPhase:部分STW
- MixedGC时机
InitiatingHeapOccupancyPercent:堆占有率达到这个数值则触发globalConcurrentMarking,默认45%
MixedGC相关参数
- G1MixedGCliveThresholdPercent: old区的region被回收时候的存活对象占比
- G1MixedGCCountTarget:一次globalConcurrentMarking之后,最多执行MixedGC次数
- G1OldCSetRegionThresholdPercent:一次MixedGC中能够被选入CSet的最多old区的region数量
- -XX:+UseG1GC 开启G1
- -XX:G1HeapRegionSize=n region的大小,1-32M,2048个
- -XX:MaxGCPauseMillis=200 最大停顿时间
- -XX:G1NewSizePrecent | -XX:G1MaxNewSizePercent 占比
- -XX:G1ReservePercent = 10 保留防止 to space溢出
- -XX:ConcGCThreads = n 并发线程数 = 1/4*并行
最佳实践
- 不要显式设置年轻代大小,不然会覆盖掉 停顿时间
- 暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量
- 关于MixdGC调优
13. 可视化工具分析GC日志
在线工具 gceasy.io
gcviewer
14. Java代码优化
14.1 常用代码优化方法
- 尽量重用对象,不要循环创建对象
- 容器初始化的时候指定长度、防止扩容
- ArryList随机访问快、LinkedList增删快
- 集合遍历减少重复计算
- 使用Entry遍历map
for(Map.Entry<String,String> entry : map.entrySet() ){String key = entry.getKey();String value = entry.getvalue();
}
-
大数组复制用System.arraycopy
-
尽量使用基本类型而不是包装类型
-
不要手动调用System.gc();
-
及时消除过期的对象引用,防止内存泄露
-
尽量使用局部变量、减少变量的作用域
-
尽量使用非同步容器 ArrayList
-
尽量减少同步方法的作用域
-
ThreadLocal缓存线程不安全的对象、SimpleDataFormat
-
尽量使用延迟加载
-
尽量减少使用反射,加缓存
-
尽量使用连接池、线程池、对象池、缓存
-
及时释放资源、IO流、Socket、数据库连接
-
慎用异常、不要用抛异常来表示正确的业务逻辑
-
String操作尽量少用正则表达式
-
日志输出尽量使用不同的级别
-
日志中参数使用占位符
更多推荐
JVM 生产环境监控
发布评论