SOFARPC 集成 ZooKeeper 註冊中心

SOFARPC 是近期螞蟻金服開源的一個高可擴展性、高性能、生產級的 Java RPC 框架。在螞蟻金服 SOFARPC 已經經歷了十多年及五代版本的發展。SOFARPC 致力於簡化應用之間的 RPC 調用,為應用提供方便透明、穩定高效的點對點遠程服務調用方案。為了用戶和開發者方便的進行功能擴展,SOFARPC 提供了豐富的模型抽象和可擴展介面,包括過濾器、路由、負載均衡等等。

SOFARPC 可以集成多種註冊中心實現,其中一種就是常用的 ZooKeeper。

ZooKeeper 作為一個開源的分散式應用協調系統,已經用到了許多分散式項目中,用來完成統一命名服務、狀態同步服務、集群管理、分散式應用配置項的管理等工作。

本文將介紹 SOFARPC 是使用 ZooKeeper 作為註冊中心的用法。

1. ZooKeeper 註冊中心安裝

這裡介紹下 ZooKeeper 單機模式兩種安裝方式,集群模式請參考下其他文檔。

1.1 基於壓縮包安裝

第一步:去官網下載 zookeeper.apache.org/re

例如目前最新版是 v3.4.11,我們下載壓縮包zookeeper-3.4.11.tar.gz,然後解壓到文件夾下,例如 /home/admin/zookeeper-3.4.11

第二步:設置配置文件,可以直接從樣例複製一份。

$ cd /home/admin/zookeeper-3.4.11$ cp conf/zoo_sample.cfg conf/zoo.cfg

第三步:到 ZooKeeper 安裝目錄下直接啟動ZooKeeper。

$ cd /home/admin/zookeeper-3.4.11$ sh bin/zkServer.sh startZooKeeper JMX enabled by defaultUsing config: /Users/zhanggeng/dev/zookeeper/bin/../conf/zoo.cfg-n Starting zookeeper ...STARTED

第四步:我們使用四字命令檢查下。

$ echo stat | nc 127.0.0.1 2181Zookeeper version: 3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT...

第五步:如果需要查看數據,直接運行 zkCli.sh,連接後執行 ls /即可。

$ sh bin/zkCli.shConnecting to localhost:2181......WatchedEvent state:SyncConnected type:None path:null[zk: localhost:2181(CONNECTED) 0] ls /[zookeeper]

1.2 基於 Docker 安裝

如果您已安裝了 Docker,那麼可以選擇使用鏡像啟動 ZooKeeper。

$ docker image pull zookeeper:3.4.11$ docker run -i -t --name my_zookeeper -p2181:2181 -d zookeeper:3.4.11

我們查看下啟動日誌:

$ docker logs -f my_zookeeperZooKeeper JMX enabled by defaultUsing config: /conf/zoo.cfg2018-04-16 07:38:59,373 [myid:] - INFO [main:QuorumPeerConfig@136] - Reading configuration from: /conf/zoo.cfg......2018-04-16 07:23:41,187 [myid:] - INFO [main:NIOServerCnxnFactory@89] - binding to port 0.0.0.0/0.0.0.0:2181

可以看到埠已經啟動並發布,我們使用四字命令檢查下。

$ echo stat | nc 127.0.0.1 2181Zookeeper version: 3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT...

我們可以查看啟動的容器運行狀態、關閉、重啟,參考命令如下:

$ docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES30b13a744254 zookeeper:3.4.11 "/docker-entrypoin..." 23 hours ago Up 42 seconds 2888/tcp, 0.0.0.0:2181->2181/tcp, 3888/tcp my_zookeeper## 關閉重啟的話$ docker container stop 30b13a744254$ docker container start 30b13a744254

如果需要使用 ZooKeeper 客戶端查看查看數據,參考命令如下:

$ docker exec -it 30b13a744254 zkCli.shConnecting to localhost:2181......WatchedEvent state:SyncConnected type:None path:null[zk: localhost:2181(CONNECTED) 0] ls /[zookeeper]

2. SOFARPC 集成 ZooKeeper 註冊中心

2.1 新建工程

運行需要 JDK 6 及以上、 Maven 3.2.5 以上。

首先我們在 IDE 里新建一個普通 Maven 工程,然後在 pom.xml 中引入如下 RPC 和 ZooKeeper 相關依賴:

<dependencies> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>sofa-rpc-all</artifactId> <version>5.3.1</version> <dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.9.1</version> </dependency></dependencies>

2.2 編寫服務提供端

第一步:創建介面

package org.howtimeflies.sofa.rpc;public interface HelloService { public String sayHello(String name);}

第二步:創建介面實現

package org.howtimeflies.sofa.rpc;public class HelloServiceImpl implements HelloService { public String sayHello(String name) { return "hello " + name; }}

第三步:編寫服務端代碼

package org.howtimeflies.sofa.rpc;import com.alipay.sofa.rpc.config.ProviderConfig;import com.alipay.sofa.rpc.config.RegistryConfig;import com.alipay.sofa.rpc.config.ServerConfig;public class ServerMain { public static void main(String[] args) { // 指定註冊中心 RegistryConfig registryConfig = new RegistryConfig() .setProtocol("zookeeper") .setAddress("127.0.0.1:2181"); // 指定服務端協議和地址 ServerConfig serverConfig = new ServerConfig() .setProtocol("bolt") .setPort(12345) .setDaemon(false); // 發布一個服務 ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>() .setInterfaceId(HelloService.class.getName()) .setRef(new HelloServiceImpl()) .setRegistry(registryConfig) .setServer(serverConfig); providerConfig.export(); }}

2.3 編寫服務調用端

我們拿到了服務端的介面,就可以編寫服務端調用端代碼

package org.howtimeflies.sofa.rpc;import com.alipay.sofa.rpc.config.ConsumerConfig;import com.alipay.sofa.rpc.config.RegistryConfig;public class ClientMain { public static void main(String[] args) { // 指定註冊中心 RegistryConfig registryConfig = new RegistryConfig() .setProtocol("zookeeper") .setAddress("127.0.0.1:2181"); // 引用一個服務 ConsumerConfig<HelloService> consumerConfig = new ConsumerConfig<HelloService>() .setInterfaceId(HelloService.class.getName()) .setProtocol("bolt") .setRegistry(registryConfig); // 拿到代理類 HelloService service = consumerConfig.refer(); // 發起調用 while (true) { System.out.println(service.sayHello("world")); try { Thread.sleep(1000); } catch (InterruptedException e) { } } }}

2.4 運行

我們先運行服務提供端程序 ServerMain,然後去 ZooKeeper上看下服務訂閱情況。

$ sh bin/zkCli.shConnecting to localhost:2181......WatchedEvent state:SyncConnected type:None path:null[zk: localhost:2181(CONNECTED) 4] ls /sofa-rpc/org.howtimeflies.sofa.rpc.HelloService/providers[bolt%3A%2F%2F10.15.232.61%3A12345%3FuniqueId%3D%26version%3D1.0%26timeout%3D0%26delay%3D-1%26id%3Drpc-cfg-0%26dynamic%3Dtrue%26weight%3D100%26accepts%3D100000%26startTime%3D1523967648457%26pid%3D17664%26language%3Djava%26rpcVer%3D50301]

然後在運行服務端調用端 ClientMain

運行結果如下:

hello worldhello worldhello worldhello world

我們也可以去 ZooKeeper上看下服務訂閱情況,

sh bin/zkCli.shConnecting to localhost:2181......WatchedEvent state:SyncConnected type:None path:null[zk: localhost:2181(CONNECTED) 5] ls /sofa-rpc/org.howtimeflies.sofa.rpc.HelloService/consumers[bolt%3A%2F%2F10.15.232.61%2Forg.howtimeflies.sofa.rpc.HelloService%3FuniqueId%3D%26version%3D1.0%26pid%3D17921%26timeout%3D3000%26id%3Drpc-cfg-0%26generic%3Dfalse%26serialization%3Dhessian2%26startTime%3D1523968102764%26pid%3D17921%26language%3Djava%26rpcVer%3D50301]

3. 在 SOFABoot 使用 SOFARPC 及 ZooKeeper 註冊中心

SOFABoot 是螞蟻金服開源的基於 Spring Boot 的研發框架,它在增強了 Spring Boot 的同時,SOFABoot 提供了讓用戶可以在 Spring Boot 中非常方便地使用 SOFAStack 相關中間件的能力。

SOFARPC 也實現以一個 rpc-sofa-boot-starter 可以方便的集成到 SOFABoot 應用。目前只支持Spring XML 方式發布和引用服務,下一個版本將支持 Annotation 方式發布和引用服務。

3.1 創建 SpringBoot 工程

SOFABoot 運行需要 JDK 7 及以上、 Maven 3.2.5 以上。

我們可以使用 Spring Boot 的工程生成工具 來生成一個標準的 Spring Boot 工程。

3.2 引入 SOFABoot 和 rpc-sofa-boot-starter

我們將工程導入到 IDE 中,然後在 pom.xml 將 Spring Boot 工程轉為一個 SOFABoot 工程,很簡單,只要加入依賴管控即可。

<dependencyManagement> <dependencies> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>sofaboot-dependencies</artifactId> <version>2.3.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>

然後再在 pom.xml 中引入 rpc-sofa-boot-starter 的依賴:

<dependencies> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>rpc-sofa-boot-starter</artifactId> <version>5.3.1</version> </dependency></dependencies>

3.3 編寫服務提供端

第一步:創建介面

package org.howtimeflies.sofa.rpc;public interface HelloService { public String sayHello(String name);}

第二步:創建介面實現

package org.howtimeflies.sofa.rpc;public class HelloServiceImpl implements HelloService { public String sayHello(String name) { return "hello " + name; }}

第三步:發布服務

我們通過 SpringBean 的方式發布服務,新建一個 Spring 的 xml,例如 src/main/resource/rpc-server.xml,注意文件頭要保持一致。

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sofa="http://sofastack.io/schema/sofaboot" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd" default-autowire="byName"> <bean id="helloServiceImpl" class="org.howtimeflies.sofa.rpc.HelloServiceImpl"/> <sofa:service interface="org.howtimeflies.sofa.rpc.HelloService" ref="helloServiceImpl"> <sofa:binding.bolt/> </sofa:service></beans>

3.4 編寫服務調用端

同樣服務端調用端也通過 SpringBean 的方式引用一個服務。新建一個 Spring 的 xml,例如 src/main/resource/rpc-client.xml,注意文件頭要保持一致。

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sofa="http://sofastack.io/schema/sofaboot" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd" default-autowire="byName"> <sofa:reference id="helloServiceRef" interface="org.howtimeflies.sofa.rpc.HelloService"> <sofa:binding.bolt/> </sofa:reference></beans>

3.5 指定註冊中心地址

我們需要在 src/main/resource/application.properties 里指定我們的應用名和註冊中心地址

# 指定應用名spring.application.name=test# 指定日誌路徑logging.path=./logs# 註冊中心地址com.alipay.sofa.rpc.registry.address=zookeeper://127.0.0.1:2181

3.6 運行

我們在生成代碼里找到了默認的啟動類 XXXApplication.java,名字自動生成的,例如本例是為:org.howtimeflies.sofa.rpc.SofaRpcSofaBootZookeeperDemoApplication

它的原始內容如下:

package org.howtimeflies.sofa.rpc;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class SofaRpcSofaBootZookeeperDemoApplication { public static void main(String[] args) { SpringApplication.run(SofaRpcSofaBootZookeeperDemoApplication.class, args); }}

可以看到裡面並未指定載入的文件,我們將啟動類改造下,引入 Spring XML 的配置,以及我們的調用代碼,如下:

package org.howtimeflies.sofa.rpc;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.ImportResource;@SpringBootApplication@ImportResource({"rpc-server.xml","rpc-client.xml"}) // 引入載入的 Spring XMLpublic class SofaRpcSofaBootZookeeperDemoApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(SofaRpcSofaBootZookeeperDemoApplication.class, args); // 等待ZooKeeper下發地址 try { Thread.sleep(2000); } catch (Exception e) { } // 拿到調用端 進行 調用 HelloService helloService = (HelloService) context.getBean("helloServiceRef"); String hi = helloService.sayHello("world"); System.out.println(hi); }}

直接運行 SofaRpcSofaBootZookeeperDemoApplication,結果如下:

. ____ _ __ _ _ /\ / ____ __ _ _(_)_ __ __ _ ( ( )\___ | _ | _| | _ / _` | \/ ___)| |_)| | | | | || (_| | ) ) ) ) |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.4.2.RELEASE)......2018-04-17 21:42:13.249 INFO 20211 --- [ main] .SofaRpcSofaBootZookeeperDemoApplication : Started SofaRpcSofaBootZookeeperDemoApplication in 5.958 seconds (JVM running for 6.75)hello world

至此,使用 ZooKeeper 作為 SOFARPC 的註冊中心介紹完了。

相關資源下載

DEMO:

  • sofa-rpc-zookeeper-demo:https://github.com/ujjboy/sofa-rpc-zookeeper-demo
  • sofa-rpc-sofa-boot-zookeeper-demo:github.com/ujjboy/sofa-

源碼:

  • sofa-rpc:github.com/alipay/sofa-
  • sofa-boot:github.com/alipay/sofa-

推薦閱讀:

面試必備:什麼是一致性Hash演算法?
HSF的發布以及調用
Elasticsearch分散式一致性原理剖析(一)-節點篇
分散式系統設計:服務(多節點)模式
Design patterns for container-based distributed systems(HotCloud 2016)

TAG:ZooKeeper | HBase | 分散式系統 |