Dubbo 2.7.7 起步入門學(xué)習(xí)筆記
本文檔基于 Dubbo 中文官方文檔編寫,詳情請(qǐng)參見 Dubbo 中文官方文檔
Dubbo 產(chǎn)生的背景
隨著互聯(lián)網(wǎng)的發(fā)展,網(wǎng)站應(yīng)用的規(guī)模不斷擴(kuò)大,常規(guī)的垂直應(yīng)用架構(gòu)已無法應(yīng)對(duì),分布式服務(wù)架構(gòu)以及流動(dòng)計(jì)算架構(gòu)勢(shì)在必行,亟需一個(gè)治理系統(tǒng)確保架構(gòu)有條不紊的演進(jìn)。

單一應(yīng)用架構(gòu)
當(dāng)網(wǎng)站流量很小時(shí),只需一個(gè)應(yīng)用,將所有功能都部署在一起,以減少部署節(jié)點(diǎn)和成本。此時(shí),用于簡化增刪改查工作量的數(shù)據(jù)訪問框架 (ORM) 是關(guān)鍵。
垂直應(yīng)用架構(gòu)
當(dāng)訪問量逐漸增大,單一應(yīng)用增加機(jī)器帶來的加速度越來越小,提升效率的方法之一是將應(yīng)用拆成互不相干的幾個(gè)應(yīng)用,以提升效率。此時(shí),用于加速前端頁面開發(fā)的 Web 框架 (MVC) 是關(guān)鍵。
分布式服務(wù)架構(gòu)
當(dāng)垂直應(yīng)用越來越多,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來,作為獨(dú)立的服務(wù),逐漸形成穩(wěn)定的服務(wù)中心,使前端應(yīng)用能更快速的響應(yīng)多變的市場需求。此時(shí),用于提高業(yè)務(wù)復(fù)用及整合的分布式服務(wù)框架 (RPC) 是關(guān)鍵。
流動(dòng)計(jì)算架構(gòu)
當(dāng)服務(wù)越來越多,容量的評(píng)估,小服務(wù)資源的浪費(fèi)等問題逐漸顯現(xiàn),此時(shí)需增加一個(gè)調(diào)度中心基于訪問壓力實(shí)時(shí)管理集群容量,提高集群利用率。此時(shí),用于提高機(jī)器利用率的資源調(diào)度和治理中心 (SOA) 是關(guān)鍵。
Dubbo 的架構(gòu)

各節(jié)點(diǎn)的說明
| 節(jié)點(diǎn) | 角色說明 |
|---|---|
Provider |
暴露服務(wù)的服務(wù)提供方 |
Consumer |
調(diào)用遠(yuǎn)程服務(wù)的服務(wù)消費(fèi)方 |
Registry |
服務(wù)注冊(cè)與發(fā)現(xiàn)的注冊(cè)中心 |
Monitor |
統(tǒng)計(jì)服務(wù)的調(diào)用次數(shù)和調(diào)用時(shí)間的監(jiān)控中心 |
Container |
服務(wù)運(yùn)行容器 |
調(diào)用關(guān)系說明
服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長連接推送變更數(shù)據(jù)給消費(fèi)者。
服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。
Dubbo 架構(gòu)具有以下幾個(gè)特點(diǎn)
Dubbo架構(gòu)所擁有的特點(diǎn)分別是連通性、健壯性、伸縮性、以及向未來架構(gòu)的升級(jí)性。
連通性
- 注冊(cè)中心負(fù)責(zé)服務(wù)地址的注冊(cè)與查找,相當(dāng)于目錄服務(wù),服務(wù)提供者和消費(fèi)者只在啟動(dòng)時(shí)與注冊(cè)中心交互,注冊(cè)中心不轉(zhuǎn)發(fā)請(qǐng)求,壓力較小
- 監(jiān)控中心負(fù)責(zé)統(tǒng)計(jì)各服務(wù)調(diào)用次數(shù),調(diào)用時(shí)間等,統(tǒng)計(jì)先在內(nèi)存匯總后每分鐘一次發(fā)送到監(jiān)控中心服務(wù)器,并以報(bào)表展示
- 服務(wù)提供者向注冊(cè)中心注冊(cè)其提供的服務(wù),并匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間不包含網(wǎng)絡(luò)開銷
- 服務(wù)消費(fèi)者向注冊(cè)中心獲取服務(wù)提供者地址列表,并根據(jù)負(fù)載算法直接調(diào)用提供者,同時(shí)匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間包含網(wǎng)絡(luò)開銷
- 注冊(cè)中心,服務(wù)提供者,服務(wù)消費(fèi)者三者之間均為長連接,監(jiān)控中心除外
- 注冊(cè)中心通過長連接感知服務(wù)提供者的存在,服務(wù)提供者宕機(jī),注冊(cè)中心將立即推送事件通知消費(fèi)者
- 注冊(cè)中心和監(jiān)控中心全部宕機(jī),不影響已運(yùn)行的提供者和消費(fèi)者,消費(fèi)者在本地緩存了提供者列表
- 注冊(cè)中心和監(jiān)控中心都是可選的,服務(wù)消費(fèi)者可以直連服務(wù)提供者
健壯性
- 監(jiān)控中心宕掉不影響使用,只是丟失部分采樣數(shù)據(jù)
- 數(shù)據(jù)庫宕掉后,注冊(cè)中心仍能通過緩存提供服務(wù)列表查詢,但不能注冊(cè)新服務(wù)
- 注冊(cè)中心對(duì)等集群,任意一臺(tái)宕掉后,將自動(dòng)切換到另一臺(tái)
- 注冊(cè)中心全部宕掉后,服務(wù)提供者和服務(wù)消費(fèi)者仍能通過本地緩存通訊
- 服務(wù)提供者無狀態(tài),任意一臺(tái)宕掉后,不影響使用
- 服務(wù)提供者全部宕掉后,服務(wù)消費(fèi)者應(yīng)用將無法使用,并無限次重連等待服務(wù)提供者恢復(fù)
伸縮性
- 注冊(cè)中心為對(duì)等集群,可動(dòng)態(tài)增加機(jī)器部署實(shí)例,所有客戶端將自動(dòng)發(fā)現(xiàn)新的注冊(cè)中心
- 服務(wù)提供者無狀態(tài),可動(dòng)態(tài)增加機(jī)器部署實(shí)例,注冊(cè)中心將推送新的服務(wù)提供者信息給消費(fèi)者
Dubbo 前期準(zhǔn)備
Zookeeper 安裝
-
zookeeper的windows安裝 -
配置
zookeeper配置文件- 打開
conf目錄下將zoo_sample.cfg配置文件復(fù)制并重命名為zoo.cfg配置文件 - 修改配置文件
# AdminServer 占用了 8080 端口,將其改用為9999 admin.serverPort=9999 # 這里原來是 Linux 中的路徑顯示,改為 window 路徑并且需要手動(dòng)創(chuàng)建 tmp_data 文件夾 dataDir=../tmp_data - 打開
-
運(yùn)行
zookeeper服務(wù)器- 在
bin目錄下通過命令啟動(dòng)zookeeper服務(wù)
xxx\zookeeper\apache-zookeeper-3.6.2-bin\apache-zookeeper-3.6.2-bin\bin> zkServer.cmd - 在
-
運(yùn)行
zookeeper客戶端- 在
bin目錄下通過命令啟動(dòng)zookeeper客戶端
xxx\zookeeper\apache-zookeeper-3.6.2-bin\apache-zookeeper-3.6.2-bin\bin> zkCli.cmd- 啟動(dòng)后輸入命令顯示如下表示成功
image - 在
dubbo-admin 安裝
-
下載 dubbo-admin
-
通過
Git下載git clone https://github.com/apache/dubbo-admin.git
-
-
修改 dubbo-admin-server 配置文件
- 進(jìn)入 dubbo-admin 的 dubbo-admin-server 目錄中
cd dubbo-admin/dubbo-admin-server- 修改
dubbo-admin-server\src\main\resources\application.properties配置文件
# centers in dubbo2.7 admin.registry.address=zookeeper://127.0.0.1:2181 admin.config-center=zookeeper://127.0.0.1:2181 admin.metadata-report.address=zookeeper://127.0.0.1:2181 -
將 dubbo-admin-server 進(jìn)行打包
- 使用
maven進(jìn)行打包:mvn clean package
- 使用
-
啟動(dòng) dubbo-admin-server
-
進(jìn)入生成的
target目錄中,運(yùn)行啟動(dòng)后臺(tái)java -jar dubboxxx.jar
-
-
啟動(dòng) dubbo-admin-ui
由于 dubbo-admin 是一個(gè)前后端分離的項(xiàng)目,所以還需要啟動(dòng)前端項(xiàng)目
-
需要提前安裝 node.js 才可以使用 npm 命令來運(yùn)行程序
> npm install > npm run dev
-
在 http://localhost:8082 中便可查看運(yùn)行界面
- 默認(rèn)賬戶密碼均為:root
Dubbo 入門案例
使用 XML 啟動(dòng) Dubbo 案例
-
項(xiàng)目目錄結(jié)構(gòu)如下
image
-
Maven 核心配置文件如下
<properties> <!-- 定義 dubbo 的版本 --> <dubbo.version>2.7.8</dubbo.version> </properties> <dependencies> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> </dependency> <!-- 使用 zookeeper 作為注冊(cè)中心--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>${dubbo.version}</version> <type>pom</type> </dependency> </dependencies> -
在 dubbo-demo-xml-interface 中創(chuàng)建公共接口
package com.study; /** * 創(chuàng)建公共接口<p> * @author DeadBoty * @since 2020/10/23 16:22 */ public interface DemoService { String sayHello(String name); } -
在 dubbo-demo-xml-provider 中創(chuàng)建接口實(shí)現(xiàn)類
- 在 pom.xml 中添加 dubbo-demo-xml-interface 的依賴
<dependencies> <dependency> <groupId>com.study</groupId> <artifactId>dubbo-demo-xml-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>- 創(chuàng)建配置文件:
provider.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" 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"> <!-- 提供方應(yīng)用信息,用于計(jì)算依賴關(guān)系 --> <dubbo:application name="dubbo-demo-hello" /> <!-- 使用 zookeeper 廣播注冊(cè)中心暴露服務(wù)地址 --> <!-- <dubbo:registry address="zookeeper://127.0.0.1:2181" /> --> <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" /> <!-- 用 dubbo 協(xié)議在 20880 端口暴露服務(wù) --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 聲明需要暴露的服務(wù)接口 --> <dubbo:service interface="com.study.DemoService" ref="demoService" /> <!-- 和本地 bean 一樣實(shí)現(xiàn)服務(wù) --> <bean id="demoService" class="com.study.DemoServiceImpl" /> </beans>- 編寫接口實(shí)現(xiàn)類
package com.study; /** * 公共接口實(shí)現(xiàn)類<p> * @author DeadBoty * @since 2020/10/23 17:17 */ public class DemoServiceImpl implements DemoService { @Override public String sayHello(String name) { return "Hello, " + name; } }- 編寫啟動(dòng)方法
package com.study; /** * 服務(wù)提供方啟動(dòng)<p> * @author DeadBoty * @since 2020/10/23 17:21 */ public class Provider { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("provider.xml"); applicationContext.start(); // 輸入一個(gè)字符退出 System.in.read(); } }- 在 dubbo-admin 的可視化中可以看到服務(wù)提供方
image -
在 dubbo-demo-xml-consumer 中實(shí)現(xiàn)服務(wù)的調(diào)用
- 在 pom.xml 中添加 dubbo-demo-xml-interface 的依賴
<dependencies> <dependency> <groupId>com.study</groupId> <artifactId>dubbo-demo-xml-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>- 創(chuàng)建配置文件:
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://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 消費(fèi)方應(yīng)用名,用于計(jì)算依賴關(guān)系,不是匹配條件,不要與提供方一樣 --> <dubbo:application name="consumer-of-hello-app" /> <!-- 使用 zookeeper 廣播注冊(cè)中心暴露發(fā)現(xiàn)服務(wù)地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 生成遠(yuǎn)程服務(wù)代理,可以和本地 bean 一樣使用 demoService --> <dubbo:reference id="demoService" interface="com.study.DemoService" /> </beans>- 編寫服務(wù)消費(fèi)啟動(dòng)
package com.study; /** * 服務(wù)消費(fèi)方啟動(dòng)類<p> * @author DeadBoty * @since 2020/10/23 17:34 */ public class Consumer { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml"); DemoService demoService = applicationContext.getBean("demoService", DemoService.class); System.out.println(demoService.sayHello("法外狂徒張三")); } }- 服務(wù)消費(fèi)與提供方的關(guān)系

基于注解開發(fā)
Spring 的注解開發(fā)和 Spring Boot 相似,所以這里直接使用 Spring Boot 進(jìn)行注解的開發(fā)
-
項(xiàng)目目錄結(jié)構(gòu)如下
image -
Maven 中各部分的配置
- dubbo-demo-annotation 的 pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <!-- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.7</version> </dependency> <!-- dubbo 依賴 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.7</version> </dependency> <!-- 導(dǎo)入 curator 分布式協(xié)調(diào)服務(wù) --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.1</version> </dependency> <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>- dubbo-demo-provider 的 pom.xml
<parent> <artifactId>dubbo-demo-annotation</artifactId> <groupId>com.study</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <!-- 導(dǎo)入 Spring Web 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.study</groupId> <artifactId>dubbo-demo-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>- dubbo-demo-consumer 的 pom.xml
<parent> <artifactId>dubbo-demo-annotation</artifactId> <groupId>com.study</groupId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <!-- 導(dǎo)入 Spring Web 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.study</groupId> <artifactId>dubbo-demo-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> -
在 dubbo-demo-interface 創(chuàng)建公共接口
package com.study; /** * 創(chuàng)建公共接口<p> * @author DeadBoty * @since 2020/10/23 16:22 */ public interface DemoService { String sayHello(String name); } -
在 dubbo-demo-provider 中創(chuàng)建接口實(shí)現(xiàn)類
- dubbo 的配置文件:
application.yml
# 定義端口號(hào) server: port: 8181 # 定義 dubbo 相關(guān)配置 dubbo: application: name: annotation-demo-provider protocol: name: dubbo port: 20880 registry: protocol: zookeeper address: 127.0.0.1:2181- 接口實(shí)現(xiàn)類
package com.study.service; /** * 公共接口的具體實(shí)現(xiàn)<p> * @author DeadBoty * @since 2020/10/25 14:59 */ @Service // 需要提供的服務(wù) @DubboService public class DemoServiceImpl implements DemoService { @Override public String sayHello(String name) { return "你好~~~ " + name; } }- 啟動(dòng)類
package com.study; /** * Spring Boot 啟動(dòng)類<p> * @author DeadBoty * @since 2020/10/25 14:53 */ @SpringBootApplication // 啟動(dòng) Dubbo 的注解 @EnableDubbo public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ProviderApplication.class, args); } } - dubbo 的配置文件:
-
在 dubbo-demo-consumer 中實(shí)現(xiàn)服務(wù)的調(diào)用
- dubbo 的配置
server: port: 8182 dubbo: application: name: annotation-demo-consumer registry: protocol: zookeeper address: 127.0.0.1:2181- 遠(yuǎn)程調(diào)用服務(wù)
package com.study.controller; /** * 服務(wù)消費(fèi)調(diào)用<p> * @author DeadBoty * @since 2020/10/25 14:59 */ @RestController @RequestMapping("/demo") public class DemoController { // 使用 @DubboReference 來實(shí)現(xiàn)遠(yuǎn)程方法引用服務(wù) @DubboReference DemoService demoService; @GetMapping("/{name}") public String sayHello(@PathVariable String name) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); // 返回了 Json 數(shù)據(jù) return mapper.writeValueAsString(demoService.sayHello(name)); } }- 啟動(dòng)類
package com.study; /** * 服務(wù)消費(fèi)端啟動(dòng)類<p> * @author DeadBoty * @since 2020/10/25 14:42 */ @SpringBootApplication @EnableDubbo public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } } -
啟動(dòng)服務(wù)后調(diào)用方法 http://localhost:8182/demo/%E6%B3%95%E5%A4%96%E7%8B%82%E5%BE%92%E5%BC%A0%E4%B8%89
- 結(jié)果如下:
image




