1. 程式人生 > 其它 >springBoot整合Dubbo的使用

springBoot整合Dubbo的使用

Zookeeper

ZooKeeper是一種為分散式應用所設計的高可用、高效能且一致的開源協調服務,它提供了一項基本服務:分散式鎖服務。由於ZooKeeper的開源特性,後來我們的開發者在分散式鎖的基礎上,摸索了出了其他的使用方法:配置維護、組服務、分散式訊息佇列、分散式通知/協調等。

建議使用zookeeper3.4.5及以上版本註冊中心。

Zookeeper是Apache Hadoop的子專案,強度相對較好,建議生產環境使用該註冊中心。

Dubbo未對Zookeeper伺服器端做任何侵入修改,只需安裝原生的Zookeeper伺服器即可,所有註冊中心邏輯適配都在呼叫Zookeeper客戶端時完成。

 

Zookeeper配置
1、下載zookeeper

2、然後修conf/zoo.cfg

dataDir=D:\zookeeper-3.3.6\\data

dataLogDir=D:\zookeeper-3.3.6\\log

3、執行zkServer.cmd,啟動Zookeeper

 

監控中心

監控中心的主要使用就是檢視dubbo提供者和消費者的資訊,以及他們的呼叫情況。


監控中心配置
1、下載dubbo-monitor

2、然後修conf/dubbo.properties

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.jetty.port=28080

3、執行start.bat,啟動監控中心


監控中心介面
在瀏覽器輸入 http://localhost:8080,就可以進入監控中心

 

構建API模組
專案結構:
springbootdubboapi
springbootdubboclient
springbootdubboservice

 

api模組中就一個介面,然後將api模組打包(maven→Lifecycle→install)雙擊install

public interface TestServiceApi {
   String sayHello(String name);
}

 

Dubbo服務提供者
Pom.xml新增dubbo依賴

<!--
spring web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 整合dubbo--> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!-- zookeeper客戶端--> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.11</version> </dependency> <!-- 打包的api路徑 --> <dependency> <groupId>com.test</groupId> <artifactId>springbootdubbo_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>

 

application.yml配置dubbo註冊中心

 

server:
  port: 8081  # 埠號
spring:
  dubbo:    # Dubbo服務提供者配置
    application:
      name: provider  # 服務名稱
    registry:
      address: zookeeper://127.0.0.1:2181  # 註冊中心地址
    protocol:
      name: dubbo  # dubbo協議
      port: 28081  # dubbo協議埠

 

 

提供服務

@Service //注意是com.alibaba.dubbo.config.annotation.Service包的service
@Component
public class ITestService implements TestServiceApi {

    @Override
    public String sayHello(String s) {
        return "Hello" + s;
    }
}

 

啟動服務

注意加上@EnableDubboConfiguration註解

@SpringBootApplication
@ComponentScan(basePackages = "com.Test.*")
@EnableDubboConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

 

監控中心可檢視到釋出的服務

 

Dubbo服務消費者

Pom.xml新增dubbo依賴

<!-- spring web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

<!-- 整合dubbo-->
        <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

<!-- zookeeper客戶端-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.11</version>
        </dependency>

<!-- 打包的api路徑 -->
        <dependency>
            <groupId>com.test</groupId>
            <artifactId>springbootdubbo_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

 

application.yml配置dubbo註冊中心

server:
  port: 8082  # 埠號
spring:
  dubbo:    # Dubbo服務提供者配置
    application:
      name: provider  # 服務名稱
    registry:
      address: zookeeper://127.0.0.1:2181  # 註冊中心地址
    protocol:
      name: dubbo  # dubbo協議
      port: 28082  # dubbo協議埠

 

消費者呼叫服務

@RestController
@RequestMapping(value = "/test")
public class DepController {

    @Reference //注意是com.alibaba.dubbo.config.annotation.Reference包的
    private TestServiceApi testServiceApi;

    @RequestMapping(value = "/sayHello")
    public String sayHello() {
        return testServiceApi.sayHello("張三消費者");
    }
}

 

啟動消費者

注意加上@EnableDubboConfiguration註解

@SpringBootApplication
@ComponentScan(basePackages = "com.test.*")
@EnableDubboConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

 

監控中心可檢視到釋出的consumer服務

 

輸入網址就能顯示內容了

http://localhost:8082/test/sayHello

 

超時時間,重試次數配置

timeout:可以設定duboo呼叫的超時時間(毫秒為單位)
retries :可以設定重試次數

@Service(timeout = 1000, retries = 3, group = "group1")
@Component

 

服務分組

可以用group屬性

示例:

@Service(timeout = 1000, retries = 3, group = "group1")
@Component
public class IEmpService implements EmpServiceApi {

    @Override
    public String sayHello(String s) {
        return "hello" + s;
    }
}


@Service(timeout = 1000, retries = 3, group = "group2")
@Component
public class IEmpService implements EmpServiceApi {


    @Override
    public String sayHello(String s) {
        return "hello" + s;
    }
}


@RestController
@RequestMapping(value = "/test")
public class EmpController {

    @Reference(group = "group1", loadbalance = "roundrobin")
    private TestServiceApi testServiceApi1;

    @Reference(group = "group2", loadbalance = "roundrobin")
    private TestServiceApi testServiceApi2;

    @RequestMapping(value = "/sayHello1")
    public String sayHello() {
        return empServiceApi1.sayHello("消費者1");
    }

    @RequestMapping(value = "/sayHello2")
    public String sayHello() {
        return empServiceApi2.sayHello("消費者2");
    }


}

 

負載均衡演算法 

random 隨機
leastactive 最小活躍值
consistenthash 一致雜湊
roundrobin 輪詢

配置:

 

random:權重隨機演算法,根據權重值進行隨機負載。它的演算法思想很簡單。

假設我們有一組伺服器 servers = [A, B, C],他們對應的權重為 weights = [5, 3, 2],權重總和為 10。

現在把這些權重值平鋪在一維座標值上,[0, 5) 區 間屬於伺服器 A,[5, 8) 區間屬於伺服器 B,[8, 10) 區間屬於伺服器 C。

接下來通過 隨機數生成器生成一個範圍在 [0, 10) 之間的隨機數,然後計算這個隨機數會落到哪個 區間上。

比如數字 3 會落到伺服器 A 對應的區間上,此時返回伺服器 A 即可。

權重 越大的機器,在座標軸上對應的區間範圍就越大,因此隨機數生成器生成的數字就會 有更大的概率落到此區間內。

只要隨機數生成器產生的隨機數分佈性很好,在經過多 次選擇後,每個伺服器被選中的次數比例接近其權重比例。


leastactive:最少活躍呼叫數演算法,活躍呼叫數越小,表明該服務提供者效率越高,單位時間內可處理更多的請求這個是比較科學的負載均衡演算法。

每個服務提供者對應一個活躍數 active。初始情況下,所有服務提供者活躍數均為 0。 每收到一個請求,活躍數加 1,完成請求後則將活躍數減 1。

在服務執行一段時間後, 效能好的服務提供者處理請求的速度更快,因此活躍數下降的也越快,此時這樣的服 務提供者能夠優先獲取到新的服務請求。

 

consistenthash:hash 一致性演算法,相同引數的請求總是發到同一提供者 當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者, 不會引起劇烈變動。

 

roundrobin:加權輪詢演算法是指將請求輪流分配給每臺伺服器。

舉個例子,我們有三臺伺服器 A、B、C。 我們將第一個請求分配給伺服器 A,第二個請求分配給伺服器 B,第三個請求分配給 伺服器 C,第四個請求再次分配給伺服器 A。

這個過程就叫做輪詢。輪詢是一種無狀 態負載均衡演算法,實現簡單,適用於每臺伺服器效能相近的場景下。

但現實情況下, 我們並不能保證每臺伺服器效能均相近。

如果我們將等量的請求分配給效能較差的服 務器,這顯然是不合理的。

因此,這個時候我們需要對輪詢過程進行加權,以調控每 臺伺服器的負載。經過加權後,每臺伺服器能夠得到的請求數比例,接近或等於他們 的權重比。

比如伺服器 A、B、C 權重比為 5:2:1。那麼在 8 次請求中,伺服器 A 將 收到其中的 5 次請求,伺服器 B 會收到其中的 2 次請求,伺服器 C 則收到其中的 1次請求。

 

叢集容錯 

在分散式網路通訊中,容錯能力是必須要具備的,什麼叫容錯呢? 從字面意思來看: 容:是容忍, 錯:是錯誤。 就是容忍錯誤的能力。

我們知道網路通訊會有很多不確定因素,比如網路延遲、網路中斷、服務異常等,會造成當前這次請求出現失敗。當服務通訊出現這個問題時,需要採取一定的措施應對。

而 dubbo 中提供了容錯機制來優雅處理這種錯誤,在叢集呼叫失敗時,Dubbo 提供了多種容錯方案,預設為 failover 重試。

 

failover:失敗自動切換,當出現失敗,重試其它伺服器。(預設) 通常用於讀操作,但重試會帶來更長延遲。 可通過 retries=“2” 來設定重試次數(不含第一次)。
failfast:快速失敗,只發起一次呼叫,失敗立即報錯。 通常用於非冪等性的寫操作,比如新增記錄。
failsafe:失敗安全,出現異常時,直接忽略。 通常用於寫入審計日誌等操作。
failback:失敗自動恢復,後臺記錄失敗請求,定時重發。 通常用於訊息通知操作。

forking:並行呼叫多個伺服器,只要一個成功即返回。 通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。 可通過 forks=“2” 來設定最大並行數。
broadcast:廣播呼叫所有提供者,逐個呼叫,任意一臺報錯則報錯。(2.1.0 開始支援) 通常用於通知所有提供者更新快取或日誌等本地資源資訊。
在實際應用中查詢語句容錯策略建議使用預設 failover ,而增刪改建議使用 failfast 或者使用 failover (retries=”0”) 策略,防止出現數據重複、新增等等其它問題!

建議在設計介面時候把查詢介面方法單獨做一個介面提供查詢。

 

服務降級 

當某個非關鍵服務出現錯誤時,可以通過降級功能來臨時遮蔽這個服務。降級可以有幾個層面的分類: 自動降級和人工降級; 按照功能可以分為:讀服務降級和寫服務降級
1. 對一些非核心服務進行人工降級,在大促之前通過降級開關關閉哪些推薦內容、評 價等對主流程沒有影響的功能。
2. 故障降級,比如呼叫的遠端服務掛了,網路故障、或者 RPC 服務返回異常。

那麼 可以直接降級,降級的方案比如設定預設值、採用兜底資料(系統推薦的行為廣告 掛了,可以提前準備靜態頁面做返回)等等 。
3. 限流降級,在秒殺這種流量比較集中並且流量特別大的情況下,因為突發訪問量特 別大可能會導致系統支撐不了。

這個時候可以採用限流來限制訪問量。當達到閥值 時,後續的請求被降級,比如進入排隊頁面,比如跳轉到錯誤頁(活動太火爆,稍 後重試等)

 

Dubbo中如何實現服務降級?
Dubbo中提供了一個mock的配置,可以通過 mock來實現當服務提供方出現網路異常或者掛掉以後,客戶端不丟擲異常,而是通過 Mock資料返回自定義的資料 。

 

客服端呼叫服務配置引數,增加mock配置,以及修改timeout=500, 表示本次呼叫的超時時間是0.5秒,

這樣可以模擬出失敗的場景 需要配置cluster=failfast,否則因為預設是failover導致客戶端會發起3次重試,等待的時間比較長。

 

 

服務端程式碼,只需要加一個休眠時間讓客戶端呼叫超時即可。

 

啟動時檢查 

Dubbo 預設會在啟動時檢查依賴的服務是否可用,不可用時會丟擲異常,阻止 Spring 初始化完成,以便上線時,能及早發現問題,預設 check="true"。

可以通過 check="false" 關閉檢查,比如,測試時,有些服務不關心,或者出現了迴圈依賴,必須有一方先啟動。