seata 1.4.0 - seataServer之NettyRemotingServer选择客户端Channel发消息

io.seata.core.rpc.netty.AbstractNettyRemotingServer#sendSyncRequest(java.lang.String, java.lang.String, java.lang.Object)

RM_CHANNELS = {
    resourceId : {
        targetApplicationId : {
            targetIP : {
                targetPort : RpcContext
            }
        }
    }
}
1、通过resourceId获取集合,如果没获取到直接返回null
2、依次通过如下优先级尝试获取channel
    1、targetApplicationId.targetIP.targetPort
    2、targetApplicationId.targetIP
    3、targetApplicationId
targetApplicationId 由 GlobalTransactionScanner 的第一个参数指定,如 "account-gts-seata-example"
resourceId 由 DataSourceProxy 生成,如: "jdbc:mysql://127.0.0.1:3306/seata_client_test"

 

// io.seata.core.rpc.netty.ChannelManager#getChannel

public static Channel getChannel(String resourceId, String clientId) {
    Channel resultChannel = null;

    String[] clientIdInfo = readClientId(clientId); // 获取客户端信息

    if (clientIdInfo == null || clientIdInfo.length != 3) {
        throw new FrameworkException("Invalid Client ID: " + clientId);
    }

    String targetApplicationId = clientIdInfo[0];
    String targetIP = clientIdInfo[1];
    int targetPort = Integer.parseInt(clientIdInfo[2]);

    /*
        RM_CHANNELS = {
            resourceId : {
                targetApplicationId : {
                    targetIP : {
                        targetPort : RpcContext
                    }
                }
            }
        }
     */

    ConcurrentMap<String /* applicationId */, ConcurrentMap<String /* ip */, ConcurrentMap<Integer /* port */, RpcContext>>> applicationIdMap = RM_CHANNELS.get(resourceId); // 获取指定资源的worker列表

    if (targetApplicationId == null || applicationIdMap == null ||  applicationIdMap.isEmpty()) {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("No channel is available for resource[{}]", resourceId);
        }
        return null;
    }

    ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>> ipMap = applicationIdMap.get(targetApplicationId); // 指定应用

    if (ipMap != null && !ipMap.isEmpty()) {
        // Firstly, try to find the original channel through which the branch was registered. 即:完全匹配
        ConcurrentMap<Integer, RpcContext> portMapOnTargetIP = ipMap.get(targetIP);
        if (portMapOnTargetIP != null && !portMapOnTargetIP.isEmpty()) {
            RpcContext exactRpcContext = portMapOnTargetIP.get(targetPort); // 端口
            if (exactRpcContext != null) {
                Channel channel = exactRpcContext.getChannel();
                if (channel.isActive()) {
                    resultChannel = channel;
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Just got exactly the one {} for {}", channel, clientId);
                    }
                } else {
                    if (portMapOnTargetIP.remove(targetPort, exactRpcContext)) {
                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info("Removed inactive {}", channel);
                        }
                    }
                }
            }

            // The original channel was broken, try another one. 即:遍历端口列表,获取一个活跃的。
            if (resultChannel == null) {
                for (ConcurrentMap.Entry<Integer /* port */, RpcContext> portMapOnTargetIPEntry : portMapOnTargetIP
                    .entrySet()) {
                    Channel channel = portMapOnTargetIPEntry.getValue().getChannel();

                    if (channel.isActive()) { // 活跃
                        resultChannel = channel; //
                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info(
                                "Choose {} on the same IP[{}] as alternative of {}", channel, targetIP, clientId);
                        }
                        break;
                    } else {
                        if (portMapOnTargetIP.remove(portMapOnTargetIPEntry.getKey(),
                            portMapOnTargetIPEntry.getValue())) {
                            if (LOGGER.isInfoEnabled()) {
                                LOGGER.info("Removed inactive {}", channel);
                            }
                        }
                    }
                }
            }
        }

        // No channel on the this app node, try another one. 即:遍历ip列表,获取一个活跃的。
        if (resultChannel == null) {
            for (ConcurrentMap.Entry<String /* ip */, ConcurrentMap<Integer /* port */, RpcContext>> ipMapEntry : ipMap
                .entrySet()) {
                if (ipMapEntry.getKey().equals(targetIP)) { continue; }

                ConcurrentMap<Integer, RpcContext> portMapOnOtherIP = ipMapEntry.getValue();
                if (portMapOnOtherIP == null || portMapOnOtherIP.isEmpty()) {
                    continue;
                }

                for (ConcurrentMap.Entry<Integer /* port */, RpcContext> portMapOnOtherIPEntry : portMapOnOtherIP.entrySet()) {
                    Channel channel = portMapOnOtherIPEntry.getValue().getChannel();

                    if (channel.isActive()) {
                        resultChannel = channel;
                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info("Choose {} on the same application[{}] as alternative of {}", channel, targetApplicationId, clientId);
                        }
                        break;
                    } else {
                        if (portMapOnOtherIP.remove(portMapOnOtherIPEntry.getKey(),
                            portMapOnOtherIPEntry.getValue())) {
                            if (LOGGER.isInfoEnabled()) {
                                LOGGER.info("Removed inactive {}", channel);
                            }
                        }
                    }
                }
                if (resultChannel != null) { break; }
            }
        }
    }

    if (resultChannel == null) {
        resultChannel = tryOtherApp(applicationIdMap, targetApplicationId); // 即:遍历applicationId列表,获取一个活跃的。

        if (resultChannel == null) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("No channel is available for resource[{}] as alternative of {}", resourceId, clientId);
            }
        } else {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Choose {} on the same resource[{}] as alternative of {}", resultChannel, resourceId, clientId);
            }
        }
    }

    return resultChannel;

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值