前言
上一篇文章中,我们讲解了启动中的RpcServer类。这个类的顶级父类AbstractRpcRemoting
是一个抽象类,封装了Netty的各种能力。除了RpcServer的直接父类AbstractRpcRemotingServer
继承了它,还有一个AbstractRpcRemotingClient
类也继承了它。在这一篇里,我们会继续把这个Client的抽象类也讲解了。
另外,RpcServer中还调用了ChannelManager
、DefaultServerMessageListenerImpl
,这两个类在本篇也会做讲解。
####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