Spring Boot 中使用 Dubbo 詳解
一開始只是想實(shí)現(xiàn)一下Dubbo的功能赏半,也滿滿的實(shí)現(xiàn)了Dubbo的demo例子诗良,但是出于求知欲又引出了一堆問題!一下是主要的幾個(gè)
- 如何使用IDEA構(gòu)建一個(gè)多模塊的項(xiàng)目
- Java項(xiàng)目中如何指定配置路徑
- SpringBoot 多模塊項(xiàng)目(module)Service自動(dòng)注入(
@Autowired
)是怎么實(shí)現(xiàn)的。
話不多說,直接上項(xiàng)目歼捐! 這是我的Dubbo的實(shí)戰(zhàn)項(xiàng)目
Spring Boot 注解下使用Dubbo(使用IDEA構(gòu)建一個(gè)多模塊的項(xiàng)目)
創(chuàng)建父類工程
首先使用 Spring Initializr 來快速創(chuàng)建好一個(gè)Maven工程。然后刪除無關(guān)的文件晨汹,只需保留pom.xml 文件豹储。
對(duì)的!你沒看錯(cuò)淘这,就只需要一個(gè)pom.xml
文件剥扣。
在 pom.xml 里面聲明該父工程包含的子模塊。(其它信息就不逐一講述了铝穷,諸如繼承SpringBoot官方父工程以及統(tǒng)一依賴管理 請(qǐng)查看下面的注釋說明)
<?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>1.0.0</modelVersion>
<name>test-dubbo-boot</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<!-- 項(xiàng)目說明:這里作為聚合工程的父工程 -->
<groupId>com.nezha</groupId>
<artifactId>test-dubbo-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 繼承說明:這里繼承SpringBoot提供的父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 模塊說明:這里聲明多個(gè)子模塊 -->
<modules>
<module>test-dubbo-boot-api</module>
<module>test-dubbo-boot-provider</module>
<module>test-dubbo-boot-consumer</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!-- 父工程導(dǎo)入公有的依賴包 -->
<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>
<!--dubbo-springBoot依賴-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
創(chuàng)建子類工程
注:這里是使用IDEA來創(chuàng)建子模塊钠怯,使用Eclipse的小伙伴可通過
Spring Initializr
構(gòu)建,然后復(fù)制去進(jìn)去父工程根目錄即可曙聂。
這里我主要就是按照分層思想創(chuàng)建了三個(gè)模塊:test-dubbo-boot-api
,test-dubbo-boot-provider
和test-dubbo-boot-consumer
,如下圖所示
test-dubbo-boot-api
api
中主要定義了服務(wù)調(diào)用的接口晦炊,這里的API是會(huì)對(duì)外暴露出來的。
test-dubbo-boot-provider
provider
是服務(wù)的提供者宁脊,這里實(shí)現(xiàn)了api
的接口断国,它會(huì)注冊(cè)為服務(wù)。
test-dubbo-boot-consumer
consumer
是服務(wù)的調(diào)用者榆苞。
創(chuàng)建的子項(xiàng)目需要注意的是:一定要繼承本項(xiàng)目的父工程
例如test-dubbo-boot-consumer
的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.nezha</groupId>
<artifactId>test-dubbo-boot-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test-dubbo-boot-provider</name>
<description>Demo project for Spring Boot</description>
<!-- 繼承本項(xiàng)目的父工程 -->
<parent>
<groupId>com.nezha</groupId>
<artifactId>test-dubbo-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<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>
<!-- 由于依賴api接口稳衬,引入接口包 -->
<dependency>
<groupId>com.nezha</groupId>
<artifactId>test-dubbo-boot-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- spring boot項(xiàng)目依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring boot的監(jiān)控模塊,非常牛逼 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>
這里在
provider
和consumer
的dependency
中一定要記住加上test-dubbo-boot-api
的依賴语稠,因?yàn)榉?wù)提供者和消費(fèi)者都依賴于接口實(shí)現(xiàn)的宋彼。在現(xiàn)實(shí)的項(xiàng)目中這個(gè)api
的模塊就可以單獨(dú)的打成JAR包給別人使用了。
Spring Boot 的 Actuator 提供了很多生產(chǎn)級(jí)的特性仙畦,比如監(jiān)控和度量Spring Boot 應(yīng)用程序输涕。Actuator 的這些特性可以通過眾多 REST 接口、遠(yuǎn)程 shell 和 JMX 獲得慨畸。
具體可以參考:
Spring Boot Actuator 使用: http://www.reibang.com/p/af9738634a21
Spring Boot Actuator:健康檢查莱坎、審計(jì)、統(tǒng)計(jì)和監(jiān)控: http://www.reibang.com/p/d5943e303a1f
如果需要監(jiān)控dubbo的服務(wù)可以引入dubbo的Actuator依賴
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-actuator</artifactId>
<version>0.2.0</version>
</dependency>
編寫子模塊代碼
1.test-dubbo-boot-api
這個(gè)模塊中其實(shí)就只有一個(gè)接口類
package com.nezha.test.dubbo;
public interface DemoService {
String sayHello(String name);
}
2.test-dubbo-boot-provider
provider
主要有三個(gè)文件:接口實(shí)現(xiàn)類寸士、配置文件和啟動(dòng)類
1.接口實(shí)現(xiàn)類:DemoServiceImpl.java
package com.nezha.test.dubbo.provider;
import com.alibaba.dubbo.config.annotation.Service;
import com.nezha.test.dubbo.DemoService;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
try {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + InetAddress.getLocalHost());
return "Hello " + name + ", response from provider: " + InetAddress.getLocalHost();
}catch (Exception e){
return "net error";
}
}
}
注意這里的
Service
是alibaba
包下的檐什。
2.配置文件:application.properties
# Spring boot application
spring.application.name = dubbo-provider-demo
dubbo.application.name = dubbo-provider-demo
#注冊(cè)中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#協(xié)議名稱
dubbo.protocol.name=dubbo
#協(xié)議端口
dubbo.protocol.port=20880
# DemoService service version
demo.service.version = 1.0.0
# Base packages to scan Dubbo Components (e.g @Service , @Reference)
dubbo.scan.basePackages = com.nezha.test.dubbo.provider
!H蹩ā乃正!重要!I舨瓮具!這里有一個(gè)非常坑的地方是0.2版本的
dubbo-spring-boot-starter
中配置 dubbo的時(shí)候,ide自動(dòng)生成的掃描包路徑為:dubbo.scan.base-packages
,實(shí)際上通過properties注入的名字應(yīng)該為dubbo.scan.basePackages名党,導(dǎo)致無法掃描到basePackages叹阔,故而沒有暴露出服務(wù)。將base-packages 修改為 basePackages后 發(fā)現(xiàn)成功暴露出服務(wù)传睹。
3.啟動(dòng)類:TestDubboBootProviderApplication
package com.nezha.test.dubbo.provider;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class TestDubboBootProviderApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(TestDubboBootProviderApplication.class)
.web(WebApplicationType.NONE)
.run(args);
}
}
3.test-dubbo-boot-consumer
消費(fèi)者也是主要三個(gè)文件耳幢。
1.服務(wù)調(diào)用類:DemoConsumerController
package com.nezha.test.dubbo.consumer;
import com.alibaba.dubbo.config.annotation.Reference;
import com.nezha.test.dubbo.DemoService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoConsumerController {
@Reference
private DemoService demoService;
@RequestMapping("/sayHello")
public String sayHello(@RequestParam String name) {
return demoService.sayHello(name);
}
}
2.配置文件:application.properties
# Spring boot application
spring.application.name = dubbo-consumer-demo
# Dubbo 服務(wù)消費(fèi)者配置
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
# Service Version
demo.service.version = 1.0.0
3.啟動(dòng)類:TestDubboBootConsumerApplication
package com.nezha.test.dubbo.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication()
public class TestDubboBootConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(TestDubboBootConsumerApplication.class, args);
}
}
Dubbo 簡(jiǎn)介
Dubbo是阿里巴巴SOA服務(wù)化治理方案的核心框架,每天為2,000+個(gè)服務(wù)提供3,000,000,000+次訪問量支持欧啤,并被廣泛應(yīng)用于阿里巴巴集團(tuán)的各成員站點(diǎn)睛藻。Dubbo是一個(gè)分布式服務(wù)框架,致力于提供高性能和透明化的RPC遠(yuǎn)程服務(wù)調(diào)用方案邢隧,以及SOA服務(wù)治理方案修档。
Dubbo 是什么?
Dubbo是一個(gè)分布式服務(wù)框架府框,致力于提供高性能和透明化的RPC遠(yuǎn)程服務(wù)調(diào)用方案,以及SOA服務(wù)治理方案讥邻。簡(jiǎn)單的說迫靖,dubbo就是個(gè)服務(wù)框架,如果沒有分布式的需求兴使,其實(shí)是不需要用的系宜,只有在分布式的時(shí)候,才有dubbo這樣的分布式服務(wù)框架的需求发魄,并且本質(zhì)上是個(gè)服務(wù)調(diào)用的東東盹牧,說白了就是個(gè)遠(yuǎn)程服務(wù)調(diào)用的分布式框架
其核心部分包含:
1.遠(yuǎn)程通訊: 提供對(duì)多種基于長連接的NIO框架抽象封裝,包括多種線程模型励幼,序列化汰寓,以及“請(qǐng)求-響應(yīng)”模式的信息交換方式。
2.集群容錯(cuò): 提供基于接口方法的透明遠(yuǎn)程過程調(diào)用苹粟,包括多協(xié)議支持有滑,以及軟負(fù)載均衡,失敗容錯(cuò)嵌削,地址路由毛好,動(dòng)態(tài)配置等集群支持。
3.自動(dòng)發(fā)現(xiàn): 基于注冊(cè)中心目錄服務(wù)苛秕,使服務(wù)消費(fèi)方能動(dòng)態(tài)的查找服務(wù)提供方肌访,使地址透明,使服務(wù)提供方可以平滑增加或減少機(jī)器艇劫。
Dubbo 能做什么吼驶?
1.透明化的遠(yuǎn)程方法調(diào)用,就像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法,只需簡(jiǎn)單配置旨剥,沒有任何API侵入咧欣。
2.軟負(fù)載均衡及容錯(cuò)機(jī)制,可在內(nèi)網(wǎng)替代F5等硬件負(fù)載均衡器轨帜,降低成本魄咕,減少單點(diǎn)。
3.服務(wù)自動(dòng)注冊(cè)與發(fā)現(xiàn)蚌父,不再需要寫死服務(wù)提供方地址哮兰,注冊(cè)中心基于接口名查詢服務(wù)提供者的IP地址,并且能夠平滑添加或刪除服務(wù)提供者苟弛。
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)用次調(diào)和調(diào)用時(shí)間的監(jiān)控中心 |
Container | 服務(wù)運(yùn)行容器 |
Dubbo提供三個(gè)關(guān)鍵功能喝滞,包括基于接口的遠(yuǎn)程呼叫,容錯(cuò)和負(fù)載平衡以及自動(dòng)服務(wù)注冊(cè)和發(fā)現(xiàn)
調(diào)用關(guān)系說明
1.服務(wù)容器負(fù)責(zé)啟動(dòng)膏秫,加載右遭,運(yùn)行服務(wù)提供者。
2.服務(wù)提供者在啟動(dòng)時(shí)缤削,向注冊(cè)中心注冊(cè)自己提供的服務(wù)窘哈。
3.服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)亭敢。
4.注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者滚婉,如果有變更,注冊(cè)中心將基于長連接推送變更數(shù)據(jù)給消費(fèi)者帅刀。
5.服務(wù)消費(fèi)者让腹,從提供者地址列表中,基于軟負(fù)載均衡算法扣溺,選一臺(tái)提供者進(jìn)行調(diào)用骇窍,如果調(diào)用失敗,再選另一臺(tái)調(diào)用娇妓。
6.服務(wù)消費(fèi)者和提供者像鸡,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心哈恰。
Dubbo 特點(diǎn)
Dubbo 架構(gòu)具有以下幾個(gè)特點(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)者
升級(jí)性
當(dāng)服務(wù)集群規(guī)模進(jìn)一步擴(kuò)大嘁信,帶動(dòng)IT治理結(jié)構(gòu)進(jìn)一步升級(jí)于样,需要實(shí)現(xiàn)動(dòng)態(tài)部署,進(jìn)行流動(dòng)計(jì)算潘靖,現(xiàn)有分布式服務(wù)架構(gòu)不會(huì)帶來阻力穿剖。下圖是未來可能的一種架構(gòu):
節(jié)點(diǎn)角色說明
節(jié)點(diǎn) | 角色說明 |
---|---|
Deployer | 自動(dòng)部署服務(wù)的本地代理 |
Repository | 倉庫用于存儲(chǔ)服務(wù)應(yīng)用發(fā)布包 |
Scheduler | 調(diào)度中心基于訪問壓力自動(dòng)增減服務(wù)提供者 |
Admin | 統(tǒng)一管理控制臺(tái) |
Registry | 服務(wù)注冊(cè)與發(fā)現(xiàn)的注冊(cè)中心 |
Monitor | 統(tǒng)計(jì)服務(wù)的調(diào)用次調(diào)和調(diào)用時(shí)間的監(jiān)控中心 |
參考文獻(xiàn)
Spring Boot集成的新特性可參考官方文檔: https://github.com/apache/incubator-dubbo-spring-boot-project
肥朝的Dubbo源碼學(xué)習(xí)http://www.reibang.com/u/f7daa458b874
Spring Boot 中使用 Dubbo 詳解:https://juejin.im/post/59f43c025188253d6816d7fe,這篇文章在掘金中找到的卦溢,很不錯(cuò)
dubbo-spring-boot-starter 的官方地址:https://github.com/apache/incubator-dubbo-spring-boot-project糊余,一開始問題一直不知道怎么解決秀又,看了
github
上的Issues
終于解決了!