第3章:Dubbo注册中心

1.注册中心工作原理在这里插入图片描述

Provider:服务提供者

Consumer:服务消费者

Registry:注册中心

Dubbo-admin:服务治理中心

  • Provider启动时,会向Registry写入自己的元数据信息,同时会订阅配置元数据信息。
  • Consumer启动时,也会向Registry写入自己的元数据信息,并订阅服务提供者、路由和配置元信息。
  • Dubbo-admin启动时,会同时订阅所有Consumer、Provider、路由和配置元信息。
  • 当有Provider离开或有新的Provider加入时,注册中心的Provider目录会发生变化,变化会通知Consumer、Dubbo-admin。
  • 当Consumer发起服务调用时,会异步将调用、统计信息等上报给监控中心(dubbo-monitor-simple)

元数据:IP、端口、权重、应用名

2.注册中心选型

2.1 Zookeeper

主要是利用Zookeeper的树型结构+发布/订阅机制,结构有四层:root(根节点,对应示例中的dubbo)、service(接口名字,对应示例中的com.foo.BarService)、四种服务目录(providers、consumers、routers、configurators)、在服务分类节点下是具体Dubbo服务URL,示例如下:
在这里插入图片描述

树型结构示意图:
在这里插入图片描述

2.2 Redis

利用Redis5种基本数据机构中的字典+发布/订阅功能实现注册中心的功能

Redis的key为root、service、Type(providers、consumers、routers、configurators)

Redis的value为一个Map,Map的key为URL,value为权重
在这里插入图片描述

3.缓存机制

缓存的存在就是用空间换时间,consumer或dubbo-admin从注册中心获取信息后会做本地缓存,避免每次都从注册中心获取数据,降低了由于网络传输导致的性能开销,也降低了注册中心的压力。

扫描二维码关注公众号,回复: 13506588 查看本文章

本地缓存的实现就是一个ConcurrentHashMap

ConcurrentMap<URL,Map<String,List<URL>> notified

外层的key是消费者的URL,内层Map的key是分类(providers,consumers,routers,configurators),value是对应的服务列表

3.1 缓存加载

注册中心的信息会在本地磁盘中保存一份Properties文件,在服务初始化时,会加载这份文件到内存中

InputStream in = null;
try {
    
    
	in = new FileInputStream(file);
	properties.load(in);
}

3.2 缓存的保存与更新

分为同步保存和异步保存

异步保存通过线程池异步保存

registryCacheExecutors.execute(new SaveProperties(version));//异步保存,通过一个AtomicLong表示版本号,保证数据是最新

4.重试机制

Dubbo维持了几个发布/订阅失败的URL集合,会有一个ScheduleExecutorService线程池,固定时间间隔发起发布/订阅重试
在这里插入图片描述

5.设计模式

5.1 模版方法模式

注册中心的逻辑部分使用了模版方法模式
在这里插入图片描述

未实现的抽象模版方法
在这里插入图片描述

模版方法调用
在这里插入图片描述

5.2 工厂模式

注册中心都是通过工厂来创建的,工厂的类图如下
在这里插入图片描述

为了避免重复创建注册中心,把注册中心加入了缓存,在创建注册中心的时候,先去看缓存中有没有,有就直接返回,没有就创建注册中心,加入到本地缓存中

@Override
public Registry getRegistry(URL url) {
    
    
  url = url.setPath(RegistryService.class.getName())
    .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
    .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
  String key = url.toServiceStringWithoutResolving();
  // Lock the registry access process to ensure a single instance of the registry
  LOCK.lock();
  try {
    
    
    Registry registry = REGISTRIES.get(key);
    if (registry != null) {
    
    
      return registry;
    }
    registry = createRegistry(url);
    if (registry == null) {
    
    
      throw new IllegalStateException("Can not create registry " + url);
    }
    REGISTRIES.put(key, registry);
    return registry;
  } finally {
    
    
    // Release the lock
    LOCK.unlock();
  }
}

猜你喜欢

转载自blog.csdn.net/weixin_42478399/article/details/121460112