1. 程式人生 > >分散式架構與Dubbo基礎入門與實踐

分散式架構與Dubbo基礎入門與實踐

【1】分散式系統

① 什麼是分散式系統

《分散式系統原理與範型》定義:“分散式系統是若干獨立計算機的集合,這些計算機對於使用者來說就像單個相關係統”。

分散式系統(distributed system)是建立在網路之上的軟體系統。

隨著網際網路的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分散式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。


② 架構發展演變

如下圖所示:

在這裡插入圖片描述

  • 單一應用架構

當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。此時,用於簡化增刪改查工作量的資料訪問框架(ORM)是關鍵。

在這裡插入圖片描述

適用於小型網站,小型管理系統,將所有功能都部署到一個功能裡,簡單易用。

缺點: 1、效能擴充套件比較難 ;2、協同開發問題; 3、不利於升級維護。


  • 垂直應用架構

當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率。此時,用於加速前端頁面開發的Web框架(MVC)是關鍵。

在這裡插入圖片描述

通過切分業務來實現各個模組獨立部署,降低了維護和部署的難度,團隊各司其職更易管理,效能擴充套件也更方便,更有針對性。

缺點: 公用模組無法重複利用,開發性的浪費。


  • 分散式服務架構

當垂直應用越來越多,應用之間互動不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。此時,用於提高業務複用及整合的分散式服務框架(RPC)是關鍵。

在這裡插入圖片描述


  • 流動計算架構

當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個排程中心基於訪問壓力實時管理叢集容量,提高叢集利用率。此時,用於提高機器利用率的資源排程和治理中心(SOA)[ Service Oriented Architecture]是關鍵。

在這裡插入圖片描述

即,通常分散式應用就是面向服務的分散式架構。


③ RPC

  • 什麼叫RPC

RPC(Remote Procedure Call)是指遠端過程呼叫,是一種程序間通訊方式,他是一種技術的思想,而不是規範。它允許程式呼叫另一個地址空間(通常是共享網路的另一臺機器上)的過程或函式,而不用程式設計師顯式編碼這個遠端呼叫的細節。即程式設計師無論是呼叫本地的還是遠端的函式,本質上編寫的呼叫程式碼基本相同。

  • RPC基本原理

在這裡插入圖片描述

時序圖如下:

在這裡插入圖片描述

可以發現RPC兩個核心模組:通訊和序列化。

常見的RPC框架有:Dubbo、GRPC(谷歌)、Thrift(Facebook)、HSF(High Speed Service Framework 阿里)、JSF(京東)及Motan(新浪)。

參考:分散式微服務架構中核心理念


【2】Dubbo

Apache Dubbo (incubating) 是一款高效能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠端方法呼叫,智慧容錯和負載均衡,以及服務自動註冊和發現。

官網地址:http://dubbo.apache.org/
官網開發文件:http://dubbo.apache.org/zh-cn/docs/user/preface/

Dubbo的官方使用者文件提供了很詳細的使用說明與例項,遇到問題請一定參考官網文件!

① 結構示意圖

如下所示(012345表示執行順序,實現表示同步,虛線表示非同步):
在這裡插入圖片描述

特性如下:

  • 面向介面代理的高效能RPC呼叫:提供高效能的基於代理的遠端呼叫能力,服務以介面為粒度,為開發者遮蔽遠端呼叫底層細節。
  • 智慧負載均衡:內建多種負載均衡策略,智慧感知下游節點健康狀況,顯著減少呼叫延遲,提高系統吞吐量。
  • 服務自動註冊與發現:支援多種註冊中心服務,服務例項上下線實時感知。
  • 高度可擴充套件能力:遵循微核心+外掛的設計原則,所有核心能力如Protocol、Transport、Serialization被設計為擴充套件點,平等對待內建實現和第三方實現。
  • 執行期流量排程:內建條件、指令碼等路由策略,通過配置不同的路由規則,輕鬆實現灰度釋出,同機房優先等功能。
  • 視覺化的服務治理與運維:提供豐富服務治理、運維工具–隨時查詢服務元資料、服務健康狀態及呼叫統計,實時下發路由策略、調整配置引數。

② 幾個概念

服務提供者(Provider):暴露服務的服務提供方,服務提供者在啟動時,向註冊中心註冊自己提供的服務。

服務消費者(Consumer): 呼叫遠端服務的服務消費方,服務消費者在啟動時,向註冊中心訂閱自己所需的服務。服務消費者從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。

註冊中心(Registry):註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。

監控中心(Monitor):服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。


③ 呼叫關係說明

  • 服務容器負責啟動,載入,執行服務提供者。
  • 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  • 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  • 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
  • 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
  • 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心(monitor)。

【3】Zookeeper註冊中心

Dubbo推薦使用Zookeeper作為註冊中心,當然Dubbo還支援其他作為註冊中心如Multicast 註冊中心,Redis註冊中心和Simple 註冊中心(本身就是一個普通的 Dubbo 服務)。

① 核心概念

Zookeeper 是 Apacahe Hadoop 的子專案,是一個樹型的目錄服務,支援變更推送,適合作為 Dubbo 服務的註冊中心,工業強度較高,可用於生產環境,並推薦使用。

官網地址:http://zookeeper.apache.org/
下載地址:https://archive.apache.org/dist/zookeeper/

在這裡插入圖片描述

② 流程說明:

  • 服務提供者啟動時: 向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的 URL 地址
  • 服務消費者啟動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者 URL 地址。並向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 地址
  • 監控中心啟動時: 訂閱 /dubbo/com.foo.BarService 目錄下的所有提供者和消費者 URL 地址。

③ 支援以下功能:

  • 當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者資訊;
  • 當註冊中心重啟時,能自動恢復註冊資料,以及訂閱請求;
  • 當會話過期時,能自動恢復註冊資料,以及訂閱請求;
  • 當設定 <dubbo:registry check="false" />時,記錄失敗註冊和訂閱請求,後臺定時重試;
  • 可通過 <dubbo:registry username="admin" password="1234" /> 設定 zookeeper 登入資訊
  • 可通過 <dubbo:registry group="dubbo" /> 設定 zookeeper 的根節點,不設定將使用無根樹
  • 支援 *號萬用字元<dubbo:reference group="*" version="*" />,可訂閱服務的所有分組和所有版本的提供者

更多詳情參考:Dubbo官網文件


④ Windows下簡單搭建Zookeeper

下載好的Zookeeper解壓到本地目錄下,並修改zoo.cfg配置檔案。

步驟如下:

  • 解壓執行bin/zkServer.cmd ,初次執行會報錯,沒有zoo.cfg配置檔案;

  • 將conf下的zoo_sample.cfg複製一份改名為zoo.cfg即可。
    注意幾個重要位置:

    dataDir=./   臨時資料儲存的目錄(可寫相對路徑)
    clientPort=2181   zookeeper的預設埠號
    

    修改完成後再次啟動zookeeper

  • 使用zkCli.cmd測試

    ls /:列出zookeeper根下儲存的所有節點
    create –e  /myzookeeper 123:建立一個myzookeeper 節點,值為123
    get /myzookeeper :獲取/myzookeeper 節點的值
    

服務端啟動示意圖如下:
在這裡插入圖片描述

客戶端測試如下:
在這裡插入圖片描述


【4】Windows下安裝Dubbo管理控制檯

dubbo本身並不是一個服務軟體。它其實就是一個jar(2.6之後為jar,之前為war需要在Tomcat下執行)包能夠幫你的java程式連線到zookeeper,並利用zookeeper消費、提供服務。所以你不用在Linux上啟動什麼dubbo服務。

但是為了讓使用者更好的管理監控眾多的dubbo服務,官方提供了一個視覺化的監控程式,不過這個監控即使不裝也不影響使用。

安裝步驟如下:

  • 進入Dubbo的GitHub專案專案地址

  • 在最下方Dubbo eco system中點選進入Dubbo-OPS

  • Download ZIP並解壓到本地
    在這裡插入圖片描述

  • 進入目錄,修改dubbo-admin配置
    修改 src\main\resources\application.properties 指定zookeeper地址:

    dubbo.registry.address=zookeeper://127.0.0.1:2181
    
  • 打包dubbo-adminmvn clean package -Dmaven.test.skip=true

    D:\Java_Tomcat_MySQL_jdk_zip\incubator-dubbo-ops-master\dubbo-admin>mvn clean package -Dmaven.test.skip=true
    
    //D:\Java_Tomcat_MySQL_jdk_zip\incubator-dubbo-ops-master 為專案路徑
    

在這裡插入圖片描述
打包成功如下圖所示:
在這裡插入圖片描述

  • 使用命令執行jarjava -jar dubbo-admin-0.0.1-SNAPSHOT.jar
  • 瀏覽器訪問(http://localhost:7001/)預設使用者名稱密碼root/root
    在這裡插入圖片描述

Dubbo OPS專案與管理後臺jar包下載:點選下載


【5】伺服器提供者/消費者專案簡單實踐

① 簡單需求

某個電商系統,訂單服務需要呼叫使用者服務獲取某個使用者的所有地址。

我們現在 需要建立兩個服務模組進行測試 :

模組 功能
訂單服務模組 建立訂單等
使用者服務模組 查詢使用者地址等

測試預期結果:訂單服務模組在A伺服器,使用者服務模組在B伺服器,A可以遠端呼叫B的功能。

② 建立服務提供者和消費者

如下所示,建立兩個maven工程,分別表示provider和consumer:

在這裡插入圖片描述

那消費者如何呼叫provider的方法呢?這裡如果將provider依賴進consumer,則就成了單體應用。

或者可以這樣,將provider的bean和service拷貝到consumer中,如下所示:

在這裡插入圖片描述

該種方式專案例項參考SpringBoot整合Dubbo和Zookeeper

這種方式是有問題:第一,暫且不說現在OrderServiceImpl呼叫UserService肯定失敗(實現類在另外一個專案);第二,UserService可能會被多個模組呼叫,原則上不應該每個呼叫UserService的模組都新增bean和UserService介面,添麻煩。而且也不符合Dubbo的服務化最佳實踐

這裡將bean和介面抽離出來放在一個公共API專案中,provider和consumer依賴該專案。如下所示:

在這裡插入圖片描述在這裡插入圖片描述

現在需要解決的問題就是遠端呼叫,OrderServiceImpl如何呼叫userService.getUserAddressList(userId);


③ Dubbo改造服務提供者

第一步:引入依賴:

<!-- 引入dubbo -->
	<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>dubbo</artifactId>
		<version>2.6.2</version>
	</dependency>
	<!-- 註冊中心使用的是zookeeper,引入操作zookeeper的客戶端端 -->
	<dependency>
		<groupId>org.apache.curator</groupId>
		<artifactId>curator-framework</artifactId>
		<version>2.12.0</version>
	</dependency>

dubbo 2.6以前的版本引入zkclient操作zookeeper ,dubbo 2.6及以後的版本引入curator操作zookeeper。

下面兩個zk客戶端根據dubbo版本2選1即可:

<dependency>
	<groupId>com.101tec</groupId>
	<artifactId>zkclient</artifactId>
	<version>0.10</version>
</dependency>
<!-- curator-framework -->
<dependency>
	<groupId>org.apache.curator</groupId>
	<artifactId>curator-framework</artifactId>
	<version>2.12.0</version>
</dependency>


第二步,配置服務

在provider類路徑下新增配置檔案provider.xml:

	<!-- 1、指定當前服務/應用的名字(同樣的服務名字相同,不要和別的服務同名) -->
	<dubbo:application name="user-service-provider"></dubbo:application>
	
	<!-- 2、指定註冊中心的位置 -->
	<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
	<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
	
	<!-- 3、指定通訊規則(通訊協議?通訊埠) -->
	<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
	
	<!-- 4、暴露服務   ref:指向服務的真正的實現物件 -->
	<dubbo:service interface="com.web.gmall.service.UserService" 
		ref="userServiceImpl" >
		<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
	</dubbo:service>
	
	<!--統一設定服務提供方的規則  -->
	<dubbo:provider timeout="1000"></dubbo:provider>
	
	<!-- 服務的實現 -->
	<bean id="userServiceImpl" class="com.web.gmall.service.impl.UserServiceImpl"></bean>

第三步,編寫主類進行測試

public class MainApplication {
	
	public static void main(String[] args) throws IOException {
		ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
		ioc.start();
		
		System.in.read();
	}
}

使用Dubbo Admin管理後臺檢視,可以發現已經新增了一個服務提供者:

在這裡插入圖片描述


④ Dubbo改造服務消費者

第一步:引入依賴:

<!-- 引入dubbo -->
	<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>dubbo</artifactId>
		<version>2.6.2</version>
	</dependency>
	<!-- 註冊中心使用的是zookeeper,引入操作zookeeper的客戶端端 -->
	<dependency>
		<groupId>org.apache.curator</groupId>
		<artifactId>curator-framework</artifactId>
		<version>2.12.0</version>
	</dependency>

第二步,配置服務

在消費者class資源路徑下配置consumer.xml:

    <context:component-scan base-package="com.web.gmall.service.impl"></context:component-scan>

	<dubbo:application name="order-service-consumer"></dubbo:application>
	
	<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
	
	
	<!--宣告需要呼叫的遠端服務的介面;生成遠端服務代理  -->
	<dubbo:reference interface="com.web.gmall.service.UserService" 
		id="userService" >
	</dubbo:reference>


第三步,編寫主類進行測試

public class MainApplication {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
		
		OrderService orderService = applicationContext.getBean(OrderService.class);
		
		orderService.initOrder("1");
		System.out.println("呼叫完成....");
		System.in.read();
	}
}

在保證Zookeeper服務端,Dubbo Admin和伺服器提供者啟動並正常執行前提下,執行該消費者主類,將會從服務提供者那裡獲取資料!

使用Dubbo Admin後臺檢視:

在這裡插入圖片描述

截止現在,Dubbo+Zookeeper簡單整合實踐,原始碼下載地址


【6】安裝Monitor監控中心

Simple Monitor 掛掉不會影響到 Consumer 和 Provider 之間的呼叫,所以用於生產環境不會有風險。

Simple Monitor 採用磁碟儲存統計資訊,請注意安裝機器的磁碟限制,如果要叢集,建議用mount共享磁碟。

① 安全並執行Monitor

和安裝Dubbo Admin時步驟類似,進入incubator-dubbo-ops-master\dubbo-monitor-simple目錄下,使用maven命令進行打包:

mvn clean package -Dmaven.test.skip=true

在這裡插入圖片描述

這裡執行jar前,需要檢視一下配置檔案。將dubbo-monitor-simple-2.0.0-assembly.tar.gz複製並解壓到指定資料夾下,檢視其conf目錄下的配置檔案:
在這裡插入圖片描述

// Zookeeper註冊中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
//監控中心於其他服務通訊埠
dubbo.protocol.port=7070
//監控中心web頁面訪問埠
dubbo.jetty.port=8080

之後,進入dubbo-monitor-simple-2.0.0\assembly.bin目錄,執行start.bat。

在這裡插入圖片描述

進入瀏覽器檢視監控中心:
在這裡插入圖片描述

此時監控中心還沒有消費者。


② 修改服務提供者/消費者配置

在consumer.xml中新增如下配置:

<dubbo:monitor protocol="registry"></dubbo:monitor>

在provider.xml中如下配置:

<dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>

這兩種有什麼區別?參考官方文件

在這裡插入圖片描述

重新啟動provider和consumer,提供者向消費者索取服務再次檢視Monitor,將會發現com.alibaba.dubbo.monitor.MonitorService對應的consumer有兩個:provider和consumer都是MonitorService的消費者!