百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

JMX,Jstatd做好JVM应用上线的最后一层保障

nanshan 2024-11-10 10:10 20 浏览 0 评论

一个成功的java项目标准并不仅仅是业务功能实现,但是纵观国内,很多项目组在前期项目开发设计中只考虑了业务功能,没有考虑项目后期维护的监控设计。没有完善的监控运维设计,项目存活的寿命应该也不长吧?好的项目能够吸引人留下来,并不断强化项目的功能优化每一处代码,坏的项目只会逼死人,不断地增加龌龊代码以至于根本无法维护。
当然从公司来说,业务的首要实现是公司能够赚钱的有效保障,公司赚不了钱了,写得再好的代码也只能静静地躺在硬盘中。我想一个负责的开发人员不仅要能重视业务功能的实现,还能保证在项目上线运维中针对突发情况做到监控。

我理解的监控

我理解的监控分两种,一种是运维的监控-监控整个集群的各项资源的使用情况以及各个服务的存活情况,另一种是开发的监控-监控代码问题导致的线程死锁,OOM等,以及业务消息的历史可回溯。
我是一名开发,这里主要讲讲我的心得,开发中的监控。如何减少开发人员不必要的加班。

代码异常监控

应用代码在面对线上各种请求时,经常会发生死锁,OOM等问题。这个时候我们应该如何去查看呢?如果我们不想连上远程服务器,可以通过本地的一些可视化工具连接远程程序,查看远程程序的线程,CPU,GC,堆内存等使用情况。

远程主机配置jmx

这里只是演示JMX的监控功能,JMX还有动态修改bean属性等功能不在这一篇文章讲解。

修改密码,找到配置文件$JAVA_HOME/jre/lib/management/jmxremote.password.template,复制一份并改名为jmxremote.password,然后修改只读权限并编辑jmxremote.passwrod,取消以下两行注释:

#monitorRole QED
#controlRole R&D

修改要启动的java程序启动参数(JVM_OPTS)。

打开tomcat的bin目录下的catalina.sh,加入以下内容**(非tomcat程序也类似)**

JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.19.131 -Dcom.sun.management.jmxremote.port=18999       -Dcom.sun.management.jmxremote.ssl=false    -Dcom.sun.management.jmxremote.authenticate=false"

参数authenticate表示是否需要密码认证,赋值为true就会使用jmxremote.password设置的密码。

修改文件权限

监控的程序是由哪个用户启动,则把jmxremote.password文件的权限改为这个用户的只读权限,

否则启动程序会报错:Error: Password file read access must be restricted。

这些在jmxremote.password里的注释都有说明。

比如,如果你是用intsmaze用户启动java程序

chown intsmaze jmxremote.passwordchmod 400 jmxremote.password

启动jvisualvm

先启动待监控的程序

sh startup.sh

左边栏,右键“远程”>>“添加远程主机”

左侧栏,右键刚才添加的远程主机>>“添加jmx链接”,使用配置的端口


如果我们不配置JVM_OPTS参数,那么我们在本地使用javaVisualVM是无法访问远程服务器上的tomcat服务的状况,要想知道远程服务器的状况就必须使用CRT等工具连上服务器使用linux命令去查看程序的运行情况。

监控服务器上的java程序

在java -cp 命令中加入如下参数即可

java -Dcom.sun.management.jmxremote
  -Dcom.sun.management.jmxremote.ssl=false 
  -Dcom.sun.management.jmxremote.authenticate=false 
  -Dcom.sun.management.jmxremote.port=22222 
  -cp jmx.jar cn.intsmaze.thread.TestDeadThread

TestDeadThread类如下

public class TestDeadThread implements Runnable {
	int a, b;
 
	public TestDeadThread(int a, int b) {
		this.a = a;
		this.b = b;
	}
 
	public void run() {
		synchronized (Integer.valueOf(a)) {
			synchronized (Integer.valueOf(b)) {
				System.out.println(a + b);
			}
		}
	}
 
	public static void main(String[] args) throws InterruptedException {
		Thread.sleep(3000);
		for (int i = 0; i < 100; i++) {
			new Thread(new TestDeadThread(1, 2)).start();
			new Thread(new TestDeadThread(2, 1)).start();
		}
	}
}
JvisiualVM通过JMX的方式连接到远程服务器上的JVM,
此时能获取到JVM的基本信息(启动参数、系统属性)、CPU使用情况、
堆内存整体情况以及线程的整体情况等。
但如果想通过Visual GC插件进一步了解堆内各区的情况的话,就会发现插件此时并不工作。


Visual GC插件不工作,是因为此插件使用的协议是RMI,因此需要使用下面的jstatd方式进行连接。

jstatd 连接到远程JVM

JVM jstat Daemon:守护进程,一个RMI服务器程序,用于监控本地所有JVM从创建开始直到销毁整个过程中的资源使用情况,同时提供接口给监控工具(如这里的VisualVM),让工具能连接到本机所有的JVM。

启动jstatd服务

${java_home}/bin目录下启动jstatd服务
[intsmaze@centos-Reall-131 bin]./jstatd
Could not create remote object
access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")
java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
        at java.security.AccessController.checkPermission(AccessController.java:884)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.System.setProperty(System.java:792)
        at sun.tools.jstatd.Jstatd.main(Jstatd.java:139)

由于jstatd server没有提供任何对远程client端的认证,客户端程序获取到本地当前用户的所有JVM信息后可能存在安全隐患,所以jstatd要求启动之前必须指定本地安全策略,否则jstatd进程无法启动,抛出上面错误。

创建安全策略文件

在需要被监控的远程主机创建一个安全策略文件,比如保存为/home/intsmaze/jdk1.8.0_144/bin/jstatd-all.policy,内容如下:

grant codebase "file:/home/intsmaze/jdk1.8.0_144/lib/tools.jar" {
permission java.security.AllPermission;
};

启动jjstatd带参数

通过如下命令可以成功启动jstatd server

./jstatd -J-Djava.security.policy=/home/intsmaze/jdk1.8.0_144/bin/jstatd-all.policy 
  -J-Djava.rmi.server.logCalls=true./jstatd
  -J-Djava.security.policy=/home/intsmaze/jdk1.8.0_144/bin/jstatd-all.policy &

向通过jstatd命令启动的JVM(Main class:sun.tools.jstatd.Jstatd)传递参数,比如-J-Xms48m指定了Jstatd这个JVM的初始堆内存为48MB

右键选择建立jstatd连接


对应的远程主机节点下会自动列出所有运行的JVM

JMX连接与JStatD连接的区别

JMX:使用JMX需要远程JVM在启动的时候开启远程访问支持,设定JMX端口等,每一个JMX连接一个远程JVM。
JStatD:使用jstatd连接方式时,需要在远程主机上创建安全策略文件然后启动jstatd进程,并且此进程需要一直保持运行状态,客户端可以看到远程主机上当前用户的所有JVM的信息,即只要创建一个jstatd连接。

linux命令监控jvm程序

如果我们不配置JMX和jstatd,那么我们无法使用jvisiualVM去监控远程JVM程序,要知道程序的运行状态我们必须连上服务器去查看。

top命令查看各进程CPU占用率

[intsmaze@centos-Reall-131 ~]$ top
top - 13:04:07 up 3 min,  2 users,  load average: 0.00, 0.01, 0.00
Tasks: 104 total,   1 running, 103 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.2%sy,  0.0%ni, 99.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   2086348k total,   224720k used,  1861628k free,    37484k buffers
Swap:  2064376k total,        0k used,  2064376k free,    91204k cached
 
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                       
  385 root      20   0     0    0    0 S  0.3  0.0   0:00.02 flush-8:0                                                                                                     
 2211 intsmaze  20   0  858m  25m 9448 S  0.3  1.2   0:00.87 java
  1. 第一行:load average: 0.41, 0.45, 0.43 系统负载,即任务队列的平均长度。1分钟前、5分钟前、15分钟前平均负载
  2. 第二行:Tasks: 141 total 进程总数,0 zombie 僵尸进程数
  3. 第三行为cpu信息
    6.1% us 用户空间占用CPU百分比
    1.5% sy 内核空间占用CPU百分比
    0.0% ni 用户进程空间内改变过优先级的进程占用CPU百分比
    92.2% id 空闲CPU百分比
    0.0% wa 等待输入输出的CPU时间百分比
    0.0% hi 硬件中断
    0.0% si 软件中断
    0.0%st 实时
  4. 第四、五行为内存信息。
    Mem: 191272k total 物理内存总量
    22052k buffers 用作内核缓存的内存量
    Swap: 192772k total 交换区总量
    123988k cached 缓冲的交换区总量

进程中每个线程占用cpu情况

[intsmaze@centos-Reall-131 ~]$ top -Hp 2461
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                                                                                            
 2462 intsmaze  20   0  870m  25m 9416 S  30.0  1.2   0:00.28 java                                                                                                          
 2463 intsmaze  20   0  870m  25m 9416 S  0.0  1.2   0:00.00 java                                                                                                          
 2464 intsmaze  20   0  870m  25m 9416 S  0.0  1.2   0:00.00 java

定位线程的运行情况

Jstack是JDK自带的命令行工具,主要用于线程Dump分析,能得到运行java程序的java stack和native stack的信息,可以轻松得知当前线程的运行情况。

jstack -l [pid]查看所有线程信息

jstack -l 2238 > intsmaze.log
[intsmaze@centos-Reall-131 ~]$ jstack -l 2461
"Thread-200":
        at cn.intsmaze.thread.TestDeadThread.run(TestDeadThread.java:29)
        - waiting to lock <0x9d62a3a0> (a java.lang.Integer)
        at java.lang.Thread.run(Thread.java:748)
"Thread-10":
        at cn.intsmaze.thread.TestDeadThread.run(TestDeadThread.java:30)
        - waiting to lock <0x9d62a390> (a java.lang.Integer)
        - locked <0x9d62a3a0> (a java.lang.Integer)
        at java.lang.Thread.run(Thread.java:748)

jstack命令生成的thread dump信息包含了JVM中所有存活的线程,为了分析指定线程,必须找出对应线程的调用栈,应该如何找?

jstack -l [pid] | grep 16进制

top -Hp [pid] 中获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值,在thread dump中每个线程都有一个nid,找到对应的nid即可。

得到2462 的十六进制值
···
[intsmaze@centos-Reall-131 ~]$ printf "%x\n" 2462 
99e
···
jstack -l 21711 | grep 99e
"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x99e in Object.wait()

在nid=0x99e 的线程调用栈中,CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),然后去观察自己写的业务代码。

相关推荐

F5负载均衡器如何通过irules实现应用的灵活转发?

F5是非常强大的商业负载均衡器。除了处理性能强劲,以及高稳定性之外,F5还可以通过irules编写强大灵活的转发规则,实现web业务的灵活应用。irules是基于TCL语法的,每个iRules必须包含...

映射域名到NAS

前面介绍已经将域名映射到家庭路由器上,现在只需要在路由器上设置一下端口转发即可。假设NAS在内网的IP是192.168.1.100,NAS管理端口2000.你的域名是www.xxx.com,配置外部端...

转发(Forward)和重定向(Redirect)的区别

转发是服务器行为,重定向是客户端行为。转发(Forward)通过RequestDispatcher对象的forward(HttpServletRequestrequest,HttpServletRe...

SpringBoot应用中使用拦截器实现路由转发

1、背景项目中有一个SpringBoot开发的微服务,经过业务多年的演进,代码已经累积到令人恐怖的规模,亟需重构,将之拆解成多个微服务。该微服务的接口庞大,调用关系非常复杂,且实施重构的人员大部分不是...

公司想搭建个网站,网站如何进行域名解析?

域名解析是将域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP地址是网络上标识站点的数字地址,为方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转...

域名和IP地址什么关系?如何通过域名解析IP?

一般情况下,访客通过域名和IP地址都能访问到网站,那么两者之间有什么关系吗?本文中科三方针对域名和IP地址的关系和区别,以及如何实现域名与IP的绑定做下介绍。域名与IP地址之间的关系IP地址是计算机的...

分享网站域名301重定向的知识

网站域名做301重定向操作时,一般需要由专业的技术来协助完成,如果用户自己在维护,可以按照相应的说明进行操作。好了,下面说说重点,域名301重定向的操作步骤。首先,根据HTTP协议,在客户端向服务器发...

NAS外网到底安全吗?一文看懂HTTP/HTTPS和SSL证书

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:可爱的小cherry搭好了NAS,但是不懂做好网络加密,那么隐私泄露也会随时发生!大家好,这里是Cherry,喜爱折腾、玩数码,热衷于分享数...

ForwardEmail免费、开源、加密的邮件转发服务

ForwardEmail是一款免费、加密和开源的邮件转发服务,设置简单只需4步即可正常使用,通过测试来看也要比ImprovMX好得多,转发近乎秒到且未进入垃圾箱(仅以Mailbox.org发送、Out...

使用CloudFlare进行域名重定向

当网站变更域名的时候,经常会使用域名重定向的方式,将老域名指向到新域名,这通常叫做:URL转发(URLFORWARDING),善于使用URL转发,对SEO来说非常有用,因为用这种方式能明确告知搜索引...

要将端口5002和5003通过Nginx代理到一个域名上的操作笔记

要将端口5002和5003通过Nginx代理到域名www.4rvi.cn的不同路径下,请按照以下步骤配置Nginx:步骤说明创建或编辑Nginx配置文件通常配置文件位于/etc/nginx/sites...

SEO浅谈:网站域名重定向的三种方式

在大多数情况下,我们输入网站访问网站的时候,很难发现www.***.com和***.com的区别,因为一般的网站主,都会把这两个域名指向到同一网站。但是对于网站运营和优化来说,www.***.com和...

花生壳出现诊断域名与转发服务器ip不一致的解决办法

出现诊断域名与转发服务器ip不一致您可以:1、更改客户端所处主机的drs为223.5.5.5备用dns为119.29.29.29;2、在windows上进入命令提示符输入ipconfig/flush...

涨知识了!带你认识什么是域名

1、什么是域名从技术角度来看,域名是在Internet上解决IP地址对应的一种方法。一个完整的域名由两个或两个以上部分组成,各部分之间用英文的句号“.”来分隔。如“abc.com”。其中“com”称...

域名被跳转到其他网站是怎么回事

当你输入域名时被跳转到另一个网站,这可能是由几种原因造成的:一、域名可能配置了域名转发服务。无论何时有人访问域名,比如.com、.top等,都会自动重定向到另一个指定的URL,这通常是在域名注册商设...

取消回复欢迎 发表评论: