Dubbo與Zookeeper簡單理解

理論

在《分散式系統原理與范型》一書中有如下定義:「分散式系統是若干獨立電腦的集合,這些電腦對於用戶來說就像單個相關係統 」;

分散式系統是由一組通過網路進行通訊、為了完成共同的任務而協調工作的電腦節點組成的系統。分散式系統的出現是為了用廉價的、普通的機器完成單個電腦無法完成的計算、存儲任務。其目的是利用更多的機器,處理更多的數據。

在這裡插入圖片描述

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

首先需要明確的是,只有當單個節點的處理能力無法滿足日益增長的計算、存儲任務的時候,且硬體的提升(加記憶體、加磁碟、使用更好的CPU)高昂到得不償失的時候,應用程式也不能進一步優化的時候,我們才需要考慮分散式系統。因為,分散式系統要解決的問題本身就是和單機系統一樣的,而由於分散式系統多節點、通過網路通訊的拓撲結構,會引入很多單機系統沒有的問題,為了解決這些問題又會引入更多的機制、協議,帶來更多的問題。。。

Dubbo

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

在Dubbo的官網文檔有這樣一張圖

在這裡插入圖片描述

單一應用架構

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

在這裡插入圖片描述

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

1、性能擴展比較難

2、協同開發問題

3、不利於升級維護

垂直應用架構

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

在這裡插入圖片描述

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

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

分散式服務架構

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

在這裡插入圖片描述

流動計算架構

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

在這裡插入圖片描述

RPC

什麼是RPC?

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

也就是說兩台伺服器A,B,一個應用部署在A伺服器上,想要調用B伺服器上應用提供的函數/方法,由於不在一個記憶體空間,不能直接調用,需要通過網路來表達調用的語義和傳達調用的數據。為什麼要用RPC呢?就是無法在一個進程內,甚至一個電腦內通過本地調用的方式完成的需求,比如不同的系統間的通訊,甚至不同的組織間的通訊,由於計算能力需要橫向擴展,需要在多台機器組成的集群上部署應用。RPC就是要像調用本地的函數一樣去調遠程函數;

推薦閱讀文章: //www.jianshu.com/p/2accc2840a1b

RPC基本原理

在這裡插入圖片描述

步驟解析

在這裡插入圖片描述

RPC兩個核心模組:通訊,序列化。

序列化的作用 : 數據傳輸需要轉換,

Dubbo與Zookeeper的安裝

什麼是dubbo?

Apache Dubbo | dxbou|是一款高性能、輕量級的開源Jdva RPC框架,它提供了三大核心能力:面向介面的遠程方法調用,智慧容錯和負載均衡,以及服務自動註冊和發現。

dubbo官網: Apache Dubbo

  1. 了解Dubbo的特性

  2. 查看官方文檔dubbo基本概念

Dubbo基本概念

在這裡插入圖片描述

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

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

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

監控中心(Monitor) : 服務消費者和提供者,在記憶體中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心

調用關係說明

  • 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  • 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  • 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
  • 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。
  • 服務消費者和提供者,在記憶體中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。

Dubbo環境搭建

點進dubbo官方文檔,推薦我們使用 Zookeeper 註冊中心 | Apache Dubbo

什麼是zookeeper呢?可以查看官方文檔

windows下載zookeeper

  1. 下載zooleeper Apache ZooKeeper

  2. 運行/bin/zkServer.cmd 初次運行會報錯,沒有zoo.cfg配置文件; 可能遇到問題:閃退!

  3. 解決方案:編輯zkServer.cmd文件末尾添加pause。這樣運行出錯就不會退出,會提示錯誤資訊,方便找到原因。

在這裡插入圖片描述

在這裡插入圖片描述

windows下載dubbo-admin

dubbo-admin :是一個監控管理後台查看我們註冊了哪些服務,哪些服務被消費了

dubbo本身並不是一個服務軟體。它其實就是一個jar包,能夠幫你的jiava程式連接到zookeeper,並利用zookeeper消費、提供服務。

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

  1. 下載dubbo-admin

地址 : //github.com/apache/dubbo-admin/tree/master

  1. 解壓進入目錄

修改 dubbo-admin\src\main\resources \application.properties 指定 zookeeper 地址

  1. 在項目目錄下打包dubbo-admin
mvn clean package -Dmaven.test.skip-true
報錯選這個    
mvn package 

第一次打包的過程有點慢,需要耐心等待! 直到成功!

  1. 執行dubbo-admin\target 下的dubbo-admin-0.0.1-SNAPSHOT.jar
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

【注意:zookeeper的服務一定要打開! 】

  • 執行完畢,我們去訪問一下http:/localhost:7001/

  • 這時候我們需要輸入登錄賬戶和密碼,我們都是默認的root-root

  • 登錄成功後,查看介面

SpringBoot + Dubbo + zookeeper

步驟

  1. 提供者提供服務
    1. 導入依賴
    2. 配置註冊中心的地址,以及服務發現名,和要掃描的包
    3. 在想要被註冊的服務上面~增加一個註解 @Service
  2. 消費者如何消費
    1. 導入依賴
    2. 配置註冊中心的地址,配置自己的服務名
    3. 從遠程注入服務 @Reference

需要的jar包:

Dubbo + zookeeper

zkclient

排除日誌的包 不然會衝突

依賴

<!--dubbo依賴-->
        <!-- //mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!--zookeeper客戶端依賴-->
        <!-- //mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>``
        </dependency>
        <!--日誌衝突-->
        <!-- 引入zookeeper -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
            <!--排除這個slf4j-log4j12-->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

提供者配置文件

server:
  port: 8001
dubbo:
  application:
    name: provider-server  #提供者名字
  registry:
    address: zookeeper://127.0.0.1:2181  #zookeeper註冊中心地址
  scan:
    base-packages: com.knight.service #需要註冊
  protocol:
    name: dubbo
    port: 20880 #如果要實現負載均衡效果,修改這裡的埠,如果不配置,會顯示埠佔用
    

負載均衡的例子配置,與上面的提供者實現負載均衡,只需要修改兩處埠號即可

server:
  port: 8002
dubbo:
  application:
    name: provider-server  #提供者名字
  registry:
    address: zookeeper://127.0.0.1:2181  #zookeeper註冊中心地址
  scan:
    base-packages: com.knight.service #需要註冊的包
  protocol:
    name: dubbo
    port: 20881

消費者的配置

server:
  port: 9001
dubbo:
  application:
    name: consumer-server
  registry:
    address: zookeeper://127.0.0.1:2181

提供者例子

@Component //這裡相當於正常的@Service,避免與dubbo的@Service混了,建議用@Component
@Service //注意,此處的service註解是dubbo的
public class TicketServiceImpl  implements TicketService{
    @Value("${server.port}")
    private String port;
    @Override
    public String getTicket() {
        return "《德魯大叔》"+port;
    }
}

消費者調用提供者的例子,這裡的TicketService介面的路徑和提供者一致,不需要實現,即消費者和提供者的介面都是在com.*.service這個路徑下,否則會找不到

@Service  
public class UserService {
    //獲得provider提供的票
    //想拿到provider提供的方法,要去註冊中心拿到服務
    @Reference  //兩種方法拿到註冊中心的服務,1、pom坐標,2,定義路徑相同的介面名
    private TicketService ticketService;
    public String getTicket(){
        return ticketService.getTicket();
    }
}

在這裡插入圖片描述