在Docker中运行Dubbo应用
更新歷史
- 2017.11.30 增加利用v3版本compose文件部署示例。
Dubbo概述
Dubbo是阿里開源的一個分布式服務框架,在國內粉絲很多。官網上的介紹是:
DUBBO是一個分布式服務框架,致力于提供高性能和透明化的RPC遠程服務調用方案,是阿里巴巴SOA服務化治理方案的核心框架,每天為2,000+個服務提供3,000,000,000+次訪問量支持,并被廣泛應用于阿里巴巴集團的各成員站點。
Dubbo的文檔很完整,網絡上資源也很多,這里就不再重復了。本文做這樣一個嘗試,將一個Dubbo應用容器化,部署到阿里云的容器服務上。
極簡Dubbo應用結構
在Dubbo世界里,服務調用方和服務提供方通過Dubbo的發現機制互相發現。一個最小的Dubbo應用包含如下三個服務:
- 服務提供者
- 服務調用方
- 發現機制(例如zookeeper)
zookeeper已經有Docker鏡像了,下面我們就會用Spring Boot開發服務提供方Service Producer和服務調用方Service Consumer。
定義服務接口
創建一個Maven模塊service-api,定義服務接口。
public interface Greetings {String say(String name); }這個接口很簡單,就是問好。
在pom.xml中引入對Dubbo的依賴:
<dependencies><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.3</version></dependency> </dependencies>我們用的是dubbo 2.5.3版本,讀者如果愿意嘗試更新的版本,可以自行升級。
服務提供方 Service Producer
創建一個Maven模塊service-producer,提供服務接口的實現。
public class GreetingsImpl implements Greetings {public String say(String name) {return "Greetings from " + name;} }為了能找到服務接口模塊,需要在pom.xml中定義對service-api的依賴。
<dependencies>...<dependency><groupId>com.example</groupId><artifactId>dubbo-service-api</artifactId><version>1.0-SNAPSHOT</version></dependency>Dubbo通過spring xml配置文件的方式聲明對zookeeper的訪問。在resources目錄下創建services.xml,其中最重要的內容是指定zookeeper的地址和端口,為了不把zookeeper的地址寫死在配置文件中,我們采用環境變量來指明服務地址。這也是12 factor應用的一個推薦實踐之一。
<dubbo:registry protocol="zookeeper" address="${ZOOKEEPER_SERVER}:2181" /><dubbo:protocol name="dubbo" port="20880" /><dubbo:service interface="com.example.service.Greetings" ref="greetingService"/><bean id="greetingService" class="com.example.service.producer.GreetingsImpl" />xml文件中的其他內容包括指定本服務的偵聽端口為20880,GreetingsImpl類實現的接口API類等。
下面要在pom.xml引入dubbo的項目依賴。
<dependencies>...<dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.5.3</version><exclusions><exclusion><artifactId>spring</artifactId><groupId>org.springframework</groupId></exclusion></exclusions></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version></dependency>我們準備用spring 4.x,所以把dubbo中自帶的老版本springframework剔除。
現在服務的實現類有了,我們需要一個主函數把實現類運行起來。Springboot有一個很好的特性,就是把一個Java應用的所有相關依賴打包成為一個超級JAR包,對于生成Docker鏡像來說非常方便。
首先在pom.xml中引入springboot依賴。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> ...創建一個Spring主應用。由于Dubbo采用xml配置文件的方式,要通過@ImportResource聲明加載services.xml配置文件。
@SpringBootApplication @ImportResource({"classpath:services.xml"}) public class Application {public static void main(String[] args) throws Exception{SpringApplication.run(Application.class, args);} }Springboot Web應用啟動后會自動偵聽8080端口。不過我們在這里沒有用到內置的tomcat和8080端口。如果你不喜歡這個多余的tomcat,可以用spring-boot-starter替換本文中的spring-boot-starter-web項目,但要注意的是,沒有tomcat的代碼需要增加不退出應用的邏輯。
服務調用方 Service Consumer
Service Consumer的結構和Producer的結構類似,也需要在pom.xml中引入對dubbo, service-api和springboot的依賴。在resouces目錄下創建services.xml,聲明zookeeper的地址和要訪問的服務接口:
<dubbo:registry protocol="zookeeper" address="${ZOOKEEPER_SERVER}:2181" /> <dubbo:reference id="greetingService" interface="com.example.service.Greetings" />遠程調用的服務bean名字為greetingService,在下面的代碼中要用到。
在Application主應用中調用Service Producer。
Greetings greetingService = (Greetings)context.getBean("greetingService"); String result = greetingService.say("Dubbo Docker");為了能夠用HTTP訪問Consumer應用,我們用@RequestMapping將context root /映射到方法上。
@RequestMapping("/") public String greetings(){...Consumer啟動偵聽的端口在resources/application.properties文件中指定:
server.port=${SERVER_PORT:0}編譯并在本地運行
在項目的根目錄下運行Maven編譯:
mvn package從Docker鏡像中啟動zookeeper,并把2181端口映射到本機:
docker run -d -p 2181:2181 -p 2888:2888 -p 3888:3888 registry.aliyuncs.com/acs-sample/zookeeper:3.4.8在環境變量中指定zookeeper地址,啟動Service Producer。
export ZOOKEEPER_SERVER=127.0.0.1 java -jar target/dubbo-service-producer-1.0-SNAPSHOT.jar啟動Service Consumer時除了要指定zookeeper地址外,還要指定consumer自己偵聽的地址,本示例中使用的是8899。
export ZOOKEEPER_SERVER=127.0.0.1 export SERVER_PORT=8899 java -jar target/dubbo-service-consumer-1.0-SNAPSHOT.jar訪問一下cosumer的HTTP 8899端口,可以看到消息的輸出。說明服務調用方從zookeeper中獲得了正確的producer的地址,并用dubbo遠程調用協議成功調用了producer的GreetingService。
$curl http://localhost:8899/ Greetings from Dubbo Docker構建Docker鏡像
為Producer和Consumer構建Docker鏡像和正常的SpringBoot應用一樣,Dockerfile內容如下:
FROM openjdk:8-jre VOLUME /tmp COPY target/*.jar app.jar RUN sh -c 'touch /app.jar' CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]把這個文件分別放在Producer和Consumer的目錄下,執行Docker的編譯命令即可打包生成容器鏡像。
在service-producer目錄下運行:
mvn package docker build -t producer .生成service-consumer鏡像類似,這里就不重復了。
兩個鏡像生成后,可以用Docker Compose命令啟動。對應的docker-compose.yml內容如下:
version: "2" services:zookeeper:image: 'registry.aliyuncs.com/acs-sample/zookeeper:3.4.8'hostname: zookeeperproducer:image: 'producer:latest'environment:- ZOOKEEPER_SERVER=zookeeperconsumer:image: 'consumer:latest'environment:- ZOOKEEPER_SERVER=zookeeper- SERVER_PORT=8899ports:- 8899:8899在這里把zookeeper容器的主機名hostname設置為zookeeper并通過環境變量傳給producer和consumer。運行Docker Compose啟動三個容器。
$docker-compose up -d Creating docker_consumer_1 Creating docker_zookeeper_1 Creating docker_producer_1容器啟動成功后用同樣方式訪問8899端口可以看到正確的輸出。
$curl http://localhost:8899/ Greetings from Dubbo Docker部署到阿里云容器上
好了,至此我們已經成功地在本地Docker環境中運行了Dubbo應用,下面就要將這個應用部署到阿里云容器服務上。
首先登陸阿里云Docker鏡像倉庫,地址在此https://cr.console.aliyun.com/,創建2個鏡像倉庫。在本示例中命名為dubbo-springboot-producer和dubbo-springboot-consumer。
創建一個為阿里云部署的模版文件,docker-compose-acs.yml,內容和docker-compose.yml類似。
version: "2" services:zookeeper:image: 'registry.aliyuncs.com/acs-sample/zookeeper:3.4.8'hostname: zookeeperproducer:image: 'registry.cn-hangzhou.aliyuncs.com/${rname}/dubbo-springboot-producer:latest'environment:- ZOOKEEPER_SERVER=zookeeperconsumer:image: 'registry.cn-hangzhou.aliyuncs.com/${rname}/dubbo-springboot-consumer:latest'environment:- ZOOKEEPER_SERVER=zookeeper- SERVER_PORT=8899labels:aliyun.routing.port_8899: http://ds-consumer這個部署文件和docker-compose.yml內容不同之處在于,所有容器到主機端口映射都去掉了,為了能訪問consumer,使用了aliyun.routing.port_8899為consumer指定一個子域名。集群部署后可用如下URL訪問consumer服務。
http://ds-consumer.c67***8cd5.cn-shenzhen.alicontainer.com登陸阿里云容器服務控制臺 https://cs.console.aliyun.com,利用部署模版創建一個新應用,部署模版的內容就是上面docker-compose-acs.yml內容,提示rname時輸入你的容器倉庫用戶名,很快應用部署就會成功。
在控制臺中進入consumer服務頁面,找到訪問端點:
點擊地址,可以在瀏覽器中看到輸出:
至此,我們成功地在云上運行了Dubbo應用。
本文中的compose模版部署為v2版本,如果大家想嘗試利用v3版本部署,可以訪問github
討論
在網上有討論容器化的Dubbo應用發送的IP地址不對,經實測在Docker 1.12版本下沒有這個問題,部署到阿里云容器服務上也正常。本文的示例代碼在github上,大家可以參考。
小節
本文通過Spring Boot構建了一個最小的Dubbo應用,容器化后成功部署到阿里云容器服務上。
總結
以上是生活随笔為你收集整理的在Docker中运行Dubbo应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 事务BEGIN TRANSACTION
- 下一篇: leetcode202(Floyd判圈算