为了账号安全,请及时绑定邮箱和手机立即绑定

利用jmx执行诊断任务

标签:
Java

如果大家仔细查看jconsole的时候会发现一个特殊的mbeans
图片描述

他的下面几乎包含了所有的交互命令。
但是如果你点进去发现,需要填写参数的都是无法执行的。
jconsole目前确实没有这个能力,但是jvirtualvm装插件是可以执行的。
通过这个能力,我们就可以发现jmx似乎可以做其他命令做的所有事情。
只不过是需要特殊的插件。这里也可以说,我们通过这个mbeans是直接可以做你想做的操作的,而不是依赖命令行执行jstack等等。
下面我们就试试通过自己写code操作mbean来进行能力的获取。

demo

    public static void main(String[] args) throws ReflectionException, MBeanException {
        DiagnosticCommandMBean diagnosticCommandMBean = ManagementFactoryHelper.getDiagnosticCommandMBean();
        Object threadPrint = diagnosticCommandMBean.invoke("threadPrint",
                new Object[]{new String[]{}}, new String[]{String[].class.getName()});
        System.out.println(threadPrint);
    }

上面是一个打印stack的案例
我们先获取到DiagnosticCommandMBean。这里是用的jdk8。可以通过ManagementFactoryHelper来进行获取,这个类在高版本中去除了,我们得需要反射等方式来获取DiagnosticCommandMBean。
下面的threadPrint是通过jconsole查看命令的时候获取的。后面是需要跟着的参数。stack不需要参数,所以这里都是空对象。
注意:这里传递的是数组
因为很多命令。例如jfr start 他是有多个参数的,所以支持多个参数的设计,这里必须传递数据才可以正常运行。

jfr的特例

        DiagnosticCommandMBean diagnosticCommandMBean = ManagementFactoryHelper.getDiagnosticCommandMBean();
        Object threadPrint = diagnosticCommandMBean.invoke("jfrStart",
                new Object[]{new String[]{"duration=60s","name=abc","filename=output.jfr"}}, new String[]{String[].class.getName()});
        System.out.println(threadPrint);

上面的例子是一个多参数的例子,jfr的开启是可以跟着很多参数的。这里展示了多参数的启动方式。返回的数据都是命令行返回的结果。

jfr本身是一个常用的profiling手段,这里就是可以使用同进程的方式,触发jfr的数据dump一次可以获取到更丰富的数据。jfr的dump的地址,以及是否通过同进程采集,这些都是我们常用的方式。

对于返回值,这里描述的都是命令行的操作结果,命令行本身返回的都是string字符串,所以这里的返回结果一般都是字符串,我们都可以直接进行打印输出。
他的功能强大,可以利用jmc进行数据的查看。
图片描述

功能的便利

jmx提供了貌似一个命令行提供的功能。他的优势是什么呢?
命令行的操作依赖socket通讯,socket的通讯文件在/tmp下。这个目录往往会因为linux的删除策略,删除掉socket文件,导致后面的功能都操作失效了。
很多线上系统有权限问题,无法直接登录机器操作,命令这些都有严格的执行权限要求,例如A用户启动的jvm程序,只有A用户才能操作,其他用户是操作不了的。所以导致了用户切换过于复杂,编写这样的系统非常的繁琐。

如何搭建一个控制系统

  1. 通过socket通讯
    我们可以通过一个javaagent通过上面的mbean的代码控制,然后连接到一个服务端。这样相比jmx的好处就是不用担心实现预定的端口,如果是以前jmx的模式,需要先确定端口,然后客户端再连接上去。这样的问题是端口需要事先约定,要和临时的端口起冲突,需要做预留端口,否则socket冲突启动不起来。
    在socket的基础上。可以远程获取数据信息,我们常见的apm系统就是这样,通过jmx,socket把信心获取走,但是原来的mbean不太多,功能没有这么复杂,导致了很多功能受限,例如要依赖tools.jar去做jmap等操作,现在就可以减少这样的依赖,直接通过mbean就可以。
  2. 同进程操作更方便
    这样我们就可以通过jmx来描述一个控制系统,是针对进程级别的,因为是同进程,所以只要标志出是我们找的进程就可以,不用再过多的考虑权限的问题,同进程有最大的权限。
  3. 支持分布式任务
    也不用考虑分布式任务的问题,javaagent自动注册过来,我们不用纠结任务会跑在哪个机器上,只要看到多余的机器就是我们的新启动的进程。
  4. 减少数据的压力
    如果数据都在本地存储,本身是一个影响性能的事情, 通过socket可以把数据存储到远端,达到在不丢失数据的基础上还能尽量的保存更多的数据。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.6万
获赞与收藏
380

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消