Dubbo点滴(5)之服务注册中心

首先DUBBO本质上是一款RPC框架,不可缺少的2个角色:服务提供者和服务消费者。

已经剖析了服务端暴露端口过程。本文简单说下注册中心。

1.注册中心是什么玩意

这是官网提供的图例

通过图例,可以看出消费者和提供者并不是直接通信的,中间有个第三者,就是注册中心。这种结构,可以实现消费者和提供者两者的依赖,和参数信息的集群化。所以这带来了几个问题。

  1. 服务注册
  2. 服务发现
  3. 服务订阅
  4. 服务通知

2. 服务暴露及服务注册过程

Dubbo点滴(4)之暴露服务解析》已经剖析了dubbo协议具体打开网络端口过程。本节内容会隐去这部分内容。因为一个完整的服务暴露,主要涉及2部分内容,1)打开端口等待消费者连接;2)将服务信息登记到注册中心,以告知消费者可以连接了。

有3点需要说明:

1)首先,根据条件判断会暴露一个injvm本地服务(step 6);

InjvmProtocol协议完成,主要供同一JVM种的消费者调用,提供RPC效率。

2) 为服务暴露一个dubbo服务(step 12),一般为DubboProtocol完成

3)step 12提供的的服务,注册到注册中心(step 13-step 23)。这一步是本文的剖析重点。

3.认识注册中心

该图是DUBBO的总体结构图。重点停留在Resistry层。比较重要的是几个组件

ZookeeperRegistry :负责与zookeeper进行交互

RegistryProtocol :从注册中心获取可用服务,或者将服务注册到zookeeper,然后提供服务或者提供调用代理。

RegistryDirectory :维护着所有可用的远程Invoker或者本地的Invoker。这个类实现了NotifyListner。

NotifyListener :负责RegistryDirectory和ZookeeperRegistry的通信。

FailbackRegistry:继承自Registry,实现了失败重试机制。

4. 注册中心数据模型

流程说明:

  • 服务提供者启动时

    • 向/dubbo/com.foo.BarService/providers目录下写入自己的URL地址。
  • 服务消费者启动时
    • 订阅/dubbo/com.foo.BarService/providers目录下的提供者URL地址。
    • 并向/dubbo/com.foo.BarService/consumers目录下写入自己的URL地址。
  • 监控中心启动时
    • 订阅/dubbo/com.foo.BarService目录下的所有提供者和消费者URL地址。

4.Registry 结构树

ZookeeperRegistry是常见的注册中心实现方案,由ZookeeperRegistryFactory负责构造。

AbstractRegistry这个类主要存储的是已经注册的服务接口,已经订阅的服务接口和已经收到通知的接口的URL,不能直接调用。

public abstract class AbstractRegistry implements Registry {

    // 本地磁盘缓存,其中特殊的key值.registies记录注册中心列表,其它均为notified服务提供者列表
    private final Properties properties = new Properties();
    // 文件缓存定时写入
    private final ExecutorService registryCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveRegistryCache", true));
    //是否是同步保存文件
    private final boolean syncSaveFile ;
    private final AtomicLong lastCacheChanged = new AtomicLong();
    private final Set<URL> registered = new ConcurrentHashSet<URL>();
    private final ConcurrentMap<URL, Set<NotifyListener>> subscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();
    private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<URL, Map<String, List<URL>>>();
    ...
    }

FailbackRegistry 继承自AbstractRegistry ,实现了失败重试机制。

public abstract class FailbackRegistry extends AbstractRegistry {
// 定时任务执行器
private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true));

// 失败重试定时器,定时检查是否有请求失败,如有,无限次重试
private final ScheduledFuture<?> retryFuture;

private final Set<URL> failedRegistered = new ConcurrentHashSet<URL>();

private final Set<URL> failedUnregistered = new ConcurrentHashSet<URL>();

private final ConcurrentMap<URL, Set<NotifyListener>> failedSubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();

private final ConcurrentMap<URL, Set<NotifyListener>> failedUnsubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();

private final ConcurrentMap<URL, Map<NotifyListener, List<URL>>> failedNotified = new ConcurrentHashMap<URL, Map<NotifyListener, List<URL>>>();
...
}

5.服务提供者启动的注册过程

服务提供者启动时 向/dubbo/com.foo.BarService/providers目录下写入自己的URL地址。接下来,找寻下代码执行路径。RegistryProtocol 作为注册中心的核心组件,作为代码的入口,还要明确一点,这是个注册登记过程。

//入口
public class RegistryProtocol implements Protocol {
final Registry registry = getRegistry(originInvoker);
final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
registry.register(registedProviderUrl);
}
public abstract class AbstractRegistry implements Registry {
    public void register(URL url) {
        if (url == null) {
            throw new IllegalArgumentException("register url == null");
        }
        if (logger.isInfoEnabled()){
            logger.info("Register: " + url);
        }
        registered.add(url);
    }
...
}
public abstract class FailbackRegistry extends AbstractRegistry {
public void register(URL url) {
    super.register(url);
    failedRegistered.remove(url);
    failedUnregistered.remove(url);
    try {
        // 向服务器端发送注册请求
        doRegister(url);
    } catch (Exception e) {
    ...
    }

        // 将失败的注册请求记录到失败列表,定时重试
        failedRegistered.add(url);
    }
    protected abstract void doRegister(URL url);
    
    protected abstract void doUnregister(URL url);
    
    protected abstract void doSubscribe(URL url, NotifyListener listener);
    
    protected abstract void doUnsubscribe(URL url, NotifyListener listener);
...
}   
 
 public class ZookeeperRegistry extends FailbackRegistry {
     public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
        super(url);
        //如果provider的url是“0.0.0.0”或者在参数中带anyHost=true则抛出异常注册地址不存在
        if (url.isAnyHost()) {
          throw new IllegalStateException("registry address == null");
       }
        //服务分组(默认“dubbo”)
        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
        if (! group.startsWith(Constants.PATH_SEPARATOR)) {
            group = Constants.PATH_SEPARATOR + group;
        }
        //服务分组根地址
        this.root = group;
        zkClient = zookeeperTransporter.connect(url);
        //添加状态监听器
        zkClient.addStateListener(new StateListener() {
            public void stateChanged(int state) {
               if (state == RECONNECTED) {
               try {
          recover();
       } catch (Exception e) {
          logger.error(e.getMessage(), e);
       }
               }
            }
        });
    }
 
     protected void doRegister(URL url) {
            try {
                //连接注册中心注册,在zk上创建节点
               zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
            } catch (Throwable e) {
                throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
            }
        }
 }

6. 注册中心关系类图

重要概念:

ZookeeperRegistry :负责与zookeeper进行交互

RegistryProtocol :从注册中心获取可用服务,或者将服务注册到zookeeper,然后提供服务或者提供调用代理。

RegistryDirectory :维护着所有可用的远程Invoker或者本地的Invoker。这个类实现了NotifyListner。

NotifyListener :负责RegistryDirectory和ZookeeperRegistry的通信。

FailbackRegistry:继承自Registry,实现了失败重试机制。

时间: 2024-08-06 07:57:31

Dubbo点滴(5)之服务注册中心的相关文章

Dubbo点滴(3)之服务配置ServiceConfig

接触过dubbo的同学,见到下面的配置都非常熟悉了,含义不多说. 本章主要目的,对DUBBO配置原理进行剖析. <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:dubbo="http://code.alibabatech.com/schema/du

dubbo在多机房多注册中心的方案

技术交流群:534368042 起因:项目在服务化之后,开辟了一个新的专有云机房A,在原有物理机房B系统不迁移的情况下,需要A的系统调用B的各种dubbo服务,且A到B之间不能直接访问需要通过交换机做网络映射,现有B内部的网段是192.168.1.X A网段59.10.59.X 映射后A访问B的网段是10.59.10.X,造成A消费者无法直接注册到B的zookeeper集群注册中心,访问B的服务. 方案:通过dubbo的双注册中心的模式,A机房访问B机房服务通过修改A机房机器的hosts例如B机

Dubbo源代码实现三:注册中心Registry

我们知道,对于服务治理框架来说,服务通信(RPC)和服务管理两部分必不可少,而服务管理又分为服务注册.服务发现和服务人工介入,我们来看看Dubbo框架的结构图(来源网络): 图中可以看出,服务提供者Provider往服务注册中心Registry注册服务,而的消费者Consumer从服务注册中心订阅它需要的服务,而不是全部服务,当有新的Provider出现,或者现有Provider宕机,注册中心Registry都应该能尽早发现,并将新的Provider列表推送给对应的Consumer,有了这样的机

spring cloud(二)服务(注册)中心Eureka

Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组件之一. 背景介绍 服务中心 服务中心又称注册中心,管理各种服务功能包括服务的注册.发现.熔断.负载.降级等,比如dubbo admin后台的各种功能. 有了服务中心调用关系会有什么变化,画几个简图来帮忙理解 项目A调用项目B 正常调用项目A请求项目B 有了服务中心之后,任何一个服务都不能直接去掉用

说一下Dubbo 的工作原理?注册中心挂了可以继续通信吗?

面试题 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程? 面试官心理分析 MQ.ES.Redis.Dubbo,上来先问你一些思考性的问题.原理,比如 kafka 高可用架构原理.es 分布式架构原理.redis 线程模型原理.Dubbo 工作原理:之后就是生产环境里可能会碰到的一些问题,因为每种技术引入之后生产环境都可能会碰到一些问题:再来点综合的,就是系统设计,比如让你设计一个 MQ.设计一个搜索引擎.设计一个缓存.设计一个 rpc 框架等等. 那既

Spring Cloud Eureka 分布式开发之服务注册中心、负载均衡、声明式服务调用实现

介绍 本示例主要介绍 Spring Cloud 系列中的 Eureka,使你能快速上手负载均衡.声明式服务.服务注册中心等 Eureka Server Eureka 是 Netflix 的子模块,它是一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移. 服务注册和发现对于微服务架构而言,是非常重要的.有了服务发现和注册,只需要使用服务的标识符就可以访问到服务,而不需要修改服务调用的配置文件.该功能类似于 Dubbo 的注册中心,比如 Zookeeper. Eureka

服务注册中心,Eureka与Zookeeper比较

转自https://my.oschina.net/thinwonton/blog/1622905 1. 前言 服务注册中心,给客户端提供可供调用的服务列表,客户端在进行远程服务调用时,根据服务列表然后选择服务提供方的服务地址进行服务调用.服务注册中心在分布式系统中大量应用,是分布式系统中不可或缺的组件,例如rocketmq的name server,hdfs中的namenode,dubbo中的zk注册中心,spring cloud中的服务注册中心eureka. 在spring cloud中,除了可

Spring Cloud构建微服务架构(六)高可用服务注册中心

在Spring Cloud系列文章的开始,我们就介绍了服务注册与发现,其中,主要演示了如何构建和启动服务注册中心Eureka Server,以及如何将服务注册到Eureka Server中,但是在之前的示例中,这个服务注册中心是单点的,显然这并不适合应用于线上生产环境,那么下面在前文的基础上,我们来看看该如何构建高可用的Eureka Server集群. 单点Eureka Server的样例: GitHub 开源中国 Eureka Server的高可用 Eureka Server除了单点运行之外,

【转帖】阿里金融云:分布式服务注册中心(DSR)

https://www.cloud.alipay.com/docs/middleware/register/index.html 分布式服务注册中心(DSR) 分布式服务注册中心简介 服务注册中心 (Register) 是一个基于“发布-订阅”模式的协调中间件.在分布式环境下,它通常被用作地址服务器. SOFA RPC.MsgBroker 等金融云中间件,都依靠服务注册中心来实时感知各个角色的在线地址列表.例如SOFA RPC中,服务消费方需要感知服务提供方地址:MsgBroker中,消息发布者