1.1 TMClient 启动流程分析

327 阅读3分钟

**(1.0 客户端启动流程分析) ** 已经描述, 客户端启动时,会触发TMCLient和RMClient的初始化动作,本文试分析TMClient启动过程所进行的操作。

1.初始化操作

! TMCLient的初始化其实就是TmRpcClient的初始化 我们可以看到,通过传入的applicationId(针对我们项目这个就是applicationName)和事务组,创建了一个TmRpcClient, 然后调用了该对象的init方法。

让我们来看TmRpcClient的创建: 一个经典的DCL,我们可以看到,TmRpcClient的创建需要两个关键参数,NettyClient配置类和一个线程池。

1.nettyClientConfig 从名字我们也能看出,这个类就是定义了一些常量,一些写死的,一些是从配置文件里拿的,此处不再过多叙述

2.messaeExcutor 这个线程池主要用于处理各种与服务端的消息交互。

2.TmRpcClient的创建过程

我们先来看一下TmRpcClient的继承关系 我们可以看到,Tm和Rm类似,都是继承了AbstractRpcRemotingClient,这个类又继承了AbstractRpcRemoting。

让我们跟进TmRpcClient 的 内部。首先让我们查看TmRpcClient的构造方法和初始化。

我们可以看到 TmRpcClient的构造方法和初始化都是调用了父类 AbstractRpcRemotingClient 方法,所以我们跟到父类去看一下这俩方法。

构造方法中

  1. 将消息执行器传给了父类 AbstractRpcRemoting,同时初始化了clientBootstrap 和clientChannelManager,父类中也是将消息执行器做了一步赋值操作。
  2. clientBootstrap 实现了RemotingService 接口中的 start 和 shutDown方法,用于控制netty服务的启停。
  3. clientChannelManager 用于管理netty通道对象。 ps:由于我对netty只了解皮毛,这里也不深入写了,以免误入,有兴趣的同学可以去阅读以下,代码位置在 : io.seata.core.rpc.netty.RpcClientBootstrap 和 io.seata.core.rpc.netty.NettyClientChannelManager

接下来我们看 AbstractRpcRemoting 的init方法。

  1. 给引导程序创建个渠道
  2. 启动引导程序
  3. 启动一个定时器, 不断尝试连接Server,启动延迟 60s,每10s重试一次
  4. 创建合并分支执行器
  5. 调用父类的初始化方法 需要注意的点, reconnect 会根据 事务分组名, 找到改分组下的所有服务器的ip+端口。里面涉及seata注册中心的实现,不再过多叙述,

在 AbstractRpcRemoting 的 init 方法中,又是开启了一个定时任务,该定时任务主要是用于定时清除 futures 已过期的 futrue,futures 是保存发送请求需要返回结果的 future 对象,该对象有个超时时间,过了超时时间就会自动抛异常,因此需要定时清除已过期的 future 对象。

总结:

TmClient 初始化的实质是创建了一个TmRpcClient , 并初始化。

TmRpcClient 的初始化,会创建两个定时任务(重连server和清除过期future), 一个引导程序(控制netty启停)两个线程池(一个和server交互,一个用于合并分支请求)