arthas二次开发支持集群

132 阅读4分钟

背景

arthas是日常java问题诊断的工具。但是默认启动的时候不支持一个机器同时对多个进程进行分析,主要的点在于端口的占用。虽然可以通过指定端口做到多个进程的分析,这样带来2个问题。

  1. 使用不方便。命令行指定的参数太多了,当没有占用的时候直接attach。冲突的时候,后续得跟着一堆端口参数。
  2. 管理不方便。每个进程的启动都得指定多个端口,客户端退出后重连需要记得原来的端口号。

在这样的背景下,我们想用arthas作为集群层面的诊断工具。就得解决上面2个问题。

思路

因为是集群多机器的维度,想要使用方便,我们直接通过统一的页面链接去链接,这样去屏蔽操作的细节。管理的问题通过统一管理节点来操作。这样整体的服务变成了一个bs端。arthas本身有个bs的模式,就是tunnelserver。 我们可以复用这个逻辑,arthas指定好server地址,然后每次使用的时候就是在shell执行arthas的attach。并且把产生的agentid发送给tunnelserver,这样就可以服用tunnelserver的逻辑,在tunnelserver上进行操作。

tunnelserver也有一些不符合集群安全的。例如用户忘记了主动关闭,那么链接就会持续存在,在长进程的场景下,就会造成的链接的泄漏。所以要针对这个场景来改造一个链接超时停止的功能。

tunnelserver的流程

想要做到链接关闭就得了解服务的流程,这里的关闭指是不是单纯关闭链接,而是要同时把arthas的一些操作回退,例如watch这些,要把字节码注入的部分也要回退,arthas的agent已经有了stop命令,用来实现操作的回退,我们的思路就是统计具体socket链接的访问时间,做个定时任务,去管理链接,在链接不活跃的时间超过时,发送stop的命令,然后链接关闭。

这里看起来是一个超时的问题,但是我们并不能用心跳来替换,心跳超时是用来做链接管理。心跳超时的逻辑本身是希望链接服务的响应在线,例如发生了异常可以触发重连的操作,保证服务可以持续的运行。如果把心跳当做管理超时来用,很容易导致的服务不稳定。

要做上面的管理,我们需要了解启动的流程。

了解启动流程

arthas和tunnelserver之间是通过websocket协议来进行通讯。这个实现的好处是可以和浏览器同协议。这样就可以直接进行socket转发,而不用做协议的转化。

从流程上,我们来说明一下启动的过程。

  1. agent register
    agent attach的时候要指定server的地址,attach的时候就会触发一个agentRegister,server收到之后,把相关的信息记录在server中。并且通知在进程中,启动一个LocalTtyServer,用来处理tty的命令。这个很重要,也是后面阅读代码的时候很容易造成疑惑的地方。作用在后面讲

  2. startTunnel
    此时就可以打开浏览器,输入agent的id,进行链接。server收到这个命令后,根据id找到链接,发送startTunnel,agent收到这个命令之后,开始创建一个ForwardClient,他的作用就是创建一个localchannel去链接LocalTtyServer。在ForwardClient中,把和server创建的链接(这是一个新的链接)和localchannel进行对接。等于server发过来的任何信息,都通过ForwardClient通过localchannel转发给LocalTtyServer,LocalTtyServer的任何的消息也同样通过ForwardClient传递给server。这里的中转的方式见RelayHandler。

  3. serverRelay
    在创建完链接之后,server要把浏览器创建的websocket链接和agent创建的websocket链接,链接在一起。这里和 startTunnel中的方式一样,使用了RelayHandler。

改造

从上面的流程就可以看出,如果想要做管理,最好的点就是在第三步serverRelay 上进行改造。只要在RelayHandler里把除去心跳的发送去掉。剩下的响应数据用来做时间的计算,只要定时巡检超过一段时间,就通过链接往client端发送stop命令就可以。具体的代码就不在这里展示了。

总结

基于上面的启动流程,我们可以发现server端的管理要更好做一些。不过得注意控制好链接。TunnelClient和 ForwardClient是两个不同的client。在server注册的过程中,记录保留的是TunnelClient,对比我们想管理命令的话,需要把ForwardClient也记录下来。这样才能做细粒度的控制。