**(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 方法,所以我们跟到父类去看一下这俩方法。
构造方法中
- 将消息执行器传给了父类 AbstractRpcRemoting,同时初始化了clientBootstrap 和clientChannelManager,父类中也是将消息执行器做了一步赋值操作。
- clientBootstrap 实现了RemotingService 接口中的 start 和 shutDown方法,用于控制netty服务的启停。
- clientChannelManager 用于管理netty通道对象。 ps:由于我对netty只了解皮毛,这里也不深入写了,以免误入,有兴趣的同学可以去阅读以下,代码位置在 : io.seata.core.rpc.netty.RpcClientBootstrap 和 io.seata.core.rpc.netty.NettyClientChannelManager
接下来我们看 AbstractRpcRemoting 的init方法。
- 给引导程序创建个渠道
- 启动引导程序
- 启动一个定时器, 不断尝试连接Server,启动延迟 60s,每10s重试一次
- 创建合并分支执行器
- 调用父类的初始化方法
需要注意的点, reconnect 会根据 事务分组名, 找到改分组下的所有服务器的ip+端口。里面涉及seata注册中心的实现,不再过多叙述,
在 AbstractRpcRemoting 的 init 方法中,又是开启了一个定时任务,该定时任务主要是用于定时清除 futures 已过期的 futrue,futures 是保存发送请求需要返回结果的 future 对象,该对象有个超时时间,过了超时时间就会自动抛异常,因此需要定时清除已过期的 future 对象。
总结:
TmClient 初始化的实质是创建了一个TmRpcClient , 并初始化。
TmRpcClient 的初始化,会创建两个定时任务(重连server和清除过期future), 一个引导程序(控制netty启停)两个线程池(一个和server交互,一个用于合并分支请求)