Zookeeper
1 准备工作
- 了解 Dubbo 基本开发步骤
- 安装并启动 Zookeeper
2 使用说明
2.1 添加 Maven 依赖
如果项目已启用 Zookeeper 作为注册中心,则无需额外配置。
如果未使用 Zookeeper 注册中心,请参考 为注册中心添加 Zookeeper 相关依赖。
2.2 启用 Zookeeper 配置中心
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
或者
dubbo
metadata-report
address: zookeeper://127.0.0.1:2181
或者
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
或者
MetadataReportConfig metadataConfig = new MetadataReportConfig();
metadataConfig.setAddress("zookeeper://127.0.0.1:2181");
有关 address
格式,请参考 [zookeeper 注册中心 - 启用配置](../../registry/zookeeper/#22-configure and enable-zookeeper)
3 高级配置
有关完整的配置参数,请参考 metadata-report-config。
4 工作原理
4.1 [服务运维元数据](../overview/#2-Service Operation and Maintenance Metadata)
Zookeeper 基于树形结构存储数据,其元数据信息位于以下节点
Provider: /dubbo/metadata/{interface name}/{version}/{group}/provider/{application name}
Consumer: /dubbo/metadata/{interface name}/{version}/{group}/consumer/{application name}
当版本或组不存在时,版本路径和组路径将被取消,路径如下
Provider: /dubbo/metadata/{interface name}/provider/{application name}
Consumer: /dubbo/metadata/{interface name}/consumer/{application name}
通过 zkCli get 操作查看数据。
提供者节点
[zk: localhost:2181(CONNECTED) 8] get /dubbo/metadata/org.apache.dubbo.demo.DemoService/provider/demo-provider
{"parameters":{"side":"provider","interface":"org.apache.dubbo.demo.DemoService","metadata-type":"remote","application":"demo-provider", "dubbo":"2.0.2","release":"","anyhost":"true","delay":"5000","methods":"sayHello,sayHelloAsync","deprecated":"false" ,"dynamic":"true","timeout":"3000","generic":"false"},"canonicalName":"org.apache.dubbo.demo.DemoService","codeSource":"file:/ Users/apple/IdeaProjects/dubbo/dubbo-demo/dubbo-demo-interface/target/classes/","methods":[{"name":"sayHelloAsync","parameterTypes":["java.lang.String" ],"returnType":"java.util.concurrent.CompletableFuture"},{"name":"sayHello","parameterTypes":["java.lang.String"],"returnType":"java.lang.String "}],"types":[{"type":"java.util.concurrent.CompletableFuture","properties":{"result":"java.lang.Object","stack":"java.util. concurrent.CompletableFuture.Completion"}},{"type":"java.lang.Object"},{"type":"java.lang.String"},{"type":"java.util.concurrent.CompletableFuture .Completion","properties":{"next":"java.util.concurrent.Co mpletableFuture. Completion", "status": "int"}}, {"type": "int"}]}
cZxid = 0x25a9b1
ctime = Mon Jun 28 21:35:17 CST 2021
mZxid = 0x25a9b1
mtime = Mon Jun 28 21:35:17 CST 2021
pZxid = 0x25a9b1
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 1061
numChildren = 0
消费者节点
[zk: localhost:2181(CONNECTED) 10] get /dubbo/metadata/org.apache.dubbo.demo.DemoService/consumer/demo-consumer
{"side":"consumer","interface":"org.apache.dubbo.demo.DemoService","metadata-type":"remote","application":"demo-consumer","dubbo":" 2.0.2","release":"","sticky":"false","check":"false","methods":"sayHello,sayHelloAsync"}
cZxid = 0x25aa24
ctime = Mon Jun 28 21:57:43 CST 2021
mZxid = 0x25aa24
mtime = Mon Jun 28 21:57:43 CST 2021
pZxid = 0x25aa24
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 219
numChildren = 0
4.2 [地址发现 - 接口-应用名称映射](../overview/#11-Interface—Application Mapping Relationship)
在 Dubbo 3.0 中,默认使用服务自省机制来实现服务发现。有关服务自省,请参考 服务自省
简而言之,服务自省机制需要能够通过接口名称找到对应的应用名称。这种关系可以是一对多的,即一个服务名称可能对应多个不同的应用名称。在 3.0 中,元数据中心提供了这种映射功能。
Zookeeper
如上所述,服务名称和应用名称可能是一对多的。在 zookeeper 中,使用单个键值对进行存储,多个应用名称之间用英文逗号,
分隔。由于使用单个键值对保存数据,因此在多个客户端的情况下可能会出现并发覆盖的问题。因此,我们使用 zookeeper 中的版本机制 version 来解决这个问题。在 zookeeper 中,每次修改数据时,dataVersion 都会增加。我们可以利用版本机制来解决多个客户端同时更新映射的并发问题。更新之前,不同的客户端检查一次版本,并将其用作本地凭证。更新时,将凭证版本传递给服务器以比较版本。如果不一致,则表示在此期间已被其他客户端修改。重新获取凭证并重试(CAS)。目前,如果 6 次重试失败,则放弃更新映射行为。
Curator api。
CuratorFramework client = ...
client.setData().withVersion(ticket).forPath(path, dataBytes);
映射信息位于
/dubbo/mapping/{service name}
通过 zkCli get 操作查看数据。
[zk: localhost:2181(CONNECTED) 26] get /dubbo/mapping/org.apache.dubbo.demo.DemoService
demo-provider, two-demo-provider, dubbo-demo-annotation-provider
cZxid = 0x25a80f
ctime = Thu Jun 10 01:36:40 CST 2021
mZxid = 0x25a918
mtime = Fri Jun 11 18:46:40 CST 2021
pZxid = 0x25a80f
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 62
numChildren = 0
4.3 [地址发现 - 接口配置元数据](../overview/#12-Interface Configuration Metadata)
要启用远程接口配置元数据注册,需要在应用中添加以下配置,因为默认情况下 Dubbo3 应用级服务发现将启用服务自省模式,并且不会将数据注册到元数据中心。
dubbo.application.metadata-type=remote
或者,仍然在自省模式下启用集中式元数据注册
dubbo.application.metadata-type=local
dubbo.metadata-report.report-metadata=true
Zookeeper 的应用级元数据位于 /dubbo/metadata/{应用名称}/{版本}
[zk: localhost:2181(CONNECTED) 33] get /dubbo/metadata/demo-provider/da3be833baa2088c5f6776fb7ab1a436
{"app":"demo-provider","revision":"da3be833baa2088c5f6776fb7ab1a436","services":{"org.apache.dubbo.demo.DemoService:dubbo":{"name":"org.apache.dubbo. demo.DemoService","protocol":"dubbo","path":"org.apache.dubbo.demo.DemoService","params":{"side":"provider","release":""," methods":"sayHello,sayHelloAsync","deprecated":"false","dubbo":"2.0.2","pid":"38298","interface":"org.apache.dubbo.demo.DemoService" ,"service-name-mapping":"true","timeout":"3000","generic":"false","metadata-type":"remote","delay":"5000","application" :"demo-provider","dynamic":"true","REGISTRY_CLUSTER":"registry1","anyhost":"true","timestamp":"1626887121829"}},"org.apache.dubbo.demo. RestDemoService:1.0.0:rest":{"name":"org.apache.dubbo.demo.RestDemoService","version":"1.0.0","protocol":"rest","path":"org .apache.dubbo.demo.RestDemoService","params":{"side":"provider","release":"","methods":"getRemoteApplicationName,sayHello,hello,error","deprecated":"false ","dubbo":"2.0.2","pid":"38298","interface":"org.apache.dubbo.demo .RestDemoService","service-name-mapping":"true","version":"1.0.0","timeout":"5000","generic":"false","revision":"1.0.0 ","metadata-type":"remote","delay":"5000","application":"demo-provider","dynamic":"true","REGISTRY_CLUSTER":"registry1","anyhost": "true","timestamp":"1626887120943"}}}}
cZxid = 0x25b336
ctime = Thu Jul 22 01:05:55 CST 2021
mZxid = 0x25b336
mtime = Thu Jul 22 01:05:55 CST 2021
pZxid = 0x25b336
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 1286
numChildren = 0