共计 9019 个字符,预计需要花费 23 分钟才能阅读完成。
本篇内容主要讲解“Dubbo 和 ZooKeeper 基本用法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“Dubbo 和 ZooKeeper 基本用法是什么”吧!
一、改造背景
在现代的分布式应用中,往往会出现节点和节点之间的协调问题,其中就包括了:选主,集群管理,分布式锁,分布式配置管理,统一命名服务,状态同步等诉求。Apache ZooKeeper,正如它的名字所暗示的那样,动物园管理员,就是为了解决这些诉求的一个分布式协调服务框架。
为了保证系统的高可用,ZooKeeper 本身也可以部署成集群模式,称之为 ZooKeeper Ensemble。ZooKeeper 集群中始终确保其中的一台为 leader 的角色,并通过 ZAB(Zookeeper Atomic Broadcast Protocol)[1] 协议确保所有节点上的信息的一致。客户端可以访问集群中的任何一台进行读写操作,而不用担心数据出现不一致的现象。
O Reilly 的 ebook-Zookeeper-Distributed Process Coordination
ZooKeeper 中的数据存储方式与传统的 UNIX 文件系统相似,节点按照树状结构来组织,其中,节点被称之为 znodes(ZooKeeper 数据节点)
二、基本用法
可以通过直接下载的方式 [2] 安装并运行 ZooKeeper,在 Mac 上也可以通过 Homebrew [3] brew install zookeeper 来安装,考虑到通用性,本文采用 docker 的方式来运行 ZooKeeper。如果没有安装 docker,请先准备好 docker 环境 [4]。
1、启动 ZooKeeper
执行命令将 ZooKeeper,运行在 docker 容器中。
docker run --rm --name zookeeper -p 2181:2181 zookeeper
2、进入 Zookeeper 容器
docker exec -it zookeeper bash
在 bin 目录下有启动 ZooKeeper 的命令 zkServer 以及管理控制台 zkCli
bash-4.4# ls -l bintotal 36
-rwxr-xr-x 1 zookeepe zookeepe 232 Mar 27 04:32
README.txt
-rwxr-xr-x 1 zookeepe zookeepe 1937 Mar 27 04:32
zkCleanup.sh
-rwxr-xr-x 1 zookeepe zookeepe 1056 Mar 27 04:32
zkCli.cmd
-rwxr-xr-x 1 zookeepe zookeepe 1534 Mar 27 04:32
zkCli.sh
-rwxr-xr-x 1 zookeepe zookeepe 1759 Mar 27 04:32
zkEnv.cmd
-rwxr-xr-x 1 zookeepe zookeepe 2696 Mar 27 04:32
zkEnv.sh
-rwxr-xr-x 1 zookeepe zookeepe 1089 Mar 27 04:32
zkServer.cmd
-rwxr-xr-x 1 zookeepe zookeepe 6773 Mar 27 04:32
zkServer.sh``
3、通过 zkCli 进入 Zookeeper 管理界面
由于是通过 Docker 启动,ZooKeeper 进程已经启动,并通过 2181 端口对外提供服务。
bash-4.4# psPID USER TIME COMMAND
1 zookeepe 0:02 /usr/lib/jvm/java-1.8-openjdk/jre/bin/java -Dzookeeper.log.dir=. -Dzookeeper.root
32 root 0:00 bash
42 root 0:00 ps
因此可以直接通过 zkCli 来访问 ZooKeeper 的控制台来进行管理。
bash-4.4# bin/zkCli.sh -server 127.0.0.1:2181Connecting to 127.0.0.1:2181...
WATCHER::
WatchedEvent state:SyncConnected type:None path:null[zk: 127.0.0.1:2181(CONNECTED) 0] helpZooKeeper -server host:port cmd args stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
getAcl path
close
connect host:port
4.zkCli 上的一些基本操作
创建 /hello-zone 节点:
[zk: 127.0.0.1:2181(CONNECTED) 19] create /hello-zone world Created /hello-zone
列出 / 下的子节点,确认 hello-zone 被创建:
[zk: 127.0.0.1:2181(CONNECTED) 19] create /hello-zone world Created /hello-zone
列出 /hello-zone 的子节点,确认为空:
[zk: 127.0.0.1:2181(CONNECTED) 21] ls /hello-zone[]
获取存储在 /hello-zone 节点上的数据:
[zk: 127.0.0.1:2181(CONNECTED) 22] get /hello-zone
world
三、在 Dubbo 中使用 ZooKeeper
Dubbo 使用 ZooKeeper 用于服务的注册发现和配置管理:
首先,所有 Dubbo 相关的数据都组织在 /duboo 的根节点下。
二级目录是服务名,如 com.foo.BarService。
三级目录有两个子节点,分别 providers 和 consumers,表示该服务的提供者和消费者。
四级目录记录了与该服务相关的每一个应用实例的 URL 信息,在 providers 下的表示该服务的所有提供者,而在 consumers 下的表示该服务的所有消费者。举例说明,com.foo.BarService 的服务提供者在启动时将自己的 URL 信息注册到 /dubbo/com.foo.BarService/providers 下; 同样的,服务消费者将自己的信息注册到相应的 consumers 下,同时,服务消费者会订阅其所对应的 providers 节点,以便能够感知到服务提供方地址列表的变化。
四、准备示例代码
本文代码可以在以下链接中找到。
1、接口定义
一个定义简单的 GreetingService 接口,只有里面一个简单的方法 sayHello 向调用者问好。
public interface GreetingService {String sayHello(String name);}
2、服务端:服务实现
实现 GreetingService 接口,并通过 @Service 来标注其为 Dubbo 的一个服务。
@Servicepublic class AnnotatedGreetingService implements GreetingService {public String sayHello(String name) { return hello,
3、服务端:组装
定义 ProviderConfiguration 来组装 Dubbo 服务。
@Configuration@EnableDubbo(scanBasePackages = com.alibaba.dubbo.samples.impl)@PropertySource(classpath:/spring/dubbo-provider.properties)static class ProviderConfiguration {}
dubbo-provider.properties 是在 Spring 应用中外置配置的方式,内容如下:
dubbo.application.name=demo-provider
dubbo.registry.address=zookeeper://$DOCKER_HOST:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
由于 ZooKeeper 运行在 Docker 容器中,需要注意的是:
本文假定 Dubbo 应用运行在宿主机上,也就是 Docker 容器外,需要将 ZooKeeper 的地址替换成环境变量 ${DOCKER_HOST} 所指定的 IP 地址,相关信息请查阅 Docker 官方文档;
如果 Dubbo 应用也是 Docker 化的应用,只需要用 ZooKeeper 的容器名,在本文中容器名是 ZooKeeper;
当然,如果不用容器方式启动 ZooKeeper,只需要简单的将这里的 $ DOCKER_HOST 换成 localhost 即可。
4、服务端:启动服务
在 main 方法中通过启动一个 Spring Context 来对外提供 Dubbo 服务。
public class ProviderBootstrap {public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.in.read();}}
服务启动端的的 main 方法,将会看到下面的输出,代表服务端启动成功,并在注册中心(ZooKeeperRegistry)注册上了 GreetingService 这个服务:
[03/08/18 10:50:33:033 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Register: dubbo://192.168.99.1:20880/com.alibaba.dubbo.samples.api.GreetingService?anyhost=true application=demo-provider dubbo=2.6.2 generic=false interface=com.alibaba.dubbo.samples.api.GreetingService methods=sayHello pid=12938 side=provider timestamp=1533264631849, dubbo version: 2.6.2, current host: 192.168.99.1
通过 ZooKeeper 管理终端观察服务提供方的注册信息:
$ docker exec -it zookeeper bash
bash-4.4# bin/zkCli.sh -server localhost:218
Connecting to localhost:2181
Welcome to ZooKeeper!
JLine support is enabled
[zk: localhost:2181(CONNECTED) 0] ls
[dubbo%3A%2F%2F192.168.99.1%3A20880%2Fcom.alibaba.dubbo.samples.api.GreetingService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.6.2%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.samples.api.GreetingService%26methods%3DsayHello%26pid%3D12938%26side%3Dprovider%26timestamp%3D1533264631849]
可以看到刚刚启动的 Dubbo 的服务在 providers 节点下注册了自己的 URL 地址:dubbo://192.168.99.1:20880 /com.alibaba.dubbo.samples.api.GreetingService?anyhost = true&application = demo-provider&dubbo =2.6 0.2&通用 = 假接口 =com.alibaba.dubbo.samples.api.GreetingService&方法 = sayHello 的&PID = 12938&侧 = 提供商时间戳 =1533264631849
5、客户端:引用服务
通过 @Reference 来在客户端声明服务的引用,运行时将会通过该引用发起全程调用,而服务的目标地址将会从 ZooKeeper 的 provider 节点下查询。
@Component(annotatedConsumer)public class GreetingServiceConsumer {
@Reference
private GreetingService greetingService;
public String doSayHello(String name) { return greetingService.sayHello(name);
}}
6、客户端:组装
定义 ConsumerConfiguration 来组装 Dubbo 服务。
@Configuration@EnableDubbo(scanBasePackages = com.alibaba.dubbo.samples.action)@PropertySource(classpath:/spring/dubbo-consumer.properties)@ComponentScan(value = { com.alibaba.dubbo.samples.action})static class ConsumerConfiguration {}
dubbo-consumer.properties 是在 Spring 应用中外置配置的方式,内容如下:
dubbo.application.name=demo-consumer
dubbo.registry.address=zookeeper://$DOCKER_HOST:2181
dubbo.consumer.timeout=3000
与服务端:组装相同,需要根据自己的运行环境来修改 dubbo.registry.address 中定义的 $ DOCKER_HOST。请参阅步骤 3 的说明部分。
7、客户端:发起远程调用
运行 main 向已经启动的服务提供方发起一次远程调用。Dubbo 会先向 ZooKeeper 订阅服务地址,然后从返回的地址列表中选取一个,向对端发起调用:
public class ConsumerBootstrap {public static void main(String[] args) {public class ConsumerBootstrap {public static void main(String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
GreetingServiceConsumer greetingServiceConsumer = context.getBean(GreetingServiceConsumer.class);
String hello = greetingServiceConsumer.doSayHello( zookeeper
System.out.println(result: + hello);
System.in.read();}
运行结果如下:
[03/08/18 01:42:31:031 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Register: consumer://192.168.99.1/com.alibaba.dubbo.samples.api.GreetingService?application=demo-consumer category=consumers check=false default.timeout=3000 dubbo=2.6.2 interface=com.alibaba.dubbo.samples.api.GreetingService methods=sayHello pid=82406 side=consumer timestamp=1533274951195, dubbo version: 2.6.2, current host: 192.168.99.1 #1[03/08/18 01:42:31:031 CST] main INFO zookeeper.ZookeeperRegistry: [DUBBO] Subscribe: consumer://192.168.99.1/com.alibaba.dubbo.samples.api.GreetingService?application=demo-consumer category=providers,configurators,routers default.timeout=3000 dubbo=2.6.2 interface=com.alibaba.dubbo.samples.api.GreetingService methods=sayHello pid=82406 side=consumer timestamp=1533274951195, dubbo version: 2.6.2, current host: 192.168.99.1 #2...
result: hello, zookeeper
说明:
注册:消费者://192.168.99.1/… category= consumers&:消费者向 ZooKeeper 注册自己的信息,并放在 consumers 节点下
订阅:消费者://192.168.99.1/… 类别 = 提供商,配置器,路由器:消费者同时向动物园管理员订阅了 providers、configurators、routers 节点,其中 configurations 与多宝配置相关,routers 与路由规则相关,值得注意的英文 providers 节点的订阅,当有新的服务提供方加入后,由于订阅的关系,新的地址列表会推送给订阅方,服务的消费者也因此动态感知到了地址列表的变化。
通过 ZooKeeper 管理终端观察服务提供方的注册信息:
$ docker exec -it zookeeper bash
bash-4.4# bin/zkCli.sh -server localhost:218
Connecting to localhost:2181
Welcome to ZooKeeper!
JLine support is enabled
[zk: localhost:2181(CONNECTED) 4] ls /dubbo/com.alibaba.dubbo.samples.api.GreetingService/consumers[consumer%3A%2F%2F192.168.99.1%2Fcom.alibaba.dubbo.samples.api.GreetingService%3Fapplication%3Ddemo-consumer%26category%3Dconsumers%26check%3Dfalse%26default.timeout%3D3000%26dubbo%3D2.6.2%26interface%3Dcom.alibaba.dubbo.samples.api.GreetingService%26methods%3DsayHello%26pid%3D82406%26side%3Dconsumer%26timestamp%3D1533274951195]
可以看到 Dubbo 的服务消费者在 consumers 节点下注册了自己的 URL 地址:
consumer://192.168.99.1/com.alibaba.dubbo.samples.api.GreetingService?application=demo-consumer category=providers,configurators,routers default.timeout=3000 dubbo=2.6.2 interface=com.alibaba.dubbo.samples.api.GreetingService methods=sayHello pid=82406 side=consumer timestamp=1533274951195
到此,相信大家对“Dubbo 和 ZooKeeper 基本用法是什么”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!