源码篇--Nacos服务--中章(8):Nacos服务端感知客户端注册-2


前言

当客户端的实例注册到nacos 集群中某一台节点后,此时需要给集群中其它的节点推送节点注册实例信息,从而保证数据的最终一致性协议。集群的节点之间通过建立grpc 连接实现消息的发送,本文对服务端nacos 集群间节点grpc 连接建立,进行介绍,服务端版本 3.0.13。


一、服务端 grpc 通道:

nacos 服务端集群内的节点,需要建立连接,从而保证节点中数据的一致性;nacos 对实例的注册和获取采用了是AP模式(可用性+分区容错性),要保证nacos 集群节点数据的最终一致性,在nacos 的内部实现中使用了distro协议。

distro协议是 Nacos 社区自研的一种 AP 分布式协议,是面向临时实例设计的一种分布式协议其保证了在某些 Nacos 节点宕机后,整个临时实例处理系统依旧可以正常工作。作为一种有状态的中间件应用的内嵌协议,Distro 保证了各个 Nacos 节点对于海量注册请求的统一协调和存储。

二、 grpc 通道建立过程:

集群内节点通道的建立是由 ClusterRpcClientProxy负责的;

2.1 ClusterRpcClientProxy bean 后置处理:

 @Autowired
 ServerMemberManager serverMemberManager;
 
 /**
  * init after constructor.
  */
 @PostConstruct
 public void init() {
     try {
         // 订阅者注册
         NotifyCenter.registerSubscriber(this);
         // 获取集群内除了自己的节点
         List<Member> members = serverMemberManager.allMembersWithoutSelf();
         // 建立grpc 连接
         refresh(members);
         Loggers.CLUSTER
                 .info("[ClusterRpcClientProxy] success to refresh cluster rpc client on start up,members ={} ",
                         members);
     } catch (NacosException e) {
         Loggers.CLUSTER.warn("[ClusterRpcClientProxy] fail to refresh cluster rpc client,{} ", e.getMessage());
     }
     
 }

2.2 refresh 通道建立:

获取到集群内的其它节点,然后进行遍历分别与其建连接,最后关闭之前建立的过时连接;

/**
* init cluster rpc clients.
 *
 * @param members cluster server list member list.
 */
private void refresh(List<Member> members) throws NacosException {
    
    //ensure to create client of new members
    for (Member member : members) {
        // grpc 连接建立
        createRpcClientAndStart(member, ConnectionType.GRPC);
    }
    
    //shutdown and remove old members.
    // 关闭之前建立的旧连接
    Set<Map.Entry<String, RpcClient>> allClientEntrys = RpcClientFactory.getAllClientEntries();
    Iterator<Map.Entry<String, RpcClient>> iterator = allClientEntrys.iterator();
    List<String> newMemberKeys = members.stream().map(this::memberClientKey).collect(Collectors.toList());
    while (iterator.hasNext()) {
        Map.Entry<String, RpcClient> next1 = iterator.next();
        if (next1.getKey().startsWith("Cluster-") && !newMemberKeys.contains(next1.getKey())) {
            Loggers.CLUSTER.info("member leave,destroy client of member - > : {}", next1.getKey());
            RpcClient client = RpcClientFactory.getClient(next1.getKey());
            if (client != null) {
                RpcClientFactory.getClient(next1.getKey()).shutdown();
            }
            iterator.remove();
        }
    }
    
}

2.3 createRpcClientAndStart 通道建立:

获取到节点的ip 和端口,然后在client.start() 的 connectToServer(serverInfo) 进行通道的建立;

private void createRpcClientAndStart(Member member, ConnectionType type) throws NacosException {
   Map<String, String> labels = new HashMap<>(2);
    labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_CLUSTER);
    // "Cluster-"+ip + ":" + port;
    String memberClientKey = memberClientKey(member);
    // 创建GrpcClusterClient 客户端
    RpcClient client = buildRpcClient(type, labels, memberClientKey);
    if (!client.getConnectionType().equals(type)) {
        Loggers.CLUSTER.info("connection type changed,destroy client of member - > : {}", member);
        RpcClientFactory.destroyClient(memberClientKey);
        client = buildRpcClient(type, labels, memberClientKey);
    }
    
    if (client.isWaitInitiated()) {
        Loggers.CLUSTER.info("start a new rpc client to member - > : {}", member);
        
        //one fixed server
        client.serverListFactory(new ServerListFactory() {
            @Override
            public String genNextServer() {
                return member.getAddress();
            }
            
            @Override
            public String getCurrentServer() {
                return member.getAddress();
            }
            
            @Override
            public List<String> getServerList() {
                return CollectionUtils.list(member.getAddress());
            }
        });
        // 连接建立
        client.start();
    }
}

2.3 client.start() 通道建立:

集群内节点连接的建立,同客户端与服务端连接建立过程相同,这里不在进行累述;
可通过:源码篇–Nacos服务–中章(5):Nacos客户端启动-实例注册-grpc连接建立,中的 2.3.2.2 start 长连接建立 ;
源码篇–Nacos服务–中章(6):Nacos客户端启动-grpc通道建立&客户端服务信息获取(故障转移)细节 查看连接的详细建立过程;


总结

本文对集群内节点之间通过建立grpc 连接过程进行介绍。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值