Dubbo基礎知識
一:基本概念
軟件架構的發展過程
單體架構-----垂直架構-----SOA架構-----微服務架構
- 單體架構:(All In One)所有的服務集中在一個應用,擴展時需要橫向擴展整個系統(成本較高)。
- 優點:適用於小型項目,開發部署簡單易用
- 缺點:大型項目不易開發與維護;只能使用一種開發語言;擴展成本高
- 垂直架構:根據業務進行整個應用的切割,拆成幾個互不影響的應用。
- 舉例說明下:一個系統包含用戶管理,訂單模塊,物流模塊,垂直架構就是,將系統根據業務分爲用戶管理和訂單模塊,用戶管理和物流模塊兩個應用,分別部署,由於公用模塊用戶管理無法複用,這也是垂直架構的一個痛點。
- 優點:實現了系統的業務的分離,能夠進行模塊的單獨部署
- 缺點:系統的切割粒度過大;擴展只能採用集羣方式;公共模塊無法複用,項目之間功能冗餘。
- SOA架構(Service-Oriented Architecture):面向服務架構
- 定義:將重複的功能或模塊抽取成組件的形式,對外服務;項目與服務之間使用ESB(企業服務總線)的形式作爲通信的橋樑。
- 缺點:依賴於ESB(中央管理模式進行各應用之間的交互運作)。
- 微服務架構:單獨部署,獨立運行。
- 定義:將系統服務完全獨立出來,抽取爲一個個職責單一的服務,服務之間採用輕量級的框架協議(Http)進行交互。
- 優點:每個服務足夠內聚,足夠小,代碼容易理解、開發效率提高;服務之間可以獨立部署,微服務架構讓持續部署成爲可能;每個服務可以各自進行橫向擴展和縱向擴展,而且,每個服務可以根據自己的需要部署到合適的硬件服務器上;容易擴大開發團隊,可以針對每個服務(service)組件開發團隊;提高容錯性(fault isolation),一個服務的內存泄露並不會讓整個系統癱瘓;系統不會被長期限制在某個技術棧上。
- 缺點:從優點中推其缺點
- 服務衆多,難以維護與管理(Dubbo+ZK,SpringCloud)。
- 服務間交互通訊是不可靠的(RPC)
- 分佈式事務處理(數據一致性)
- 單獨部署就意味着每一個服務都擁有自己數據落地存儲(MySQL),也就意味着微服務的擴展,只能採用集羣方式。
SOA機構與微服務架構一脈相承,微服務架構做了更細緻的處理(服務的顆粒度更小,去中心化,去ESB)。
功能 | SOA | 微服務 |
---|---|---|
組件大小 | 大塊業務邏輯 | 單獨任務或小塊業務邏輯 |
耦合 | 通常鬆耦合 | 總是鬆耦合 |
公司架構 | 任何類型 | 小型、專注於功能交叉的團隊 |
管理 | 着重中央管理 | 着重分散管理 |
目標 | 確保應用能夠交互操作 | 執行新功能,快速拓展開發團隊 |
Dubbo概念簡介
以下內容摘自dubbo官網:
dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。
dubbo就是一款解決服務間通信的框架,它能讓不在一臺服務器的各個服務進行相互調用,對使用者來說就像調用本地方法一樣,併爲我們整合了智能容錯和負載均衡,當某個服務不可用或是當某個服務新增時dubbo會自動發現並註冊他們。dubbo還提供了管理控制檯,我們可以很直觀的看到當前註冊中心的狀態以及註冊中心中註冊的服務(包括服務的提供者和消費者;dubbo推薦ZK作爲其註冊中心),還可以對這些服務進行各種管理,包括服務動態配置,負載均衡,訪問控制,權重管理等等
二:基本結構與流程
dubbo官網上的dubbo架構圖:
Node | Role Spec | 翻譯 |
---|---|---|
Provider | The provider exposes remote services | 服務提供者(生產遠程調用的服務) |
Consumer | The consumer calls the remote services | 消費者(調用遠程服務) |
Registry | The registry is responsible for service discovery and configuration | 註冊中心(服務的註冊與配置) |
Monitor | The monitor counts the number of service invocations and time-consuming | 監視器(統計並監聽服務提供者、消費者的情況) |
Container | The container manages the services’s lifetime | 服務的容器(管理服務的生命週期) |
服務註冊中心(dubbo推薦ZK)
(這裏只做ZK的一些簡單介紹與安裝說明[單機版],後續博主會詳細更新ZK的相關文章)
官方文檔解釋
它是一個分佈式服務框架,是Apache Hadoop 的一個子項目,它主要是用來解決分佈式應用中經常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。
簡單點來講zooKeeper就是一個樹形目錄服務(或者說文件系統+監聽通知機制)。
1. 樹形目錄結構
ZK支持四種zNode
- PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在
- PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
- EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除
- EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
說明:子目錄例如 NameService 都被稱作爲 znode(目錄節點),和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,同時znode可以存儲數據。
2. 監聽通知機制
客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
3. zookeeper單機版安裝
兩種方式:一、docker部署;二、解壓縮對應的壓縮文件,並修改配置文件
docker部署
docker pull zookeeper
docker run -d -v /home/docker/zookeeperhost/zookeeperDataDir:/data -v /home/docker/zookeeperhost/zookeeperDataLogDir:/datalog -e ZOO_MY_ID=1 -e ZOO_SERVERS='server.1=192.168.32.134:2888:3888' -p 2181:2181 -p 2888:2888 -p 3888:3888 --name zookeeper --privileged zookeeper
非docker部署
Step1:配置JAVA環境,檢驗環境:
# java -version
Step2:下載並解壓zookeeper
# cd /usr/local
# wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz
# tar -zxvf zookeeper-3.4.12.tar.gz
# cd zookeeper-3.4.12
Step3:重命名配置文件zoo_sample.cfg
# cp conf/zoo_sample.cfg conf/zoo.cfg
Step4:啓動zookeeper
# bin/zkServer.sh start
Step5:檢測是否成功啓動,用zookeeper客戶端連接下服務端
# bin/zkCli.sh
配置zoo.cfg文件
- tickTime
基本事件單元,以毫秒爲單位。它用來控制心跳和超時,默認情況下最小的會話超時時間爲兩倍的 tickTime。 - dataDir是存放內存數據庫快照的位置;
- dataLogDir 是事務日誌目錄;
- clientPort是client連接的端口。
tickTime=2000
dataDir=/usr/zdatadir
dataLogDir=/usr/zlogdir
clientPort=2181
initLimit=5
syncLimit=2
三:項目中如何使用與注意事項
項目中簡單實用可以概括爲以下幾點
- 服務提供者:service類使用Dubbo的@Service註解(表明該服務會註冊到Dubbo的ZK註冊中心)
- 配置文件(XML)或者SpringBoot集成Dubbo在application.yml配置文件中配置Dubbo的註冊中心(ZK)
- 服務消費者:使用@Reference註解,標註到對應服務接口對象(服務消費者與提供者,實現的服務接口需一致)
- 項目中,爲了避免提供者服務與消費者服務中接口冗餘,會將接口放入統一的接口模塊中(存放工程中所有Dubbo管理的服務接口)
Dubbo配置文件詳解
配置文件主要配置以下內容
- 註冊中心
- 協議配置(不同的傳輸協議,可以提高Dubbo對服務的高效調用)
- 服務發佈(1.包掃描+註解;2.註冊bean+<dubbo:service … /> 手動註冊服務)
示例配置文件:
<?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:context="http://www.springframework.org/schema/context"
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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<!-- 提供方應用信息,用於計算依賴關係 -->
<dubbo:application name="dubbo_provider" />
<!-- 使用zookeeper註冊中心暴露服務地址() -->
<dubbo:registry address="zookeeper://192.168.32.135:2181" />
<!-- 用dubbo協議在20880端口暴露服務 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 具體的實現bean
<bean id="demoService" class="com.floatcloud.provider.service.impl.ProviderServiceImpl" />
-->
<!-- 聲明需要暴露的服務接口
<dubbo:service interface="com.floatcloud.provider.service.ProviderService" ref="demoService" />
-->
<!-- 使用註解方式暴露接口 -->
<dubbo:annotation package="com.floatcloud.provider.service" />
<!-- 加入spring註解掃描 -->
<context:component-scan base-package="com.floatcloud.provider"/>
</beans>
Dubbo常見的屬性配置
1. <dubbo:application/> 應用配置,用於配置當前應用信息,不管該應用是提供者還是消費者。
2. <dubbo:registry/> 註冊中心配置,用於配置連接註冊中心相關信息。
<dubbo:protocol/> 協議配置,用於配置提供服務的協議信息,協議由提供方指定,消費方被動接受。
3.
// 服務提供者
<dubbo:service/> 服務配置,用於暴露一個服務,定義服務的元信息,一個服務可以用多個協議暴露,一個服務也可以註冊到多個註冊中心。
// 服務消費者
<dubbo:reference/> 引用服務配置,用於創建一個遠程服務代理,一個引用可以指向多個註冊中心。
4.
<dubbo:module/> 模塊配置,用於配置當前模塊信息,可選。
<dubbo:monitor/> 監控中心配置,用於配置連接監控中心相關信息,可選。
<dubbo:provider/> 提供方的缺省值,當ProtocolConfig和ServiceConfig某屬性沒有配置時,採用此缺省值,可選。
<dubbo:consumer/> 消費方缺省配置,當ReferenceConfig某屬性沒有配置時,採用此缺省值,可選。
<dubbo:method/> 方法配置,用於ServiceConfig和ReferenceConfig指定方法級的配置信息。
<dubbo:argument/> 用於指定方法參數配置。
詳細參數分析:參見道人另一篇博文。
這裏主要講解SpringBoot與Dubbo集成的場景
項目結構如圖:
1. pom.xml文件設置
api接口module
<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>
服務提供者module
<!--引入api模塊-->
<dependency>
<groupId>com.floatcloud</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!--引入dubbo環境-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
服務消費者module
<!--引入api模塊-->
<dependency>
<groupId>com.floatcloud</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!--引入dubbo環境-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
2. application.yml配置文件
服務提供者module
server:
port: 8081
dubbo:
application:
name: dubbo-provider
registry:
address: 192.168.32.135:2181
protocol: zookeeper
check: false
protocol:
name: dubbo
port: 30003
monitor:
protocol: register
consumer:
check: false
timeout: 3000
服務消費者module
server:
port: 8082
dubbo:
application:
name: dubbo-consumer
registry:
address: 192.168.32.135:2181
protocol: zookeeper
check: false
monitor:
protocol: register
consumer:
check: false
timeout: 3000
3. 接口業務邏輯代碼
api接口module
/**
* OrderService
* 訂單接口
* @auther FloatCloud
* @date 2020/5/16
*/
public interface OrderService {
/**
* 修改訂單狀態
* @param status 訂單狀態
* @return 修改是否成功
*/
boolean swapOrderStatus(int status);
}
服務提供者module
import com.alibaba.dubbo.config.annotation.Service;
import com.floatcloud.api.service.OrderService;
/**
* ProviderService
* 服務提供者
* @auther FloatCloud
* @date 2020/5/16
*/
@Service
public class ProviderService implements OrderService {
@Override
public boolean swapOrderStatus(int status) {
if(status > 0){
return true;
}
return false;
}
}
服務消費者module
import org.springframework.stereotype.Service;
import com.alibaba.dubbo.config.annotation.Reference;
import com.floatcloud.api.service.OrderService;
/**
* ConsumerService
* 服務的消費者
* @auther FloatCloud
* @date 2020/5/16
*/
@Service
public class ConsumerService {
@Reference
private OrderService orderService;
public boolean change(int status){
return orderService.swapOrderStatus(status);
}
}
四:Dubbo注意事項
負載均衡
將請求均勻分攤到多個操作單元上進行執行,從而共同完成工作,Dubbo提供的均衡策略有(隨機、輪詢、最少活躍調用數、一致性hash),缺省爲Random(隨機調用)。
項目中使用loadbalance指定相應的均衡策略
// 服務提供方
@Service(loadbalance = "random")
// 服務消費方
@Reference(loadbalance = "random")
服務被事務管理,Dubbo無法發佈該Service
@Transactional 註解
原因:Spring的事務管理是基於JDK動態代理來實現,JDK動態代理針對的是接口,會代理生成實現該接口的代理類,而生成的代理類的包名不是固定的(com.sum.proxy.$Proxy11,最後兩位數字不固定),導致Dubbo發佈服務無法通過包匹配查找到對應服務,因此無法進行服務的發佈。
解決方法:
- 服務提供方,@Service 通過interfaceClass參數來指定接口
@Service(loadbalance = "random", interfaceClass = OrderService.class)
- 事務代理方式由JDK動態代理轉化爲cglib動態代理(代理的是類)
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
若是springBoot項目,在AOP中進行設置
spring:
aop:
proxy-target-class: true