共計 9019 個字符,預計需要花費 23 分鐘才能閱讀完成。
本篇內容主要講解“Dubbo 和 ZooKeeper 基本用法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“Dubbo 和 ZooKeeper 基本用法是什么”吧!
一、改造背景
在現代的分布式應用中,往往會出現節點和節點之間的協調問題,其中就包括了:選主,集群管理,分布式鎖,分布式配置管理,統一命名服務,狀態同步等訴求。Apache ZooKeeper,正如它的名字所暗示的那樣,動物園管理員,就是為了解決這些訴求的一個分布式協調服務框架。
為了保證系統的高可用,ZooKeeper 本身也可以部署成集群模式,稱之為 ZooKeeper Ensemble。ZooKeeper 集群中始終確保其中的一臺為 leader 的角色,并通過 ZAB(Zookeeper Atomic Broadcast Protocol)[1] 協議確保所有節點上的信息的一致??蛻舳丝梢栽L問集群中的任何一臺進行讀寫操作,而不用擔心數據出現不一致的現象。
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 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!