【RPC】 ---- 基于ZooKeeper为注册中心实现的RPC

本文介绍了基于ZooKeeper实现的RPC服务注册、发现和负载均衡的详细过程。服务提供者启动时注册服务到ZooKeeper,消费者通过服务名获取IP列表并选择服务器。还探讨了动态感知服务器状态,包括上线和下线的处理。文章总结了该方案的优点,并提供了项目源码链接。
摘要由CSDN通过智能技术生成

一、原理

一个能够动态注册和获取服务信息的地方,来统一管理服务名称和其对应的服务器列表信息,称之为服务配置中心。如图所示

image-20210612234403793
  • 服务提供在启动时,将其提供的服务名称、服务器地址注册到服务配置中心
  • 服务消费者通过服务配置中心来获得需要调用的服务的机器列表,通过相应的负载均衡算法,选取其中一台服务器进行调用
  • 当服务器宕机或者下线时,相应的机器需要能够动态地从服务配置中心里面移除,并通知相应地服务消费者

二、统一配置管理

主要把服务名以及服务相关的服务器IP地址注册到注册中心,在使用服务的时候,只需要根据服务名,就可以得到所有服务地址IP,然后根据一定的负载均衡策略来选择IP地址

image-20210615234836712

1、服务的注册

关于服务的注册,其实就是把服务和IP注册到ZooKeeper节点中。

  • 服务名用的是永久节点
  • 服务IP地址用的是临时节点(为后面对节点进行注册监听做铺垫)

(用端口号的不同区别不同的机器)

image-20210615235851021

CuratorUtils类提供createPersistentNode()createEphemeralNode()方法

// 创建服务名永久节点PERSISTENT
public static void createPersistentNode(CuratorFramework zkClient, String path) {
   
   try {
   
      // 永久节点已存在
      if (PERSISTENT_REGISTERED_PATH_SET.contains(path) || zkClient.checkExists().forPath(path) != null) {
   
         logger.info("永久节点已经存在,永久节点是:[{}]", path);
      } else {
   
         // 永久节点不存在,则创建永久节点
         //eg: /MyRPC/com.whc.rpc.api.UserService
         zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path);
         logger.info("永久节点成功被创建,永久节点是:[{}]", path);
      }
      PERSISTENT_REGISTERED_PATH_SET.add(path);
   } catch (Exception e) {
   
      logger.error("创建永久节点失败[{}]", path);
   }
}

// 创建服务地址为临时节点EPHEMERAL
// 临时节点,当客户端与 Zookeeper 之间的连接或者 session 断掉时会被zk自动删除。开源 Dubbo 框架,使用的就是临时节点
// 优点: 当服务节点下线或者服务节点不可用,Zookeeper 会自动将节点地址信息从注册中心删除
public static void createEphemeralNode(CuratorFramework zkClient, String path) {
   
   try {
   
      // 临时节点已存在
      if (EPHEMERAL_REGISTERED_PATH_SET.contains(path) || zkClient.checkExists().forPath(path) != null) {
   
         logger.info("临时节点已经存在,临时节点是:[{}]", path);
      } else {
   
         // 临时节点不存在,则创建临时节点
         //eg: /MyRPC/com.whc.rpc.api.UserService/127.0.0.1:9000
         zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path);
         logger.info("临时节点成功被创建,临时节点是:[{}]", path);
      }
      EPHEMERAL_REGISTERED_PATH_SET.add(path);
   } catch (Exception e) {
   
      logger.error("创建临时节点失败[{}]", path);
   }
}

2、服务的发现

服务的发现就是根据服务名来获取ZooKeeper节点中的IP地址

CuratorUtils类提供了getChildrenNodes()方法

// 获取一个节点下的孩子节点
public static List<String> getChildrenNodes(CuratorFramework zkClient, String rpcServiceName) {
   
   if (SERVICE_ADDRESS_MAP.containsKey(rpcServiceName)) {
   
      return SERVICE_ADDRESS_MAP.get(rpcServiceName);
   }
   List<String> result = null;
   String servicePath = ZK_REGISTER_ROOT_PATH + "/" + rpcServiceName;
   try {
   <
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值