dubbo · 2022-10-31 0

dubbo 在 zookeeper 上的数据结构

一、配置

1.公共包

pom 文件:

<groupId>org.example</groupId>
<artifactId>dubbo-common</artifactId>
<version>1.0.0</version>

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

接口:

public interface BarService {
    String say(Integer id);
}
public interface BazService {

    String walk(Integer id);
}

2.provider

pom 文件:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath/>
</parent>

<groupId>org.example</groupId>
<artifactId>spring-boot-dubbo-provider1</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
        <version>3.2.0</version>
        <type>pom</type>
        <exclusions>
            <exclusion>
                <artifactId>slf4j-reload4j</artifactId>
                <groupId>org.slf4j</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>3.2.0</version>
    </dependency>

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>dubbo-common</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

配置:

# 服务端口
server:
  port: 8001

# dubbo 配置
dubbo:
  # 应用
  application:
    name: provider1
  # 注册中心地址
  registry:
    address: zookeeper://127.0.0.1:2181
    # group: group_1
    timeout: 30000 # 连接超时时间,默认 30s
    session: 60000 # 会话超时时间,默认 60s
  # 配置中心地址
  config-center:
    address: zookeeper://127.0.0.1:2181
  # 元中心地址
  metadata-report:
    address: zookeeper://127.0.0.1:2181
  # 协议
  protocol:
    name: dubbo
    port: 20881

java 类:

@SpringBootApplication
@EnableDubbo
public class Provider1Boot {

    public static void main(String[] args) {
        SpringApplication.run(Provider1Boot.class, args);
    }
}
@DubboService
public class BarServiceImpl implements BarService {

    @Override
    public String say(Integer id) {
        return "hello bar!";
    }
}

3.consumer

pom 文件:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath/>
</parent>

<groupId>org.example</groupId>
<artifactId>spring-boot-dubbo-consumer1</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
        <version>3.2.0</version>
        <type>pom</type>
        <exclusions>
            <exclusion>
                <artifactId>slf4j-reload4j</artifactId>
                <groupId>org.slf4j</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>3.2.0</version>
    </dependency>

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>dubbo-common</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

配置:

# 服务端口
server:
  port: 9001

# dubbo 配置
dubbo:
  # 应用
  application:
    name: consumer1
  # 注册中心地址
  registry:
    address: zookeeper://127.0.0.1:2181
    # group: group_1
    timeout: 30000 # 连接超时时间,默认 30s
    session: 60000 # 会话超时时间,默认 60s
  # 配置中心地址
  config-center:
    address: zookeeper://127.0.0.1:2181
  # 元中心地址
  metadata-report:
    address: zookeeper://127.0.0.1:2181
  # 协议
  protocol:
    name: dubbo
    port: 20891

java 类:

@SpringBootApplication
public class Consumer1Boot {

    public static void main(String[] args) {
        SpringApplication.run(Consumer1Boot.class, args);
    }
}
@RestController
public class BarController {

    @DubboReference
    private BarService barService;

    @RequestMapping("/say")
    public String say(){
        return barService.say(1);
    }
}

二、数据结构

1.注册中心

# application.yml
dubbo:
  registry:
    address: zookeeper://localhost:2181
    # group: group_1
    timeout: 30000 # 连接超时时间,默认 30s
    session: 60000 # 会话超时时间,默认 60s

dubbo-zookeeper-registry

zookeeper 中存储的 dubbo 数据分为三级:

序号 节点 说明
1 根节点 dubbo
2 一级子节点 提供服务的服务名
3 一级子节点 固定的四个子节点:configurators, consumers, providers, routers

查看节点信息:

[zk: localhost:2181(CONNECTED) 1] ls /
[dubbo, services, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo
[com.foo.BarService, com.foo.BazService, config, mapping, metadata, org.apache.dubbo.metadata.MetadataService]
[zk: localhost:2181(CONNECTED) 3] ls /dubbo/com.foo.BarService
[configurators, consumers, providers, routers]
[zk: localhost:2181(CONNECTED) 4] ls /dubbo/com.foo.BarService/providers
[dubbo%3A%2F%2F172.17.0.1%3A20881%2Fcom.foo.BarService%3Fanyhost%3Dtrue%26application%3Dprovider1%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26generic%3Dfalse%26interface%3Dcom.foo.BarService%26methods%3Dsay%26pid%3D3755%26prefer.serialization%3Dfastjson2%2Chessian2%26release%3D3.2.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1693844361821, dubbo%3A%2F%2F172.17.0.1%3A20882%2Fcom.foo.BarService%3Fanyhost%3Dtrue%26application%3Dprovider2%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26generic%3Dfalse%26interface%3Dcom.foo.BarService%26methods%3Dsay%26pid%3D3987%26prefer.serialization%3Dfastjson2%2Chessian2%26release%3D3.2.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1693844370960]
[zk: localhost:2181(CONNECTED) 5] ls /dubbo/com.foo.BarService/consumers
[consumer%3A%2F%2F172.17.0.1%2Fcom.foo.BarService%3Fapplication%3Dconsumer1%26background%3Dfalse%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26interface%3Dcom.foo.BarService%26methods%3Dsay%26pid%3D4256%26qos.enable%3Dtrue%26release%3D3.2.0%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1693844399089%26unloadClusterRelated%3Dfalse, consumer%3A%2F%2F172.17.0.1%2Fcom.foo.BarService%3Fapplication%3Dconsumer2%26background%3Dfalse%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26interface%3Dcom.foo.BarService%26methods%3Dsay%26pid%3D4471%26qos.enable%3Dtrue%26release%3D3.2.0%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1693844406717%26unloadClusterRelated%3Dfalse]

providers 进行 url 解码,如下:

[dubbo://172.17.0.1:20881/com.foo.BarService?anyhost=true&application=provider1&background=false&deprecated=false&dubbo=2.0.2&dynamic=true&executor-management-mode=isolation&file-cache=true&generic=false&interface=com.foo.BarService&methods=say&pid=3755&prefer.serialization=fastjson2,hessian2&release=3.2.0&service-name-mapping=true&side=provider&timestamp=1693844361821, dubbo://172.17.0.1:20882/com.foo.BarService?anyhost=true&application=provider2&background=false&deprecated=false&dubbo=2.0.2&dynamic=true&executor-management-mode=isolation&file-cache=true&generic=false&interface=com.foo.BarService&methods=say&pid=3987&prefer.serialization=fastjson2,hessian2&release=3.2.0&service-name-mapping=true&side=provider&timestamp=1693844370960]

提供者属性:

属性 描述
anyhost true
application provider1 应用名称
background false
deprecated false
dubbo 2.0.2 dubbo 版本
dynamic true
executor isolation
file-cache true
generic false
interface com.foo.BarService 接口名称
methods say 接口方法名
pid 3755 进程号
prefer.serialization fastjson2,hessian2
release 3.2.0
service-name-mapping true
side provider 消费端或服务端
timestamp 1693844361821 时间辍

consumer 进行 url 解码,如下:

[consumer://172.17.0.1/com.foo.BarService?application=consumer1&background=false&category=consumers&check=false&dubbo=2.0.2&executor-management-mode=isolation&file-cache=true&interface=com.foo.BarService&methods=say&pid=4256&qos.enable=true&release=3.2.0&side=consumer&sticky=false&timestamp=1693844399089&unloadClusterRelated=false, consumer://172.17.0.1/com.foo.BarService?application=consumer2&background=false&category=consumers&check=false&dubbo=2.0.2&executor-management-mode=isolation&file-cache=true&interface=com.foo.BarService&methods=say&pid=4471&qos.enable=true&release=3.2.0&side=consumer&sticky=false&timestamp=1693844406717&unloadClusterRelated=false]

消费者属性:

属性 描述
application consumer1 应用名称
background false
category consumers 类型
check false
dubbo 2.0.2 dubbo 版本
executor-management-mode isolation
file-cache true
interface com.foo.BarService 接口名称
methods say 接口方法名
pid 4256 进程号
qos.enable true
release 3.2.0
side consumer 消费端或服务端
sticky false
timestamp 1693844399089 时间辍
unloadClusterRelated false

流程:

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

支持以下功能:

  • 当提供者出现断电等异常停机时,注册中心能自动删除提供者信息
  • 当注册中心重启时,能自动恢复注册数据,以及订阅请求
  • 当会话过期时,能自动恢复注册数据,以及订阅请求
  • 当设置 <dubbo:registry check="false" /> 时,记录失败注册和订阅请求,后台定时重试
  • 可通过 <dubbo:registry username="admin" password="1234" /> 设置 zookeeper 登录信息
  • 可通过 <dubbo:registry group="dubbo" /> 设置 zookeeper 的根节点,不配置将使用默认的根节点。
  • 支持 * 号通配符 <dubbo:reference group="*" version="*" />,可订阅服务的所有分组和所有版本的提供者

2.元数据中心

元数据

dubbo:
  metadata-report:
    address: zookeeper://127.0.0.1:2181

它的元数据信息位于以下节点:

Provider: /dubbo/metadata/{interface name}/{version}/{group}/provider/{application name}
Consumer: /dubbo/metadata/{interface name}/{version}/{group}/consumer/{application name}

当 version 或者 group 不存在时,version 路径和 group 路径会取消:

Provider: /dubbo/metadata/{interface name}/provider/{application name}
Consumer: /dubbo/metadata/{interface name}/consumer/{application name}

查看节点信息:

[zk: localhost:2181(CONNECTED) 1] ls /dubbo
[com.foo.BarService, com.foo.BazService, config, mapping, metadata, org.apache.dubbo.metadata.MetadataService]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/metadata
[com.foo.BarService, com.foo.BazService]
[zk: localhost:2181(CONNECTED) 3] ls /dubbo/metadata/com.foo.BarService
[consumer, provider]
[zk: localhost:2181(CONNECTED) 4] ls /dubbo/metadata/com.foo.BarService/provider
[provider1, provider2]
[zk: localhost:2181(CONNECTED) 5] ls /dubbo/metadata/com.foo.BarService/provider/provider1
[]
[zk: localhost:2181(CONNECTED) 6] get /dubbo/metadata/com.foo.BarService/provider/provider1
{"annotations":[],"canonicalName":"com.foo.BarService","codeSource":"file:/home/zxm/IdeaProjects/jdk8-demo/dubbo/dubbo-common/target/classes/","methods":[{"annotations":[],"name":"say","parameterTypes":["java.lang.Integer"],"parameters":[],"returnType":"java.lang.String"}],"parameters":{"dubbo":"2.0.2","side":"provider","interface":"com.foo.BarService","release":"3.2.0","pid":"3755","anyhost":"true","application":"provider1","executor-management-mode":"isolation","file-cache":"true","methods":"say","deprecated":"false","service-name-mapping":"true","qos.enable":"true","generic":"false","bind.port":"20881","bind.ip":"172.17.0.1","prefer.serialization":"fastjson2,hessian2","background":"false","dynamic":"true","timestamp":"1693844361821"},"types":[{"enums":[],"items":[],"properties":{},"type":"java.lang.String"},{"enums":[],"items":[],"properties":{},"type":"java.lang.Integer"}],"uniqueId":"com.foo.BarService@file:/home/zxm/IdeaProjects/jdk8-demo/dubbo/dubbo-common/target/classes/"}
[zk: localhost:2181(CONNECTED) 7] ls /dubbo/metadata/com.foo.BarService/consumer
[consumer1, consumer2]
[zk: localhost:2181(CONNECTED) 8] ls /dubbo/metadata/com.foo.BarService/consumer/consumer1
[]
[zk: localhost:2181(CONNECTED) 9] get /dubbo/metadata/com.foo.BarService/consumer/consumer1
{"release":"3.2.0","side":"consumer","pid":"4256","interface":"com.foo.BarService","application":"consumer1","dubbo":"2.0.2","executor-management-mode":"isolation","file-cache":"true","register.ip":"172.17.0.1","methods":"say","background":"false","sticky":"false","qos.enable":"true","unloadClusterRelated":"false","timestamp":"1693844399089"}

providers 的数据格式化为:

{
    "annotations": [],
    "canonicalName": "com.foo.BarService",
    "codeSource": "file:/home/zxm/IdeaProjects/jdk8-demo/dubbo/dubbo-common/target/classes/",
    "methods": [{
        "annotations": [],
        "name": "say",
        "parameterTypes": ["java.lang.Integer"],
        "parameters": [],
        "returnType": "java.lang.String"
    }],
    "parameters": {
        "dubbo": "2.0.2",
        "side": "provider",
        "interface": "com.foo.BarService",
        "release": "3.2.0",
        "pid": "3755",
        "anyhost": "true",
        "application": "provider1",
        "executor-management-mode": "isolation",
        "file-cache": "true",
        "methods": "say",
        "deprecated": "false",
        "service-name-mapping": "true",
        "qos.enable": "true",
        "generic": "false",
        "bind.port": "20881",
        "bind.ip": "172.17.0.1",
        "prefer.serialization": "fastjson2,hessian2",
        "background": "false",
        "dynamic": "true",
        "timestamp": "1693844361821"
    },
    "types": [{
        "enums": [],
        "items": [],
        "properties": {},
        "type": "java.lang.String"
    }, {
        "enums": [],
        "items": [],
        "properties": {},
        "type": "java.lang.Integer"
    }],
    "uniqueId": "com.foo.BarService@file:/home/zxm/IdeaProjects/jdk8-demo/dubbo/dubbo-common/target/classes/"
}

consumers 的数据格式化为:

{
    "release": "3.2.0",
    "side": "consumer",
    "pid": "4256",
    "interface": "com.foo.BarService",
    "application": "consumer1",
    "dubbo": "2.0.2",
    "executor-management-mode": "isolation",
    "file-cache": "true",
    "register.ip": "172.17.0.1",
    "methods": "say",
    "background": "false",
    "sticky": "false",
    "qos.enable": "true",
    "unloadClusterRelated": "false",
    "timestamp": "1693844399089"
}

地址发现 - 接口-应用名映射

在Dubbo 3.0 中,默认使用了服务自省机制去实现服务发现。

简而言之,服务自省机制需要能够通过 interface name 去找到对应的 application name,这个关系可以是一对多的,即一个 service name 可能会对应多个不同的 application name。在 3.0 中,元数据中心提供此项映射的能力。

在上面提到,service name 和 application name 可能是一对多的,在 zookeeper 中,使用单个 key-value 进行保存,多个 application name 通过英文逗号,隔开。由于是单个 key-value 去保存数据,在多客户端的情况下可能会存在并发覆盖的问题。因此,我们使用 zookeeper 中的版本机制 version 去解决该问题。在 zookeeper 中,每一次对数据进行修改,dataVersion 都会进行增加,我们可以利用 version 这个机制去解决多个客户端同时更新映射的并发问题。不同客户端在更新之前,先去查一次 version,当作本地凭证。在更新时,把凭证 version 传到服务端比对 version, 如果不一致说明在此期间被其他客户端修改过,重新获取凭证再进行重试(CAS)。目前如果重试6次都失败的话,放弃本次更新映射行为。

查看节点信息:

[zk: localhost:2181(CONNECTED) 1] ls /dubbo
[com.foo.BarService, com.foo.BazService, config, mapping, metadata, org.apache.dubbo.metadata.MetadataService]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/mapping
[com.foo.BarService, com.foo.BazService]
[zk: localhost:2181(CONNECTED) 3] ls /dubbo/mapping/com.foo.BarService
[]
[zk: localhost:2181(CONNECTED) 4] get /dubbo/mapping/com.foo.BarService
provider1,provider2

3. 配置中心

dubbo:
  config-center:
    address: zookeeper://127.0.0.1:2181

dubbo-zookeeper-configcenter

[zk: localhost:2181(CONNECTED) 1] ls /dubbo
[com.foo.BarService, com.foo.BazService, config, mapping, metadata, org.apache.dubbo.metadata.MetadataService]
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/config
[DUBBO_SERVICEDISCOVERY_MIGRATION, dubbo]
[zk: localhost:2181(CONNECTED) 3] ls /dubbo/config/dubbo
[]