tm什么时候注册到seata server的
seata的核心类GlobalTransactionScanner,也是一个BeanPostProcessor,如果使用的是seata-spring-boot-start.jar这个包,spring会给我们自动装配GlobalTransactionScanner,如果用的是seata-all.jar这个包,就需要我们手动把GlobalTransactionScanner注册到spring ioc上去。 GlobalTransactionScanner又实现了InitializingBean这个接口,spring ioc在给我们创建GlobalTransactionScanner这个bean的时候,就会调用它的 afterPropertiesSet这个方法。
@Override
public void afterPropertiesSet ( ) {
if ( disableGlobalTransaction) {
if ( LOGGER. isInfoEnabled ( ) ) {
LOGGER. info ( "Global transaction is disabled." ) ;
}
return ;
}
initClient ( ) ;
}
initClient这个方法中就有去初始化TMClient和RMClient,这个方法里面我把一个日志打印和一些校验去掉了,留下主要内容。
private void initClient ( ) {
TMClient. init ( applicationId, txServiceGroup) ;
RMClient. init ( applicationId, txServiceGroup) ;
registerSpringShutdownHook ( ) ;
}
今天只关注TM的初始化过程,RM的初始化过程基本与TM初始化过程类似。
TMClient的init方法,首先获取了TmRpcClient 实例,然后调用了tmRpcClient的init方法。
public static void init ( String applicationId, String transactionServiceGroup) {
TmRpcClient tmRpcClient = TmRpcClient. getInstance ( applicationId, transactionServiceGroup) ;
tmRpcClient. init ( ) ;
}
TmRpcClient 的init方法,判断了有没有被初始化过,如果有就不再进行初始化,没有就调用了父类的init方法。
@Override
public void init ( ) {
registerProcessor ( ) ;
if ( initialized. compareAndSet ( false , true ) ) {
enableDegrade = CONFIG. getBoolean ( ConfigurationKeys. SERVICE_PREFIX + ConfigurationKeys. ENABLE_DEGRADE_POSTFIX) ;
super . init ( ) ;
}
}
TmRpcClient 的父类AbstractRpcRemotingClient的init方法,第一步启动netty服务端;第二步启动了一个定时任务,这个定时任务会判断跟server端的连接是否还有效,如果已经断开,就会重新连上,并且重新把tm注册到server;第二步开启了一个线程池,并且又调用了父类的init方法。我们的关注点就是第二步的定时任务。RmRpcClient也继承了AbstractRpcRemotingClient。
@Override
public void init ( ) {
clientBootstrap. setChannelHandlers ( new ClientHandler ( ) ) ;
clientBootstrap. start ( ) ;
timerExecutor. scheduleAtFixedRate ( new Runnable ( ) {
@Override
public void run ( ) {
clientChannelManager. reconnect ( getTransactionServiceGroup ( ) ) ;
}
} , SCHEDULE_DELAY_MILLS, SCHEDULE_INTERVAL_MILLS, TimeUnit. MILLISECONDS) ;
if ( NettyClientConfig. isEnableClientBatchSendRequest ( ) ) {
mergeSendExecutorService = new ThreadPoolExecutor ( MAX_MERGE_SEND_THREAD,
MAX_MERGE_SEND_THREAD,
KEEP_ALIVE_TIME, TimeUnit. MILLISECONDS,
new LinkedBlockingQueue < > ( ) ,
new NamedThreadFactory ( getThreadPrefix ( ) , MAX_MERGE_SEND_THREAD) ) ;
mergeSendExecutorService. submit ( new MergedSendRunnable ( ) ) ;
}
super . init ( ) ;
}
这个定时任务是每10s执行一次,初始化60s后才开始执行。调用了clientChannelManager.reconnect方法,去掉校验看,先获取到seata server的地址,并且挨个调用acquireChannel方法
void reconnect ( String transactionServiceGroup) {
List< String> availList = null;
try {
availList = getAvailServerList ( transactionServiceGroup) ;
} catch ( Exception e) {
LOGGER. error ( "Failed to get available servers: {}" , e. getMessage ( ) , e) ;
return ;
}
for ( String serverAddress : availList) {
try {
acquireChannel ( serverAddress) ;
} catch ( Exception e) {
LOGGER. error ( "{} can not connect to {} cause:{}" , FrameworkErrorCode. NetConnect. getErrCode ( ) , serverAddress, e. getMessage ( ) , e) ;
}
}
}
acquireChannel方法,首先查看channel是否已经存在并且是alive状态,如果是直接返回,如果否就创建一个把锁,调用doConnect方法。
Channel acquireChannel ( String serverAddress) {
Channel channelToServer = channels. get ( serverAddress) ;
if ( channelToServer != null) {
channelToServer = getExistAliveChannel ( channelToServer, serverAddress) ;
if ( channelToServer != null) {
return channelToServer;
}
}
if ( LOGGER. isInfoEnabled ( ) ) {
LOGGER. info ( "will connect to " + serverAddress) ;
}
channelLocks. putIfAbsent ( serverAddress, new Object ( ) ) ;
synchronized ( channelLocks. get ( serverAddress) ) {
return doConnect ( serverAddress) ;
}
}
doConnect,首先是获取到registerRMRequest 对象,然后从nettyClientKeyPool对象池中获取到channel,获取不到就会调用工厂去创建,在NettyClientChannelManager的构造函数中创建的nettyClientKeyPool对象,并把NettyPoolableFactory对象传给了它的构造函数。
private Channel doConnect ( String serverAddress) {
Channel channelToServer = channels. get ( serverAddress) ;
if ( channelToServer != null && channelToServer. isActive ( ) ) {
return channelToServer;
}
Channel channelFromPool;
try {
NettyPoolKey currentPoolKey = poolKeyFunction. apply ( serverAddress) ;
NettyPoolKey previousPoolKey = poolKeyMap. putIfAbsent ( serverAddress, currentPoolKey) ;
if ( previousPoolKey != null && previousPoolKey. getMessage ( ) instanceof RegisterRMRequest ) {
RegisterRMRequest registerRMRequest = ( RegisterRMRequest) currentPoolKey. getMessage ( ) ;
( ( RegisterRMRequest) previousPoolKey. getMessage ( ) ) . setResourceIds ( registerRMRequest. getResourceIds ( ) ) ;
}
channelFromPool = nettyClientKeyPool. borrowObject ( poolKeyMap. get ( serverAddress) ) ;
channels. put ( serverAddress, channelFromPool) ;
} catch ( Exception exx) {
LOGGER. error ( "{} register RM failed." , FrameworkErrorCode. RegisterRM. getErrCode ( ) , exx) ;
throw new FrameworkException ( "can not register RM,err:" + exx. getMessage ( ) ) ;
}
return channelFromPool;
}
NettyPoolableFactory的makeObject方法,这里面真正去建立连接并把消息传送了出去
@Override
public Channel makeObject ( NettyPoolKey key) {
InetSocketAddress address = NetUtil. toInetSocketAddress ( key. getAddress ( ) ) ;
if ( LOGGER. isInfoEnabled ( ) ) {
LOGGER. info ( "NettyPool create channel to " + key) ;
}
Channel tmpChannel = clientBootstrap. getNewChannel ( address) ;
long start = System. currentTimeMillis ( ) ;
Object response;
Channel channelToServer = null;
if ( key. getMessage ( ) == null) {
throw new FrameworkException ( "register msg is null, role:" + key. getTransactionRole ( ) . name ( ) ) ;
}
try {
response = rpcRemotingClient. sendAsyncRequestWithResponse ( tmpChannel, key. getMessage ( ) ) ;
if ( ! isRegisterSuccess ( response, key. getTransactionRole ( ) ) ) {
rpcRemotingClient. onRegisterMsgFail ( key. getAddress ( ) , tmpChannel, response, key. getMessage ( ) ) ;
} else {
channelToServer = tmpChannel;
rpcRemotingClient. onRegisterMsgSuccess ( key. getAddress ( ) , tmpChannel, response, key. getMessage ( ) ) ;
}
} catch ( Exception exx) {
if ( tmpChannel != null) {
tmpChannel. close ( ) ;
}
throw new FrameworkException (
"register " + key. getTransactionRole ( ) . name ( ) + " error, errMsg:" + exx. getMessage ( ) ) ;
}
return channelToServer;
}