Apache Dubbo |ˈdʌbəʊ| 是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。致力於提升性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。html
節點 | 角色說明 |
---|---|
Provider |
暴露服務的服務提供方 |
Consumer |
調用遠程服務的服務消費方 |
Registry |
服務註冊與發現的註冊中心 |
Monitor |
統計服務的調用次數和調用時間的監控中心 |
Container |
服務運行容器 |
功能特色:java
面向接口代理的高性能RPC調用:web
提供高性能的基於代理的遠程調用能力,服務以接口爲粒度,爲開發者屏蔽遠程調用底層細節。算法
智能負載均衡:spring
內置多種負載均衡策略,智能感知下游節點健康情況,顯著減小調用延遲,提升系統吞吐量。apache
服務自動註冊與發現:api
支持多種註冊中心服務,服務實例上下線實時感知。架構
高度可擴展能力:app
遵循微內核+插件的設計原則,全部核心能力如Protocol、Transport、Serialization被設計爲擴展點,平等對待內置實現和第三方實現。負載均衡
運行期流量調度:
內置條件、腳本等路由策略,經過配置不一樣的路由規則,輕鬆實現灰度發佈,同機房優先等功能。
可視化的服務治理與運維:
提供豐富服務治理、運維工具:隨時查詢服務元數據、服務健康狀態及調用統計,實時下發路由策略、調整配置參數。
在Spring Cloud構建的微服務系統中,大多數的開發者使用都是官方提供的Feign組件來進行內部服務通訊,這種聲明式的HTTP客戶端使用起來很是的簡潔、方便、優雅,可是有一點,在使用Feign消費服務的時候,相比較Dubbo這種RPC框架而言,性能堪憂。
雖然說在微服務架構中,會講按照業務劃分的微服務獨立部署,而且運行在各自的進程中。微服務之間的通訊更加傾向於使用HTTP這種簡答的通訊機制,大多數狀況都會使用REST API。這種通訊方式很是的簡潔高效,而且和開發平臺、語言無關,可是一般狀況下,HTTP並不會開啓KeepAlive功能,即當前鏈接爲短鏈接,短鏈接的缺點是每次請求都須要創建TCP鏈接,這使得其效率變的至關低下。
對外部提供REST API服務是一件很是好的事情,可是若是內部調用也是使用HTTP調用方式,就會顯得顯得性能低下,Spring Cloud默認使用的Feign組件進行內部服務調用就是使用的HTTP協議進行調用,這時,咱們若是內部服務使用RPC調用,對外使用REST API,將會是一個很是不錯的選擇,恰巧,Dubbo Spring Cloud給了咱們這種選擇的實現方式。
建立ApacheDubbo總工程, 在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.gofy</groupId> <artifactId>ApacheDubbo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> </parent> <modules> <module>dubbo-provider</module> <module>dubbo-consumer</module> </modules> <properties> <!-- Environment Settings --> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-cloud.version>Greenwich.SR3</spring-cloud.version> <spring-cloud-alibaba.version>0.2.1.RELEASE</spring-cloud-alibaba.version> <dubbo.version>2.7.6</dubbo.version> <dubbo-spring.version>2.7.6</dubbo-spring.version> <dubbo-actuator.version>2.7.6</dubbo-actuator.version> <dubbo-kryo.version>2.7.6</dubbo-kryo.version> <dubbo-nacos.version>2.7.6</dubbo-nacos.version> <dubbo-nacos-config.version>2.1.0.RELEASE</dubbo-nacos-config.version> <spring-context-support.version>1.0.6</spring-context-support.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Apache Dubbo --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-actuator</artifactId> <version>${dubbo-actuator.version}</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>${dubbo-spring.version}</version> </dependency> <!-- 使用kryo序列化/反序列化工具, 提升項目性能 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-serialization-kryo</artifactId> <version>${dubbo-kryo.version}</version> </dependency> <!-- Spring Cloud Alibaba --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>${dubbo-nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${dubbo-nacos-config.version}</version> </dependency> <dependency> <groupId>com.alibaba.spring</groupId> <artifactId>spring-context-support</artifactId> <version>${spring-context-support.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <!-- Compiler 插件, 設定 JDK 版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> <!-- 資源文件配置 --> <resources> <resource> <directory>src/main/java</directory> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build> </project>
在Dubbo RPC框架中, 服務提供者的接口類和實現類應該分開爲倆個模塊, 因此咱們應該在服務提供者下建立兩個子模塊, 分別爲 接口模塊dubbo-provider-api 和 實現模塊dubbo-provider-service
在總工程 ApacheDubbo下建立dubbo-provider模塊, 添加服務提供者的統一依賴
<?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> <artifactId>ApacheDubbo</artifactId> <groupId>com.gofy</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.gofy</groupId> <artifactId>dubbo-provider</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>dubbo-provider-api</module> <module>dubbo-provider-service</module> </modules> </project>
在dubbo-provider下建立dubbo-provider-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"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>dubbo-provider</artifactId> <groupId>com.gofy</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.gofy</groupId> <artifactId>dubbo-provider-api</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> </project>
建立接口類 EchoService
package com.gofy.dubbo.api; public interface EchoService { String echo(String s); }
在dubbo-provider下建立dubbo-provider-service子模塊, 並添加依賴
導入接口模塊失敗緣由: 通常是總工程的統一依賴出了問題, 能夠查看本地maven倉庫的中總工程導入的依賴的包有沒有缺失文件. 我以前失敗緣由就是 spring-cloud-dependencies 包出了問題, Greenwich.SR5版本下載一直缺失文件, 改成Greenwich.SR3就行了.
<?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> <artifactId>dubbo-provider</artifactId> <groupId>com.gofy</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.gofy</groupId> <artifactId>dubbo-provider-service</artifactId> <packaging>jar</packaging> <dependencies> <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> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-serialization-kryo</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </dependency> <dependency> <groupId>com.alibaba.spring</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- 導入接口模塊 --> <dependency> <groupId>com.gofy</groupId> <artifactId>dubbo-provider-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.gofy.dubbo.ProviderApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>
在
注:若是要在 SpringClou Alibaba+Dubbo 中使用nacos動態配置,操做與以前naocs動態配置的操做同樣
spring:
application:
name: dubbo-provider
main:
allow-bean-definition-overriding: true # 解決bean重複定義,設置爲true時,後定義的bean會覆蓋以前定義的相同名稱的bean
dubbo:
scan:
base-packages: com.gofy.dubbo.service # 實現類所在的包
protocol:
name: dubbo
port: -1 # 端口爲-1時,便是讓dubbo自動分配端口
serialization: kryo # 使用kryo序列化/反序列化工具
registry:
address: nacos://192.168.11.132:8848 #註冊中心地址,格式爲 註冊中心組件名://註冊中心訪問地址
package com.gofy.dubbo.service; import com.gofy.dubbo.api.EchoService; import org.apache.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Value; @Service(version = "1.0.0") //服務版本號 public class EchoServiceImpl implements EchoService { @Override public String echo(String s) { return "Hello Dubbo "+s; } }
建立啓動類 ProviderApplication
@SpringBootApplication public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ProviderApplication.class, args); } }
在總工程 ApacheDubbo下建立服務消費者 dubbo-consumer, 並添加依賴
<?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> <artifactId>ApacheDubbo</artifactId> <groupId>com.gofy</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.gofy</groupId> <artifactId>dubbo-consumer</artifactId> <packaging>jar</packaging> <dependencies> <!-- SpringBoot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Dubbo --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-serialization-kryo</artifactId> </dependency> <!-- Spring Cloud Alibaba --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </dependency> <dependency> <groupId>com.alibaba.spring</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- 導入接口模塊 --> <dependency> <groupId>com.gofy</groupId> <artifactId>dubbo-provider-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.gofy.dubbo.ConsumerApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>
在dubbo-consumer的application.yml裏添加配置
server:
port: 8080
spring:
application:
name: dubbo-consumer
main:
allow-bean-definition-overriding: true
dubbo:
scan:
base-packages: com.gofy.dubbo.controller #controller類所在包
protocol:
name: dubbo
port: -1
serialization: kryo
registry:
address: nacos://192.168.11.132:8848
endpoints:
dubbo:
enabled: true #容許暴露dubbo分配的端點
management:
health: #健康檢查
dubbo:
status:
defaults: memory
extras: threadpool
endpoints: #暴露全部web端點
web:
exposure:
include: "*"
建立controller類 EchoController
package com.gofy.dubbo.controller; import com.gofy.dubbo.api.EchoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class EchoController { @Reference(version = "1.0.0") //經過服務的版本號注入 EchoService echoService; @GetMapping("/echo/{s}") public String echo(@PathVariable("s")String s){ return echoService.echo(s); } }
建立啓動類 ConsumerApplication
@SpringBootApplication public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } }
訪問nacos註冊中心,查看已註冊服務
訪問 localhost:8080/echo/hi , 成功獲取到服務提供者返回的信息
當咱們對內使用Dubbo的RPC通訊,再也不使用RestTemplate或feign的 HTTP通訊時,咱們要怎麼使用負載均衡呢?
在 Dubbo 中,也有負載均衡的概念和相應的實現。Dubbo 須要對服務消費者的調用請求進行分配,避免少數服務提供者負載過大。服務提供者負載過大,會致使部分請求超時。所以將負載均衡到每一個服務提供者上,是很是必要的。Dubbo 提供了4種負載均衡實現,分別是基於權重隨機算法的 RandomLoadBalance、基於最少活躍調用數算法的 LeastActiveLoadBalance、基於 hash 一致性的 ConsistentHashLoadBalance,以及基於加權輪詢算法的 RoundRobinLoadBalance。
Dubbo負載均衡的源碼在 org.apache.dubbo:dubbo下的org.apache.dubbo.rpc.cluster.loadbalance
經過源碼能夠發現4個負載均衡策略的實現類都繼承了AbstractLoadBalance抽象類,而AbstractLoadBalance實現了LoadBalance接口。
再來看看LoadBalance接口,能夠知道duboo是經過 loadbalance屬性來適配負載均衡接口的實現類,且默認值爲 random權重隨機。
@SPI("random") public interface LoadBalance { @Adaptive({"loadbalance"}) <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException; }
因此,咱們只要在@Reference註解裏添加 loadbalance屬性,就能夠選擇dubbo的負載均衡策略了
loadbalance屬性值爲負載均衡實現類的 NAME屬性,分別是:
random 、roundrobin 、leastactive 、consistenthash
@Reference(version = "1.0.0", loadbalance = "roundrobin")
EchoService echoService;
負載均衡策略實現類的詳細源碼分析,dubbo官方文檔裏講解得很是好,就很少轉述了
翻譯 朗讀 複製 正在查詢,請稍候…… 重試 朗讀 複製 複製 朗讀 複製 via 谷歌翻譯(國內)譯
翻譯 朗讀 複製 正在查詢,請稍候…… 重試 朗讀 複製 複製 朗讀 複製 via 谷歌翻譯(國內) 譯