Dubbo 介紹

官網:http://dubbo.apache.org/zh-cn/
Github:https://github.com/apache/dubbo
2018 年 2 月 15 日,阿里巴巴的服務治理框架 dubbo 通過投票,順利成為 Apache 基金會孵化項目。
Apache Dubbo 是一款高性能、輕量級的開源 Java RPC 框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動注冊和發現。
Dubbo 架構
Dubbo 提供三個核心功能:基於接口的遠程調用、容錯和負載均衡,以及服務的自動注冊與發現。Dubbo 框架廣泛的在阿里巴巴內部使用,以及當當、去哪兒、網易考拉、滴滴等都在使用。

節點角色說明
節點 | 角色說明 |
---|---|
Provider |
暴露服務的服務提供方 |
Consumer |
調用遠程服務的服務消費方 |
Registry |
服務注冊與發現的注冊中心 |
Monitor |
統計服務的調用次數和調用時間的監控中心 |
Container |
服務運行容器 |
調用關系說明
-
服務容器負責啟動,加載,運行服務提供者。 -
服務提供者在啟動時,向注冊中心注冊自己提供的服務。 -
服務消費者在啟動時,向注冊中心訂閱自己所需的服務。 -
注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基於長連接推送變更數據給消費者。 -
服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。 -
服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鍾發送一次統計數據到監控中心。
Dubbo 快速入門
我們先通過一個簡單的案例讓大家理解一下 Dubbo 的使用,然后基於 Spring Boot 和 Spring Cloud 環境整合 Dubbo。
Dubbo 采用全 Spring 配置方式,透明化接入應用,對應用沒有任何 API 侵入,只需用 Spring 加載 Dubbo 的配置即可。
依賴
JDK 1.6 以上和 Maven 3.0 以上,采用 Maven 多模塊聚合工程構建 api 模塊,provider 模塊以及 consumer 模塊。
聚合工程
項目結構如下圖,簡單介紹一下:
-
dubbo-api
:服務接口 -
dubbo-provider
:依賴服務接口,具體的業務實現,服務提供者 -
dubbo-coonsumer
:依賴服務接口,遠程調用服務,服務消費者

依賴關系
dubbo-parent 的 pom.xml 依賴 apache dubbo。
<dependencies>
<!-- apache dubbo 依賴 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.4.1</version> </dependency> </dependencies>
dubbo-provider 和 dubbo-consumer 的 pom.xml 依賴 dubbo-api 服務接口。
<dependencies>
<!-- dubbo-api 依賴 --> <dependency> <groupId>org.example</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
定義服務接口
dubbo-api 中編寫 HelloService.java
package org.example.service;
/** * Hello服務 */ public interface HelloService { String sayHello(String name); }
定義服務提供者
在 provider 模塊中實現服務接口
dubbo-provider 中編寫 HelloServiceImpl.java
package org.example.service.impl;
import org.example.service.HelloService; /** * 服務實現 */ public class HelloServiceImpl implements HelloService { public String sayHello(String name) { return "hello " + name; } }
配置服務提供者
dubbo-provider.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:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 提供方應用信息,用於計算依賴關系 --> <dubbo:application name="hello-world-app"/> <!-- 使用 multicast 廣播注冊中心暴露服務地址 --> <dubbo:registry address="multicast://224.5.6.7:1234"/> <!-- 用 dubbo 協議在 20880 端口暴露服務 --> <dubbo:protocol name="dubbo" port="20880"/> <!-- 聲明需要暴露的服務接口 --> <dubbo:service interface="org.example.service.HelloService" ref="helloService"/> <!-- 和本地 bean 一樣實現服務 --> <bean id="helloService" class="org.example.service.impl.HelloServiceImpl"/> </beans>
加載 Spring 配置啟動服務
package org.example;
import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 發布服務 */ public class Provider { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml"); context.start(); System.out.println("服務注冊成功!"); System.in.read(); // 按任意鍵退出 } }
定義服務消費者
通過 Spring 配置引用遠程服務
dubbo-consumer.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:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 消費方應用名,用於計算依賴關系,不是匹配條件,不要與提供方一樣 --> <dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用 multicast 廣播注冊中心暴露發現服務地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 生成遠程服務代理,可以和本地 bean 一樣使用 helloService --> <dubbo:reference id="helloService" interface="org.example.service.HelloService" /> </beans>
加載 Spring 配置並調用遠程服務
package org.example;
import org.example.service.HelloService; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 調用遠程服務 */ public class Consumer { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml"); context.start(); HelloService helloService = (HelloService) context.getBean("helloService"); // 獲取遠程服務代理 String result = helloService.sayHello("world"); // 執行遠程方法 System.out.println(result); // 顯示調用結果 } }
Dubbo 常用標簽
-
dubbo:application
:應用程序名稱 -
dubbo:registry
:連接注冊中心信息(配置注冊中心) -
dubbo:protocol
:服務提供者注冊服務采用的協議-
Dubbo 協議,默認 -
RMI 協議 -
Hessian 協議 -
HTTP 協議 -
WebService 協議 -
Thrift 協議 -
Memcached 協議 -
Redis 協議 -
Rest 協議(RESTful) -
Grpc 協議 -
更多協議信息請參考:http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html
-
-
dubbo:service
:聲明需要暴露的服務接口 -
dubbo:reference
:配置訂閱的服務(生成遠程服務代理)
更多配置信息請參考:http://dubbo.apache.org/zh-cn/docs/user/references/xml/introduction.html
注冊中心
注冊中心我們已經學習了不少,例如:ZooKeeper、Eureka、Consul、Nacos 等等,注冊中心可以更高效的管理系統的服務:比如服務接口的發布、自動剔除無效的服務、自動恢復服務等。
Dubbo 支持五種注冊中心:Multicast、Nacos(推薦)、ZooKeeper(推薦) 、Redis、Simple。本文重點介紹前兩個,更多注冊中心的信息請參考:http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html
Multicast 注冊中心
Multicast 注冊中心不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。

-
提供方啟動時廣播自己的地址 -
消費方啟動時廣播訂閱請求 -
提供方收到訂閱請求時,單播自己的地址給訂閱者,如果設置了 unicast=false
,則廣播給訂閱者 -
消費方收到提供方地址時,連接該地址進行 RPC 調用。
組播受網絡結構限制,只適合小規模應用或開發階段使用。組播地址段: 224.0.0.0 - 239.255.255.255
配置
<dubbo:registry address="multicast://224.5.6.7:1234" />
或
<dubbo:registry protocol="multicast" address="224.5.6.7:1234" />
為了減少廣播量,Dubbo 缺省使用單播發送提供者地址信息給消費者,如果一個機器上同時啟了多個消費者進程,消費者需聲明 unicast=false
,否則只會有一個消費者能收到消息。
當服務者和消費者運行在同一台機器上,消費者同樣需要聲明unicast=false
,否則消費者無法收到消息,導致 No provider available for the service 異常。
<dubbo:registry address="multicast://224.5.6.7:1234?unicast=false" />
或
<dubbo:registry protocol="multicast" address="224.5.6.7:1234">
<dubbo:parameter key="unicast" value="false" /> </dubbo:registry>
zookeeper 注冊中心
Apache ZooKeeper 是一個開放源碼的分布式應用程序協調組件,是 Hadoop 和 Hbase 的重要組件。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。適合作為 Dubbo 服務的注冊中心,工業強度較高,可用於生產環境,推薦使用。
在微服務項目開發中 ZooKeeper 主要的角色是當做服務注冊中心存在,我們將編寫好的服務注冊至 ZooKeeper 即可。

流程說明:
-
服務提供者啟動時: 向 /dubbo/com.foo.BarService/providers
目錄下寫入自己的 URL 地址。 -
服務消費者啟動時: 訂閱 /dubbo/com.foo.BarService/providers
目錄下的提供者 URL 地址。並向/dubbo/com.foo.BarService/consumers
目錄下寫入自己的 URL 地址。 -
監控中心啟動時: 訂閱 /dubbo/com.foo.BarService
目錄下的所有提供者和消費者 URL 地址。
支持以下功能:
-
當提供者出現斷電等異常停機時,注冊中心能自動刪除提供者信息; -
當注冊中心重啟時,能自動恢復注冊數據,以及訂閱請求; -
當會話過期時,能自動恢復注冊數據,以及訂閱請求; -
當設置 <dubbo:registry check="false" />
時,記錄失敗注冊和訂閱請求,后台定時重試; -
可通過 <dubbo:registry username="admin" password="1234" />
設置 zookeeper 登錄信息; -
可通過 <dubbo:registry group="dubbo" />
設置 zookeeper 的根節點,不配置將使用默認的根節點; -
支持 *
號通配符<dubbo:reference group="*" version="*" />
,可訂閱服務的所有分組和所有版本的提供者。
❝作為 Dubbo 的老牌黃金搭檔 ZooKeeper,我們在單獨講解 Dubbo 時已經給大家分享過如何使用了,本文系 Spring Cloud Alibaba 系列文章,重點對象是 Nacos,所以 ZooKeeper 這里就不過多贅述了。
❞
Nacos 注冊中心
Nacos 是 Alibaba 公司推出的開源工具,用於實現分布式系統的服務發現與配置管理。Nacos 是 Dubbo 生態系統中重要的注冊中心實現,其中 dubbo-registry-nacos 則是 Dubbo 融合 Nacos 注冊中心的實現,推薦使用。
Nacos 官網:https://nacos.io/zh-cn/
Github:https://github.com/alibaba/nacos
預備工作
當您將 Nacos 整合到您的 Dubbo 工程之前,請確保后台已經啟動 Nacos 服務。關於 Nacos 的安裝和其他詳細內容可參考我之前的文章 Spring Cloud 系列之 Alibaba Nacos 注冊中心。
快速上手
Dubbo 融合 Nacos 成為注冊中心的操作步驟非常簡單,大致步驟可分為“增加 Maven 依賴”和“配置注冊中心“。
依賴
核心依賴主要是 dubbo-registry-nacos
和 nacos-client
。
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-registry-nacos -->
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.4.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.3.0</version> </dependency>
配置注冊中心
服務提供者和服務消費者只需要調整 address
屬性配置即可。
單機配置:
<!-- 使用 Nacos 注冊中心,單機版 -->
<dubbo:registry address="nacos://127.0.0.1:8848"/> <!-- 或 --> <dubbo:registry protocol="nacos" address="127.0.0.1:2181"/>
或:
dubbo.register.address=nacos://192.168.10.101:8848
或:
dubbo.register.protocol=nacos
dubbo.register.address=192.168.10.101:8848
集群配置:
<!-- 使用 Nacos 注冊中心,集群版 -->
<dubbo:registry address="nacos://192.168.10.101:2181?backup=192.168.10.102:2181,192.168.10.103:2181"/> <!-- 或 --> <dubbo:registry protocol="nacos" address="192.168.10.101:2181,192.168.10.102:2181,192.168.10.103:2181"/>
或:
dubbo.register.address=nacos://192.168.10.101:8848
或:
dubbo.register.protocol=nacos
dubbo.register.address=192.168.10.101:8848,192.168.10.102:8848,192.168.10.103:8848
隨后,重啟您的 Dubbo 應用,Dubbo 的服務提供和消費信息在 Nacos 控制台中即可顯示。
Spring Cloud Alibaba Nacos 整合 Dubbo
之前的文章中,無論我們學習 Eureka、Consul 還是 Nacos,負責服務間通信的功能都是由 Ribbon 來完成的,接下來我們使用 Dubbo 來替換 Ribbon。
聚合工程
dubbo-demo
聚合工程。SpringBoot 2.3.0.RELEASE
、Spring Cloud Hoxton.SR5
。
項目結構如下圖,簡單介紹一下:
-
service-api
:服務接口 -
product-service
:商品服務,服務提供者,提供了/product/list
接口 -
order-service
:訂單服務,服務消費者,遠程調用商品服務

依賴關系
dubbo-demo 的 pom.xml。
<?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> <!-- 項目坐標地址 --> <groupId>com.example</groupId> <!-- 項目模塊名稱 --> <artifactId>dubbo-demo</artifactId> <packaging>pom</packaging> <!-- 項目版本名稱 快照版本SNAPSHOT、正式版本RELEASE --> <version>1.0-SNAPSHOT</version> <modules> <module>service-api</module> <module>product-service</module> <module>order-service</module> </modules> <!-- 繼承 spring-boot-starter-parent 依賴 --> <!-- 使用繼承方式,實現復用,符合繼承的都可以被使用 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> </parent> <!-- 集中定義依賴組件版本號,但不引入, 在子工程中用到聲明的依賴時,可以不加依賴的版本號, 這樣可以統一管理工程中用到的依賴版本 --> <properties> <!-- Spring Cloud Hoxton.SR5 依賴 --> <spring-cloud.version>Hoxton.SR5</spring-cloud.version> <!-- spring cloud alibaba 依賴 --> <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version> </properties> <!-- 項目依賴管理 父項目只是聲明依賴,子項目需要寫明需要的依賴(可以省略版本信息) --> <dependencyManagement> <dependencies> <!-- spring cloud 依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring cloud alibaba 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
service-api 的 pom.xml
<?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"> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>service-api</artifactId> <dependencies> <!-- lombok 依賴 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
product-service 需要依賴 Nacos 和 Dubbo 的依賴,還有 service-api 的依賴,完整依賴如下:
<?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"> <!-- 繼承父依賴 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>product-service</artifactId> <!-- 項目依賴 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依賴 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依賴 --> <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> </project>
order-service 需要依賴 Nacos 和 Dubbo 的依賴,還有 service-api 的依賴,完整依賴如下:
<?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"> <!-- 繼承父依賴 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <!-- 項目依賴 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依賴 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依賴 --> <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> </project>
定義服務接口
我們在 service-api
模塊中定義實體類和服務接口信息。
實體類
Product.java
package com.example.product.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; }
Order.java
package com.example.product.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor public class Order implements Serializable { private Integer id; private String orderNo; private String orderAddress; private Double totalPrice; private List<Product> productList; }
服務接口
package com.example.product.service;
import com.example.product.pojo.Product; import java.util.List; /** * 商品服務 */ public interface ProductService { /** * 查詢商品列表 * * @return */ List<Product> selectProductList(); }
定義服務提供者
配置文件
配置文件需要配置 Nacos 注冊中心和 Dubbo 相關信息,核心配置如下:
server:
port: 7070 # 端口 spring: application: name: product-service # 應用名稱 # 配置 Nacos 注冊中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 進行服務注冊和發現,設置為 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服務器地址,單機版 # Dubbo dubbo: # 提供方應用信息,用於計算依賴關系 application: name: product-service # 使用 nacos 注冊中心暴露服務地址 registry: protocol: nacos address: spring-cloud://localhost # 用 dubbo 協議在 20880 端口暴露服務 protocol: name: dubbo port: 20880 # 掃描需要暴露的服務,可以被 @EnableDubbo 注解替代 #scan: # base-packages: com.example.service
服務提供者
product-service 的 ProductServiceImpl.java
package com.example.service.impl;
import com.example.product.pojo.Product; import com.example.product.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Service; import java.util.Arrays; import java.util.List; /** * 商品服務 * timeout 調用該服務的超時時間 * version 為版本號 * group 為分組 * interface、group、version 三者確定一個服務 */ @Slf4j @Service(timeout = 5000, version = "1.0", group = "product-service") public class ProductServiceImpl implements ProductService { /** * 查詢商品列表 * * @return */ @Override public List<Product> selectProductList() { log.info("商品服務查詢商品信息..."); return Arrays.asList( new Product(1, "華為手機", 1, 5800D), new Product(2, "聯想筆記本", 1, 6888D), new Product(3, "小米平板", 5, 2020D) ); } }
值得注意的是 @Service
注解不是 Spring 的注解而是 Dubbo
的注釋:

啟動類
啟動類通過 @EnableDubbo
注解掃描需要暴露的服務,如果配置文件中配置了該選項,那么這里可以省略。
package com.example;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 掃描需要暴露的服務 @EnableDubbo(scanBasePackages = "com.example.service") // 開啟 @EnableDiscoveryClient 注解,當前版本默認會開啟該注解 //@EnableDiscoveryClient @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } }
定義服務消費者
配置文件
配置文件需要配置 Nacos 注冊中心和 Dubbo 相關信息,核心配置如下:
server:
port: 9090 # 端口 spring: application: name: order-service # 應用名稱 # 配置 Nacos 注冊中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 進行服務注冊和發現,設置為 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服務器地址,單機版 # Dubbo dubbo: # 消費方應用名,用於計算依賴關系,不是匹配條件,不要與提供方一樣 application: name: order-service # 發現 nacos 注冊中心暴露的服務 registry: protocol: nacos address: spring-cloud://localhost cloud: subscribed-services: product-service # 訂閱服務,遠程調用的服務名稱
服務消費者
order-service 的 OrderServiceImpl.java
package com.example.service.impl;
import com.example.product.pojo.Order; import com.example.product.service.ProductService; import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Reference; import org.springframework.stereotype.Service; @Slf4j @Service public class OrderServiceImpl implements OrderService { // dubbo 提供了 @Reference 注解,可替換 @Autowired 注解,用於引入遠程服務 // 如果注冊服務時設置了版本及分組信息,調用遠程服務時也要設置對應的版本及分組信息 @Reference(timeout = 5000, version = "1.0", group = "product-service") private ProductService productService; /** * 根據主鍵查詢訂單 * * @param id * @return */ @Override public Order selectOrderById(Integer id) { log.info("訂單服務查詢訂單信息..."); return new Order(id, "order-001", "中國", 22788D, productService.selectProductList()); } }
啟動類
package com.example;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 開啟 @EnableDiscoveryClient 注解,當前版本默認會開啟該注解 //@EnableDiscoveryClient @SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
測試
先啟動 Nacos 服務器,然后啟動服務提供者 product-service,訪問:http://localhost:8848/nacos/ 控制台顯示如下:


然后啟動服務消費者,控制台顯示如下:

訂單服務調用遠程商品服務,結果如下:

Dubbo 負載均衡
在集群負載均衡時,Dubbo 提供了多種均衡策略,缺省為 random
隨機調用,也可以自行擴展負載均衡策略。
負載均衡策略
Random LoadBalance
-
「隨機」,按權重設置隨機概率。 -
在一個截面上碰撞的概率高,但調用量越大分布越均勻,而且按概率使用權重后也比較均勻,有利於動態調整提供者權重。

RoundRobin LoadBalance
-
「輪詢」,按公約后的權重設置輪詢比率。 -
存在慢的提供者累積請求的問題,比如:第二台機器很慢,但沒掛,當請求調到第二台時就卡在那,久而久之,所有請求都卡在調到第二台上。
LeastActive LoadBalance
-
「最少活躍調用數」,ping 值(延遲低)的調用,相同延遲的情況下隨機。 -
使慢的提供者收到更少請求,因為越慢的提供者的調用前后計數差會越大。

ConsistentHash LoadBalance
-
「一致性 Hash」,相同參數的請求總是發到同一提供者。 -
當某一台提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。 -
算法參見:http://en.wikipedia.org/wiki/Consistent_hashing -
缺省只對第一個參數 Hash,如果要修改,請配置 <dubbo:parameter key="hash.arguments" value="0,1" />
-
缺省用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key="hash.nodes" value="320" />
配置
一般在項目中不會在代碼層面指定權重,而是通過監控中心(dubbo-admin)對服務動態的指定權重,官方文檔:http://dubbo.apache.org/zh-cn/docs/admin/introduction.html
xml
服務端服務級別
<dubbo:service interface="..." loadbalance="roundrobin" weight="100" />
客戶端服務級別
<dubbo:reference interface="..." loadbalance="roundrobin" />
服務端方法級別
<dubbo:service interface="..." weight="100">
<dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:service>
客戶端方法級別
<dubbo:reference interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:reference>
yaml
dubbo:
provider: loadbalance: roundrobin weight: 100 consumer: loadbalance: roundrobin
注解
@Service(loadbalance = "roundrobin", weight = 100)
@Reference(loadbalance = "roundrobin")


至此 Dubbo RPC 通信所有的知識點就講解結束了。

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議
。
大家可以通過 分類
查看更多關於 Spring Cloud
的文章。
🤗 您的點贊
和轉發
是對我最大的支持。
📢 掃碼關注 哈嘍沃德先生
「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕松噢 ~

