Apache Dubbo
是一款高效能、輕量級的開源 Java
RPC
框架,它提供了三大核心能力:面向介面的遠端方法呼叫,智慧容錯和負載均衡,以及服務自動註冊和發現。
注意,是
Apache Dubbo
,不再是Alibaba Dubbo
。簡單來說就是Alibaba
將Dubbo
移交給Apache
開源社群進行維護。參見 dubbo-spring-boot-project
Spring Boot 系列:整合 Alibaba Dubbo
一、本文示例說明
1.1 框架版本
Dubbo
版本
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
Spring Boot
版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/>
</parent>
1.2 模組關係
- 根工程
order
:管理工程資訊; - 子工程
order-api
:定義RPC
服務的介面、引數以及響應結果的結果集; - 子工程
order-provider
:RPC
服務的提供端; - 子工程
order-consumer
:RPC
服務的消費端,實際開發過程中實際情況是其它服務的呼叫該訂單RPC
服務
二、根工程
2.1 建立專案 order
我這裡為了和之前老版本的
alibaba
的dubbo
專案區分,檔名取為apache-dubbo-demo
,maven
專案名稱為order
。
該專案主要作用是定義工程資訊、管理整個專案依賴版本等等,所以src
目錄不需要。
2.2 pom.xml
根工程中使用了<dependencyManagement>
和<dependencies>
進行依賴管理。
<dependencyManagement>
:宣告全域性依賴,當子專案指定引用才會繼承依賴;<dependencies>
:宣告全域性依賴,子專案直接自動繼承依賴。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父級引用 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/>
</parent>
<!-- 基本資訊 -->
<groupId>cn.van.order</groupId>
<artifactId>order</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<description>Apache Dubbo 根專案</description>
<!--配置-->
<properties>
<java.version>1.8</java.version>
<dubbo.version>2.7.5</dubbo.version>
<zookeeper.version>3.4.14</zookeeper.version>
</properties>
<!-- 子專案 -->
<modules>
<module>order-api</module>
<module>order-provider</module>
<module>order-consumer</module>
</modules>
<!--宣告全域性依賴(子專案需要顯示的引用才會繼承依賴)-->
<dependencyManagement>
<dependencies>
<!-- dubbo-start依賴 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!--zookeeper 註冊中心客戶端引入 使用的是curator客戶端 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<!--宣告全域性依賴(子專案不需要顯示的引用,自動繼承依賴)-->
<dependencies>
<!-- spring boot 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- 打包外掛 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
三、order-api
3.1 專案依賴
無需更多依賴,所以很簡單。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.van.order</groupId>
<artifactId>order</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>cn.van.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<description>dubbo公共專案</description>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.2 封裝 RPC
結果集
- 先封裝一個返回碼列舉類
ResultCodeEnum.java
public enum ResultCodeEnum {
/*** 通用部分 100 - 599***/
// 成功請求
SUCCESS(200, "successful"),
/*** 這裡可以根據不同模組用不同的區級分開錯誤碼,例如: ***/
// 1000~1999 區間表示使用者模組錯誤
// 2000~2999 區間表示訂單模組錯誤
// 3000~3999 區間表示商品模組錯誤
// 。。。
ORDER_NOT_FOUND(2000, "order not found"),
;
/**
* 響應狀態碼
*/
private Integer code;
/**
* 響應資訊
*/
private String message;
ResultCodeEnum(Integer code, String msg) {
this.code = code;
this.message = msg;
}
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 先封裝一個RPC 響應結果集
RpcResult.java
public class RpcResult <T> implements Serializable {
/**
* 是否響應成功
*/
private Boolean success;
/**
* 響應狀態碼
*/
private Integer code;
/**
* 響應資料
*/
private T data;
/**
* 錯誤資訊
*/
private String message;
// 構造器開始
/**
* 無參構造器(構造器私有,外部不可以直接建立)
*/
private RpcResult() {
this.code = 200;
this.success = true;
}
/**
* 有參構造器
* @param obj
*/
private RpcResult(T obj) {
this.code = 200;
this.data = obj;
this.success = true;
}
/**
* 有參構造器
* @param resultCode
*/
private RpcResult(ResultCodeEnum resultCode) {
this.success = false;
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
// 構造器結束
/**
* 通用返回成功(沒有返回結果)
* @param <T>
* @return
*/
public static<T> RpcResult<T> success(){
return new RpcResult();
}
/**
* 返回成功(有返回結果)
* @param data
* @param <T>
* @return
*/
public static<T> RpcResult<T> success(T data){
return new RpcResult<T>(data);
}
/**
* 通用返回失敗
* @param resultCode
* @param <T>
* @return
*/
public static<T> RpcResult<T> failure(ResultCodeEnum resultCode){
return new RpcResult<T>(resultCode);
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "RpcResult{" +
"success=" + success +
", code=" + code +
", data=" + data +
", message='" + message + '\'' +
'}';
}
}
3.3 編寫一個 RPC
介面
public interface OrderDubboService {
RpcResult<OrderDomain> getOrder();
}
實體
OrderDomain.java
挺簡單的,詳見Github
倉庫。
四、order-provider
此子專案是一個服務類專案,也就是將介面服務註冊到zookeeper
註冊中心供消費端調取使用。
4.1 專案依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.van.order</groupId>
<artifactId>order</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>cn.van.order</groupId>
<artifactId>order-provider</artifactId>
<version>1.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<description>Dubbo 服務提供者</description>
<dependencies>
<dependency>
<groupId>cn.van.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- zookeeper依賴 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.2 服務實現介面
@Service
public class OrderDubboServiceImpl implements OrderDubboService {
@Override
public RpcResult<OrderDomain> getOrder() {
return RpcResult.success(new OrderDomain(1, 10086, LocalDateTime.now()));
}
}
注意:
@Service
是 dubbo
包下面的註解不是 Spring
裡面的註解。
4.3 專案配置
dubbo
的配置直接用dubbo
,不再以Spring
開頭;base-packages
:指定介面實現所在路徑。
server:
# 服務埠
port: 7777
spring:
application:
name: order-provider
# dubbo 相關配置(dubbo 的配置不再以 Spring 開頭)
dubbo:
application:
# 應用名稱
name: order-provider
scan:
# 介面實現者(服務實現)包
base-packages: cn.van.order.service.impl
# 註冊中心資訊
registry:
address: zookeeper://127.0.0.1:2181
protocol:
# 協議名稱
name: dubbo
# 協議埠
port: 20880
五、order-consumer
此子專案就是一個消費專案,比如商品模組、財務模組等等。
5.1 專案依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.van.order</groupId>
<artifactId>order</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>cn.van.order</groupId>
<artifactId>order-consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<description>Dubbo 消費者</description>
<dependencies>
<dependency>
<groupId>cn.van.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- web專案依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- dubbo依賴 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- dubbo的zookeeper依賴 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5.2 測試介面
模擬一個介面獲取訂單詳情。
@RestController
@RequestMapping("/order")
public class OrderConsumerController {
@Reference
OrderDubboService orderDubboService;
@GetMapping("getOrder")
public RpcResult getOrder() {
return orderDubboService.getOrder();
}
}
注意:@Reference
引入的是 Dubbo
介面,所以是 Dubbo
的註解。
5.3 配置檔案
server:
port: 7000
spring:
application:
name: order-consumer
# dubbo 相關配置
dubbo:
application:
name: order-consumer
registry:
address: zookeeper://127.0.0.1:2181
六、測試
一切就緒,如果在order-consumer
的測試介面能成功請求到資料,則證明 Dubbo
服務搭建成功。
6.1 啟動 zookeeper
我們選用zookeeper
作為註冊中心,因此啟動專案之前需要先啟動它。
6.2 dubbo-admin
dubbo-admin
便於觀察 order-provider
是否成功將介面註冊,具體安裝步驟詳見apache/dubbo-admin
預設埠:
8080
。
6.3 啟動 dubbo-provider
成功啟動後可以在dubbo-admin
:已經成功將介面 OrderService
註冊到 zookeeper
上如下:
成功將藉口註冊到註冊中心,說明dubbo-provider
註冊成功。
6.4 啟動 order-cosumer
啟動消費者專案,在瀏覽器請求消費介面:http://localhost:7000/order/getOrder,成功返回資料如下:
{
"success":true,
"code":200,
"data":{
"id":1,
"orderNum":10086,
"gmtCreate":"2020-05-06T11:59:45.535"
},
"message":null
}
成功請求到 order-provider
提供的資料,說明 Dubbo
搭建成功!
七、總結
以上的完整程式碼我已上傳到 Github,需要的可以自取測試,歡迎star
!