最新 Dubbo3 深入理解原理系列

7、【最新Dubbo3深入理解】Dubbo3中的服务注册以及应用级注册优化_元数据

Dubbo 的服务注册中应用级注册优化

Dubbo 的注册中心

Dubbo 支持很多种注册中心,支持的主流注册中心包括:ZooKeeper、Nacos、Redis

Dubbo 需要引入注册中心依赖,并且配置注册中心地址,这里以 ZooKeeper 注册中心为例介绍如何使用

引入依赖:

其中引入的 dubbo-dependencies-zookeeper 将自动为应用增加 Zookeeper 相关客户端的依赖,减少用户使用 Zookeeper 成本,如使用中遇到版本兼容问题,用户也可以不使用 dubbo-dependencies-zookeeper,而是自行添加 Curator、Zookeeper Client 等依赖。

<properties>
    <dubbo.version>3.0.8</dubbo.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>${dubbo.version}</version>
    </dependency>
    <!-- This dependency helps to introduce Curator and Zookeeper dependencies that are necessary for Dubbo to work with zookeeper as transitive dependencies  -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>${dubbo.version}</version>
        <type>pom</type>
    </dependency>
</dependencies>

要特别注意 ZooKeeper 版本和 Dubbo 版本之间的适配兼容,如下:

Zookeeper Server 版本

Dubbo 版本

Dubbo Zookeeper 依赖包

说明

3.4.x 及以下

3.0.x 及以上

dubbo-dependencies-zookeeper

传递依赖 Curator 4.x 、Zookeeper 3.4.x

3.5.x 及以上

3.0.x 及以上

dubbo-dependencies-zookeeper-curator5

传递依赖 Curator 5.x 、Zookeeper 3.7.x

3.4.x 及以上

2.7.x 及以下

dubbo-dependencies-zookeeper

传递依赖 Curator 4.x 、Zookeeper 3.4.x

3.5.x 及以上

2.7.x 及以下


须自行添加 Curator、Zookeeper 等相关客户端依赖

配置启用:

# application.yml
dubbo
 registry
   address: zookeeper://localhost:2181

Dubbo 支持多注册中心

Dubbo 在默认情况下:

  • Service 服务会 注册到所有的全局默认的注册中心
  • 会将 Reference 服务去 对所有的全局默认注册中心进行订阅

多注册中心配置如下:

# application.yml (Spring Boot)
dubbo
 registries
  beijingRegistry
   address: zookeeper://localhost:2181
  shanghaiRegistry
   address: zookeeper://localhost:2182

如果不进行 默认项 的配置,则该注册中心是默认的,上边两个注册中心没有指定默认项(默认 default = true),那么对于没有指定注册中心 id 的服务将会分别注册到上边的两个注册中心去

也可以指定该注册中心不是默认的:

# application.yml (Spring Boot)
dubbo
 registries
  beijingRegistry
   address: zookeeper://localhost:2181
   default: true
  shanghaiRegistry
   address: zookeeper://localhost:2182
   # 非默认
   default: false

可以显式指定服务要注册的注册中心 id:

@DubboService(registry = {"beijingRegistry"})
public class DemoServiceImpl implements DemoService {}

@DubboService(registry = {"shanghaiRegistry"})
public class HelloServiceImpl implements HelloService {}

Dubbo 的服务注册

Dubbo3 之前一直是接口级注册,Dubbo3 之后推出了应用级注册,接下来说一下为什么要换为应用级注册!

  • Dubbo 中 接口级注册 的缺点

在 Dubbo3.0 之前的服务注册使用的是 接口级注册 ,这种注册方式对于注册中心的压力是非常大的,比如一个应用有 3 个实例对象,那么在注册中心上注册的格式如下:

tri://192.168.65.61:20880/com.zqy.UserService
tri://192.168.65.62:20880/com.zqy.UserService
tri://192.168.65.63:20880/com.zqy.UserService

tri://192.168.65.61:20880/com.zqy.ProductService
tri://192.168.65.62:20880/com.zqy.ProductService
tri://192.168.65.63:20880/com.zqy.ProductService

那么当一个 服务提供者 上提供很多接口的时候,就需要在注册中心上 注册大量的节点 ,导致注册中心压力比较大,并且如果提供者新增接口的话,消费者也需要去修改本地缓存的注册中心节点,也会比较耗费性能

简单一句话概括就是,在 Dubbo3.0 之前,接口级注册要注册的信息太多了!

而在 SpringCloud 中,和 Dubbo 的 注册粒度不同 ,SpringCloud 是进行应用级的注册,因此下边无论多少个接口,都不影响 SpringCloud 的注册,注册的格式如下:

应用名:
    192.168.65.61:8080
    192.168.65.62:8080
    192.168.65.63:8080
  • 因此,Dubbo3 中改成了 应用级服务注册!

简单来说,应用及服务注册带来的好处就是,大大减少了注册的数据!但同时给服务消费者寻找服务带来了复杂性!

在 Dubbo3.0 中,默认情况下,会同时进行 接口级注册应用级注册 ,这是为了兼容!因为当服务提供者升级到 3.0 之后,可能有些服务消费者还处于 Dubbo2.7 的版本,并没有应用级注册的能力!

如果确认所有的消费者都已经成功迁移 Dubbo3.0 的话,就可以在 yml 文件中配置只进行应用级注册:

# application.yml
dubbo:
  application:
    name: dubbo-app
    register-mode: instance # 只进行应用级注册
    # register-mode: interface # 只进行接口级注册
    # register-mode: all # 默认,同时进行接口级、应用级注册,为了兼容
  • Dubbo 的服务提供者如何进行 应用级注册

我们先来思考一下,服务消费者如果需要使用服务,需要哪些信息?

服务消费者本身是只有接口相关的信息的,比如 com.zqy.hello.UserService 这个接口信息,那么消费者就要通过这个接口信息来找到提供者中对应的服务

因此提供者必须将接口 -> 服务的信息给暴露出来

1、首先,服务提供者进行应用级注册,在注册中心上的数据为:

# 应用名 -> 应用地址的映射
dubbo-provider: 192.168.65.61:20880

2、此时注册中心上只有应用地址的 ip:port 信息,那么服务消费者还不知道他所使用的接口对应的应用是哪一个

因此服务提供者还存储了 接口名 -> 应用名 的映射:

# 接口名和应用名的映射
com.zqy.dubbo.service.UserService: dubbo-provider

那么此时,消费者就可以根据接口名获取到对应的应用地址了

3、但是消费者怎样去知道这个应用中是否有自己需要的服务呢?

因此服务提供者将自己应用中的所有 Dubbo 服务信息都给存储了 MetaDataInfo 中去,并且在服务启动之后,会暴露一个 应用元数据服务 ,这是 Dubbo 内置的一个服务

那么消费者就可以调用这个 应用元数据服务 来获取该应用中的 Dubbo 服务信息了

这样一来呢,Dubbo 中服务的具体信息就不在注册中心上了,而是在元数据中进行存储,避免了注册中心压力过大!

  • 再说一下 Dubbo 的应用元数据服务

上边说到了 Dubbo 服务提供者会暴露一个 应用元数据 服务

这个 应用元数据服务 其实就是用来减轻注册中心压力的,之前使用接口级注册的时候,会将服务的信息都给注册到注册中心去,导致注册中心压力很大

现在会将服务的信息给存储到 应用元数据服务 中去,来供消费者查询服务的具体信息

那么服务提供者需要将服务的元数据信息给暴露出去,让服务消费者可以查询到,暴露的方式有两种,可以通过 metadata-type 来配置:

# application.yaml
dubbo:
  application:
    name: dubbo-provider
    metadata-type: local # 或 remote
  • local :默认情况,如果是 local 的话,会将服务的元数据给放在服务提供者的本地,之后暴露 应用元数据服务 来供消费者进行查询,也就是上边我们说的情况

7、【最新Dubbo3深入理解】Dubbo3中的服务注册以及应用级注册优化_zookeeper_02

  • remote :如果是 remote 的话,表示会将服务的元数据放在远程主机,则提供者不会暴露 应用元数据服务 ,而是通过将服务的元数据信息存储在远程的 元数据中心 中去,元数据中心 可以是 ZooKeeper 也可以是 Nacos,那么消费者需要查询服务的信息时,去 元数据中心 中查询即可!

7、【最新Dubbo3深入理解】Dubbo3中的服务注册以及应用级注册优化_元数据_03

这两种暴露方式在性能上有什么区别呢?

  • 如果是暴露 应用元数据服务 的话,每一个服务提供者都会暴露一个 应用元数据服务 ,因此这个 元数据服务 是比较分散的,一般不会出现单点压力较大的情况
  • 如果是使用 元数据中心 的话,当整个微服务集群压力比较大的时候,会导致这个 元数据中心 压力也大

因此,综上看来,暴露 应用元数据服务 这一种方式比较好,而 Dubbo 中默认的也就是这一种方式

那么,应用级注册就已经说完了,为什么需要应用级注册呢?

就是为了减轻注册中心的压力,至于具体非常细的细节可以不用抠的非常认真,知道它原理是什么,用于解决什么问题的即可