一:什麼是Dubbo
Dubbo是一款高性能、輕量級的開源Java RPC框架,
它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。
即實現了多個獨立應用之間的解耦且可以遠程調用對方的服務
二、爲什麼需要 dubbo
很多時候,因爲項目需要用到分佈式架構,所以就引用了dubbo這項技術,但是至於爲什麼我們需要用到這個技術
可能自身並不是很瞭解,但是,其實瞭解技術的來由及背景知識,對於理解一項技術還是有幫助的,
在以前,我們只需要一個服務器,將程序全部打包好就可以,但是,隨着流量的增大,常規的垂直應用架構已無法應對,所以,架構就發生了演變。
所需演變的方面
1 單一應用架構
2 應用和數據庫單獨部署
3 應用和數據庫集羣部署
4 數據庫壓力變大,讀寫分離
5 使用緩存技術加快速度
6 數據庫分庫分表
7 應用分爲不同的類型拆分
發展到這個階段的時候,我們發現,應用與應用之間的關係已經十分的複雜了,就會出現以下幾個問題(以下摘錄於官網):
① 當服務越來越多時,服務 URL 配置管理變得非常困難,F5 硬件負載均衡器的單點壓力也越來越大。
② 當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪個應用要在哪個應用之前啓動,架構師都不能完整的描述應用的架構關係。
③ 接着,服務的調用量越來越大,服務的容量問題就暴露出來,這個服務需要多少機器支撐?什麼時候該加機器?
爲了解決這由於架構的演變所產生的問題幾個問題,於是,dubbo 產生了。當然,解決這個問題的技術不止 dubbo 。
三、關鍵點介紹:
1.註冊與發現
Dubbo使用zookeeper做服務的註冊中心,就是服務的提供者以臨時節點的形式將服務Server信息註冊保存到Zookeeper的dubbo目錄下
的provider的節點下,供消費者發現調用。
2.負載均衡
Dubbo支持負載均衡策略,就是同一個Dubbo服務被多臺服務器啓用後,會在Zookeeper提供者節點下顯示多個相同接口名稱節點。
消費者在調用Dubbo負載均衡服務時,採用權重的算法策略選擇具體某個服務器上的服務,權重策略以*2倍數設置。
3.容錯機制
Dubbo的提供者在Zookeeper上使用的是臨時節點,一旦提供者所在服務掛掉,該節點的客戶端連接將會關閉,故節點自動消失。所以消費者調用接口時將不會輪詢到已經掛掉的接口上(延遲例外)。
4.Dubbo協議
Dubbo常用協議有兩種:dubbo、hessian
dubbo:
Dubbo 缺省協議是dubbo協議,採用單一長連接和 NIO 異步通訊,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。
hessian:
Hessian底層採用Http通訊(同步),採用Servlet暴露服務。適用於傳入傳出參數數據包較大,消費者併發量少,提供者較多,可傳文件。
5.Dubbo容器
Dubbo在java jvm中有自己的容器,和Spring IOC的bean一樣,將服務對象保存到自己的容器中。
6.監控中心
監控中心主要是用來服務監控和服務治理。
服務治理包含:負載均衡策略、服務狀態、容錯、路由規則限定、服務降級等。具體可以下載Dubbo監控中心客戶端查看與設置。
dubbo監控中心下載和搭建啓動參考網址https://blog.csdn.net/a704397849/article/details/91904842
四、節點角色說明
節點 角色說明
Provider 暴露服務的服務提供方
Consumer 調用遠程服務的服務消費方
Registry 服務註冊與發現的註冊中心
Monitor 統計服務的調用次數和調用時間的監控中心
Container 服務運行容器
看了這幾個概念後似乎發現,其實 Dubbo 的架構也是很簡單的(其實現細節是複雜的),爲什麼這麼說呢,有沒有發現,
其實很像"生產者-消費者"模型。只是在這種模型上,加上了註冊中心和監控中心,用於管理提供方提供的url,以及監控和管理整個過程
那麼dubbo發佈-訂閱的過程是怎樣的呢?
1、啓動容器,加載,運行服務提供者。
2、服務提供者在啓動時,在註冊中心發佈註冊自己提供的服務。
3、服務消費者在啓動時,在註冊中心訂閱自己所需的服務
容器如何啓動呢?
即java中整合了dubbo,在spirngboot的啓動類上加一個啓動的註解,服務啓動即自動開啓容器
當然作爲一個類似於中間件的dubbo框架,肯定也有對它某些配置自定義的方式 如
1、註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
2、服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
3、服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
這些均可在java配置文件中進行配置,下面在詳細講述
五、zookeeper
欲實現dubbo架構先要搭建zookeeper集羣作爲服務註冊發現中心,安裝集羣步驟參考網址https://blog.csdn.net/weixin_43784880/article/details/104428651
此前就完成了dubbo-admin和zookepper集羣的搭建,啓動後進行下面步驟
六、SpringBoot整合Dubbo和Zookeeper
先說明後不亂:
這裏創建了一個主工程dubbo-hotels,其下包含了api、dubbo-provider、dubbo-customer
api: 主要存放公共實體類、需要遠程調用的服務接口、也可以放一些公用的工具類工程
dubbo-provider: 服務提供工程 將接口實現類的服務暴露出去
dubbo-customer: 服務調用工程 遠程從zookeeper調用提供者暴露的服務
切記:因爲服務接口只是寫在api工程中,所以dubbo-provider、dubbo-customer兩個工程都需要在pom文件中引入api的jar包,下面會一一闡述
父工程
1、先創建一個springboot主工程 dubbo-hotels
主工程添加依賴如下:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 添加springboot父級依賴-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--自定義該工程的jar包的座標-->
<groupId>com.hotels</groupId>
<artifactId>dubbo-hotels</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-hotels</name>
<modules>
<!-- 服務消費者工程 -->
<module>dubbbo-customer</module>
<module>hotel-customer</module>
<!-- 服務提供者工程-->
<module>hotel-provider</module>
<module>dubbo-provider</module>
<!-- 主要放實體、接口、也可以放一些公用的工具類工程-->
<module>api</module>
</modules>
<!-- dependency依賴 版本號 的變量,也可以不要直接將版本號寫在version中-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<dubbo-spring-boot>1.0.0</dubbo-spring-boot>
<dubbo.version>2.5.5</dubbo.version>
<zkclient.version>0.10</zkclient.version>
<lombok.version>1.16.18</lombok.version>
<spring-boot.version>1.5.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!--開啓web-->
<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>
<!-- 使用lombok實現JavaBean的get、set、toString、hashCode、equals等方法的自動生成 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Spring Boot Dubbo 依賴 -->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--zookeeper的客戶端依賴-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.11</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
到這裏父工程配置結束
服務接口工程 api
1、pom寫法
<?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 https://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.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hotels</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>api</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、服務接口類
package com.hotel1.demo.api;
public interface DubboUserServer {
String getUser(Integer id);
}
跟普通接口沒有兩樣,爲了簡單明瞭我這裏只有一個方法,如果用到實體類操作數據庫,可以創建實體類
無需其他過多配置,服務接口工程的配置結束
服務提供工程 dubbo-privoder
1、pom加入
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--子工程爲了繼承父工程的依賴,節省代碼,可以在parent標籤中加入父工程的jar包座標-->
<parent>
<groupId>com.hotels</groupId>
<artifactId>dubbo-hotels</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.hotels</groupId>
<artifactId>dubbo-privoder</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-privoder</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<!-- 爲了引入api服務接口來實現接口類,需要引入api工程的jar包 這樣可以引入api中的類-->
<dependency>
<groupId>com.hotels</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
父工程的依賴可以被子工程引入,即子工程無需再寫一遍依賴,只需要parent父級依賴指定成子工程即可
dubbo-provider引入dubbo-hotels的pom,如圖
A工程想要引入B工程的類,需要以依賴的形式引入B類的jar,如圖
無論是dependency引入還是parent父級引入,關鍵在於要一一對應號groupId、artifactId、version等座標和版本,否則出錯
2、接口實現類
package com.provider.demo.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.hotel1.demo.api.DubboUserServer; //此處的DubboUserServer正是引入了api工程的接口,dubbo-provider中並不需要寫此接口
import org.springframework.stereotype.Component;
//用到實體類對的話實體類要實現序列化接口
@Service(interfaceClass = DubboUserServer.class)//使用dubbo提供的service註解來暴露服務
@Component
public class DubboUserServerImpl implements DubboUserServer {
@Override
public String getUser(Integer id) {
String name = "";
if(1==id){
name = "董";
}else if(2==id){
name = "劉";
}else{
name = "楊";
}
return name;
}
}
3、啓動類
package com.provider.demo;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo//添加此註解開啓dubbo容器 必要
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4、properties.yml
server:
port: 8083 //tomcat端口
dubbo:
application:
name: server-privoder //應用程序名
registry:
address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183 //我這裏是zookeeper集羣的寫法
protocol:
name: dubbo
#修改默認端口要寫成字符串形式,如果寫20880數字將無法識別,暴露的服務使用的是默認端口20880
port: "20881"
scan: com.provider.demo.impl //用來掃描使用了dubbo暴露服務註解@Service的類所在的包
① 上面的文件其實就是類似 spring 的配置文件,而且,dubbo 底層就是 spring。
② 節點:dubbo:application
就是整個項目在分佈式架構中的唯一名稱,可以在 name 屬性中配置,另外還可以配置 owner 字段,表示屬於誰。
下面的參數是可以不配置的,這裏配置是因爲出現了端口的衝突,所以配置。
③ 節點:dubbo:monitor
監控中心配置, 用於配置連接監控中心相關信息,可以不配置,不是必須的參數。 本文就沒有配置
④ 節點:dubbo:registry
配置註冊中心的信息,比如,這裏我們可以配置 zookeeper 作爲我們的註冊中心。address 是註冊中心的地址,
也可以配置 N/A 表示由 dubbo 自動分配地址。或者說是一種直連的方式,不通過註冊中心。
⑤ 節點:dubbo:protocol
name:服務發佈的時候 dubbo 依賴什麼協議,可以配置 dubbo、webserovice、Thrift、Hessain、http等協議,用name來指定。
這裏僅解釋兩種協議:
dubbo:缺省協議是dubbo協議,採用單一長連接和 NIO 異步通訊,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。
hessian:Hessian底層採用Http通訊(同步),採用Servlet暴露服務。適用於傳入傳出參數數據包較大,消費者併發量少,提供者較多,可傳文件。
port:服務暴露的端口用port來指定,此處的端口數字必須用字符串表示,否則無法識別,會使用dubbo默認端口20880
⑥ 節點:dubbo:scan:
用來掃描使用了dubbo暴露服務註解@Service的類所在的包
服務消費工程 dubbo-customer
pom
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.hotels</groupId>
<artifactId>dubbo-hotels</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.hotels</groupId>
<artifactId>dubbo-customer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-customer</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.hotels</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5、測試web類
package com.customer.demo.web;
import com.hotel1.demo.api.DubboUserServer;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
//引入服務接口的註解 關鍵地方
@Reference
DubboUserServer dubboUserServer;
@RequestMapping(value = "/show", method = RequestMethod.GET)
public String shows() {
return dubboUserServer.getUser(2);
}
}
6、啓動類同理加上@EnableDubbo
7、properties.yml
server:
port: 8084
dubbo:
application:
name: server-customer
registry:
address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183
protocol:
name: dubbo
#修改默認端口要寫成字符串形式
port: "20880"
scan: com.customer.demo.web //掃描註解@Reference調用服務的類所在的包
啓動dubbo-customer,在瀏覽器地址欄輸入http://127.0.0.1:8084/test/show 即可測試