天天看點

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

分布式RPC架構Apache Dubbo

  • 軟體架構的演進過程
    • 1· 單體架構
    • 2· 垂直架構
    • 3· SOA架構
    • 4· 微服務架構
  • Dubbo簡介
  • 服務注冊中心Zookeeper
    • Zookeeper樹型目錄服務:
  • Dubbo協定
  • Dubbo的負載均衡
  • 給Dubbo添加事務
    • @Transactional
    • 解決方法

軟體架構的演進過程

軟體架構的發展經曆了由單體架構、垂直架構、SOA架構到微服務架構的演進過程

1· 單體架構

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

全部功能集中在一個項目内(All in one)

架構優點:

架構簡單,前期開發成本低、開發周期短,适合小型項目。

架構缺點:

全部功能內建在一個工程中,對于大型項目不易開發、擴充和維護。

技術棧受限,隻能使用一種語言開發。

系統性能擴充隻能通過擴充叢集節點,成本高。

最初學習的項目就是為單體架構

2· 垂直架構

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

按照業務進行切割,形成小的單體項目。

架構優點:

技術棧可擴充(不同的系統可以用不同的程式設計語言編寫)。

架構缺點:

功能集中在一個項目中,不利于開發、擴充、維護。

系統擴張隻能通過叢集的方式。

項目之間功能備援、資料備援、耦合性強。

3· SOA架構

SOA全稱為Service-Oriented Architecture,即面向服務的架構。它可以根據需求通過網絡對松散耦合的粗粒度應用元件(服務)進行分布式部署、組合和使用。一個服務通常以獨立的形式存在于作業系統程序中。

站在功能的角度,把業務邏輯抽象成可複用的服務,通過服務的編排實作業務的快速再生,目的:把原先固有的業務功能轉變為通用的業務服務,實作業務邏輯的快速複用。

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

将重複功能或子產品抽取成元件的形式,對外提供服務,在項目與服務之間使用ESB(企業服務總線)的形式作為通信的橋梁。

架構優點:

重複功能或子產品抽取為服務,提高開發效率。

可重用性高。

可維護性高。

架構缺點:

各系統之間業務不同,很難确認功能或子產品是重複的。

抽取服務的粒度大。

系統和服務之間耦合度高。

目前大部分小型公司采用SOA架構

4· 微服務架構

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

将系統服務層完全獨立出來,抽取為一個一個的微服務。

抽取的粒度更細,遵循單一原則。

采用輕量級架構協定傳輸。

架構優點:

服務拆分粒度更細,有利于提高開發效率。

可以針對不同服務制定對應的優化方案。

适用于網際網路時代,産品疊代周期更短。

架構缺點:

粒度太細導緻服務太多,維護成本高。

分布式系統開發的技術成本高,對團隊的挑戰大。

目前市場上主流架構為微服務架構

Dubbo簡介

Apache Dubbo是一款高性能的Java RPC架構。其前身是阿裡巴巴公司開源的、輕量級的開源Java RPC架構,可以和Spring架構無縫內建,2018年阿裡巴巴把這個架構捐獻給了apache基金會。

RPC全稱為remote procedure call,即遠端過程調用。RPC是一個泛化的概念,嚴格來說一切遠端過程調用手段都屬于RPC範疇。

Dubbo提供了三大核心能力:面向接口的遠端方法調用,智能容錯和負載均衡,以及服務自動注冊和發現。

服務注冊中心Zookeeper

Zookeeper 是 Apache Hadoop 的子項目,是一個樹型的目錄服務,支援變更推送,适合作為 Dubbo服務的注冊中心,工業強度較高,可用于生産環境,并推薦使用 。

Zookeeper樹型目錄服務:

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

服務提供者(Provider)啟動時: 向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的URL 位址;

服務消費者(Consumer)啟動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者URL 位址。并向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 位址;

監控中心(Monitor)啟動時: 訂閱 /dubbo/com.foo.BarService 目錄下的所有提供者和消費者URL 位址;

Dubbo協定

Dubbo支援的協定有:dubbo、rmi、hessian、http、webservice、rest、redis等。

推薦使用的是dubbo協定,預設的端口号為20880

dubbo 協定采用單一長連接配接和 NIO 異步通訊,适合于小資料量大并發的服務調用,以及服務消費者機器數遠大于服務提供者機器數的情況。不适合傳送大資料量的服務,比如傳檔案,傳視訊等,除非請求量很低。

dubbo也可以在同一個工程中配置多個協定,不同服務可以使用不同的協定。

Dubbo的負載均衡

負載均衡(Load Balance):其實就是将請求分攤到多個操作單元上進行執行,進而共同完成工作任務。

在叢集負載均衡時,Dubbo 提供了多種均衡政策(包括随機、輪詢、最少活躍調用數、一緻性Hash),預設為random随機調用。

配置負載均衡政策,既可以在服務提供者一方配置,也可以在服務消費者一方配置:

public class HelloController {
//在服務消費者一方配置負載均衡政策
@Reference(check = false,loadbalance = "random")
private HelloService helloService;
           
//在服務提供者一方配置負載均衡
@Service(loadbalance = "random")
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "hello " + name;
}
}
           

給Dubbo添加事務

@Transactional

Dubboo通過提供的标簽配置進行包掃描,掃描到@Service注解的類後被釋出為服務。

但是在服務提供者類上加入@Transactional事務控制注解後,服務就釋出不成功了。原因是@Transactional注解的底層原理是為服務提供者類建立代理對象,預設情況下Spring是基于JDK動态代理方式建立代理對象,代理對象的完整類名為com.sun.proxy.$Proxy42(最後兩位數字不是固定的)。導緻

Dubbo在釋出服務前進行包比對時無法完成比對,進而沒有進行服務的釋出。

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

根據源碼可看出 beanClassName包的位址不能與pkg,無法傳回ture。

分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

解決方法

在l類上加入事務注解後,Spring會為此類基于JDK動态代理技術建立代理對象,建立的代理對象完整類名為com.sun.proxy.$Proxy35,導緻Dubbo在進行包比對時沒有成功。

(1)修改applicationContext-service.xml配置檔案,開啟事務控制注解支援時指定proxy-target-class屬性,值為true。其作用是使用cglib代理方式為Service類建立代理對象

<!--開啟事務控制的注解支援-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-targetclass="true"/>
           
分布式RPC架構Apache Dubbo軟體架構的演進過程Dubbo簡介服務注冊中心ZookeeperDubbo協定Dubbo的負載均衡給Dubbo添加事務

(2)修改HelloServiceImpl類,在Service注解中加入interfaceClass屬性,值為HelloService.class,作用是指定服務的接口類型

@Service(interfaceClass = HelloService.class)
@Transactional
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "hello " + name;
}
}