一、配置
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
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×tamp=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×tamp=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×tamp=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×tamp=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
[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
[]