Seata源码解析6——事务协调者的启动(4)

本文深入解析Seata事务协调者启动过程,涵盖DefaultServerMessageListenerImpl、ChannelManager、AbstractRpcRemotingClient的实现细节,包括通道管理、消息监听、客户端连接管理和心跳处理等方面。
摘要由CSDN通过智能技术生成
前言

上一篇文章中,我们讲解了启动中的RpcServer类。这个类的顶级父类AbstractRpcRemoting是一个抽象类,封装了Netty的各种能力。除了RpcServer的直接父类AbstractRpcRemotingServer继承了它,还有一个AbstractRpcRemotingClient类也继承了它。在这一篇里,我们会继续把这个Client的抽象类也讲解了。

另外,RpcServer中还调用了ChannelManagerDefaultServerMessageListenerImpl,这两个类在本篇也会做讲解。

####ChannelManager

ChannelManager 是服务端 channel 的管理器,服务端每次和客户端通信,都需要从 ChannelManager 中获取客户端对应的 channel,它用于保存 TM 和 RM 客户端 channel 的缓存结构。

主要有3个用户缓存的Map:

//channel为key,对应的上下文为value
ConcurrentMap<Channel, RpcContext> IDENTIFIED_CHANNELS

//嵌套很多,它的key分别是resourceId -> applicationId -> ip -> port,最后一层Map的value是RpcContext
  ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<Integer,
        RpcContext>>>>
        RM_CHANNELS
          
//它的key分别是ip+appname -> port        
ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>> TM_CHANNELS

主要逻辑就是channel的增删改查:

1.registerRMChannel

名字叫register,其实就是新增嘛

//注册RMchannel,就是新增
public static void registerRMChannel(RegisterRMRequest resourceManagerRequest, Channel channel)
    throws IncompatibleVersionException {
   
  //检查版本,是一个todo的方法
    Version.checkVersion(resourceManagerRequest.getVersion());
  //获取数据库key集合,多个用英文逗号隔开,这里知识spilt了一下
    Set<String> dbkeySet = dbKeytoSet(resourceManagerRequest.getResourceIds());
    RpcContext rpcContext;
  //如果缓存里没有,则构建一个rpc上下文
    if (!IDENTIFIED_CHANNELS.containsKey(channel)) {
   
        rpcContext = buildChannelHolder(NettyPoolKey.TransactionRole.RMROLE, resourceManagerRequest.getVersion(),
            resourceManagerRequest.getApplicationId(), resourceManagerRequest.getTransactionServiceGroup(),
            resourceManagerRequest.getResourceIds(), channel);
        rpcContext.holdInIdentifiedChannels(IDENTIFIED_CHANNELS);
    } else {
   
      //如果缓存里已经存在,更新一下dbkey就好了,resource是一个set,自动去重
        rpcContext = IDENTIFIED_CHANNELS.get(channel);
        rpcContext.addResources(dbkeySet);
    }
    if (null == dbkeySet || dbkeySet.isEmpty()) {
    return; }
  //缓存到RM对应的Map里面
    for (String resourceId : dbkeySet) {
   
        String clientIp;
        ConcurrentMap<Integer, RpcContext> portMap = RM_CHANNELS.computeIfAbsent(resourceId, resourceIdKey -> new ConcurrentHashMap<>())
                .computeIfAbsent(resourceManagerRequest.getApplicationId(), applicationId -> new ConcurrentHashMap<>())
                .computeIfAbsent(clientIp = getClientIpFromChannel(channel), clientIpKey -> new ConcurrentHashMap<>());

        rpcContext.holdInResourceManagerChannels(resourceId, portMap);
      //更新里面嵌套的子Map
        updateChannelsResource(resourceId, clientIp, resourceManagerRequest.getApplicationId());
    }

}

2.registerTMChannel

注册TM的channel,逻辑也相似

public static void registerTMChannel(RegisterTMRequest request, Channel channel)
        throws IncompatibleVersionException {
   
    Version.checkVersion(request.getVersion());
  //创建一个上下文
    RpcContext rpcContext = buildChannelHolder(NettyPoolKey.TransactionRole.TMROLE, request.getVersion(),
        request.getApplicationId(),
        request.getTransactionServiceGroup(),
        null, channel);
    rpcContext.holdInIdentifiedChannels(IDENTIFIED_CHANNELS);
  //创建唯一标识
    String clientIdentified = rpcContext.getApplicationId() + Constants.CLIENT_ID_SPLIT_CHAR
        + getClientIpFromChannel(channel);
  //保存TM的channel到对应的Map
    TM_CHANNELS.putIfAbsent(clientIdentified, new ConcurrentHashMap<Integer, RpcContext>());
    ConcurrentMap<Integer, RpcContext
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值