LCN分布式事务学习3-服务端(TM)代码逻辑梳理

1. TM启动流程

TM是一个springboot项目,在springboot启动时,会通过一个applicationRunner启动TM服务,即启动一个基于netty网络框架的服务端。

NettyRpcServerChannelInitializer类的源码如下:

这里重点关注下RpcAnswerHandler处理器。

RpcAnswer是一个接口,有两个实现:

  • ServerRpcAnswer
  • ClientRpcAnswer

TM端用的是ServerRpcAnswer实现类。重点需要关注callback方法。在callback方法中,将具体的业务处理交给一个业务线程池处理。源码如下:

public void callback(RpcCmd rpcCmd) {
        executorService.submit(() -> {
            try {
                //将RpcCmd对象转换成TransactionCmd
                TransactionCmd transactionCmd = parser(rpcCmd);
                String action = transactionCmd.getMsg().getAction();
                //根据类型(createGroup、joinGroup、notifyGroup)获取具体的执行类
                RpcExecuteService rpcExecuteService = rpcBeanHelper.loadManagerService(transactionCmd.getType());
                System.out.println("RpcExecuteService = "+rpcExecuteService);
                MessageDto messageDto = null;
                try {
                    Serializable message = rpcExecuteService.execute(transactionCmd);
                    messageDto = MessageCreator.okResponse(message, action);
                } catch (Throwable e) {
                    log.error("rpc execute service error. action: " + action, e);
                    messageDto = MessageCreator.failResponse(e, action);
                } finally {
                    // 对需要响应信息的请求做出响应
                    if (rpcCmd.getKey() != null) {
                        assert Objects.nonNull(messageDto);
                        try {
                            messageDto.setGroupId(rpcCmd.getMsg().getGroupId());
                            rpcCmd.setMsg(messageDto);
                            rpcClient.send(rpcCmd);
                        } catch (RpcException ignored) {
                        }
                    }
                }
            } catch (Throwable e) {
                if (rpcCmd.getKey() != null) {
                    log.info("send response.");
                    String action = rpcCmd.getMsg().getAction();
                    // 事务协调器业务未处理的异常响应服务器失败
                    rpcCmd.setMsg(MessageCreator.serverException(action));
                    try {
                        rpcClient.send(rpcCmd);
                        log.info("send response ok.");
                    } catch (RpcException ignored) {
                        log.error("requester:{} dead.", rpcCmd.getRemoteKey());
                    }
                }
            }
        });
    }

2. TM创建事务组

如果是创建事务组,那么ServerRpcAnswer的callback方法中的RpcExecuteService即为CreateGroupExecuteService。

只做了一件事,即将事务组id存入Redis中,并设置了过期时间。在Redis中,被存储成一个hash,key为tm:group:groupID,键为root,值为空。

创建事务组时,客户端向服务端发送的数据如下所示:

{"key":"573f860ad9e536",
"msg":{"action":"createGroup","groupId":"573f860ad9e537","state":100},
"remoteKey":"/127.0.0.1:25633"}

服务端想客户端返回的数据如下所示:

{"key":"573f860ad9e536",
"msg":{"action":"createGroup","groupId":"573f860ad9e537","state":200},
"remoteKey":"/127.0.0.1:25633"}

3. TM加入事务组

如果是加入事务组,那么ServerRpcAnswer的callback方法中的RpcExecuteService即为JoinGroupExecuteService。

只做了一件事,将事务信息保存在Redis中。key为tm:group:groupID,键为事务对应的unitId,值为事务相关信息。

加入事务组时,客户端请求数据为:

{
	"key": "573f8609f99537",
	"msg": {
		"action": "joinGroup",
		"data": {
			"groupId": "573f860ad9e537",
			"transactionState": 1,
			"unitId": "fa8dc78c9b7ad90a30bc4066226749b5",
			"unitType": "lcn"
		},
		"groupId": "573f860ad9e537",
		"state": 100
	},
	"remoteKey": "/127.0.0.1:25632"
}

服务端响应数据为:

{"key":"573f8609f99537",
"msg":{"action":"joinGroup","groupId":"573f860ad9e537","state":200},
"remoteKey":"/127.0.0.1:25632"}

4. TM通知事务组

如果是通知事务组,那么ServerRpcAnswer的callback方法中的RpcExecuteService即为NotifyGroupExecuteService。

如果事务状态为1,表示需要commit,如果事务状态为0则需要rollback,并返回状态。但最终都会调用如下方法:

从Redis中获取该事务组对应的子事务,并遍历子事务。获取到客户端的ip地址,向客户端发送消息。如果发送失败,则将信息保存到数据库中。

通知事务组时,客户端发送的数据为:

{"key":"573f860879e537",
"msg":{"action":"notifyGroup","data":{"groupId":"573f860ad9e537","state":0},"groupId":"573f860ad9e537","state":100},
"remoteKey":"/127.0.0.1:25633"}

响应结果为:

{"key":"573f860879e537",
"msg":{"action":"notifyGroup","data":0,"groupId":"573f860ad9e537","state":200},
"remoteKey":"/127.0.0.1:25633"}

5. 总结

TC向TM发送的数据包括创建事务组、加入事务组、通知事务组三类消息。

当TM接收到这三类消息后,在ServerRpcAnswer类中,调用对应类型的处理器进行处理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值