Dubbo必知必會

1. 爲什麼要進行系統拆分? 如何拆?

(1) 爲什麼要進行系統拆分?

  • 所有的業務模塊都在一個系統中, 導致系統太過於龐大, 迭代, 維護困難, 比如開發時很容易出現代碼衝突, 一次小改動就需要大量的迴歸測試.
  • 大一統的系統會系統的可靠性降低, 一個小地方出現問題就會導致整個系統不可用.
  • 不利於技術升級, 如果某個業務系統想要技術升級, 就必須整個系統跟着一起技術升級.

(2) 如何拆?

使用Dubbo根據業務進行垂直拆分, 比如將一個大一統的系統拆分爲UGC系統, 用戶系統, 訂單系統, 支付系統, 結算系統, 搜索系統, 審覈系統等等, 當這些系統慢慢地也變得龐大後, 再開始新一輪的拆分.

2. 說一下的dubbo的工作原理?說說一次RPC請求的流程?註冊中心掛了還可以繼續通信嗎?

(1) dubbo的工作原理, RPC請求的流程.

Dubbo的實現原理

(2) 註冊中心掛了還可以繼續通信嗎?

可以, 因爲剛開始初始化的時候, 消費者會將提供者的地址等信息拉取到本地緩存, 所以註冊中心掛了可以繼續通信.

3. dubbo支持哪些通信協議?爲什麼dubbo協議要使用長連接?

dubbo支持哪些通信協議?

(1) dubbo協議

  • 連接個數:單連接
  • 連接方式:長連接
  • 傳輸協議:TCP
  • 傳輸方式:NIO 異步傳輸
  • 序列化:Hessian 二進制序列化
  • 適用範圍:傳入傳出參數數據包較小(建議小於100K), 消費者比提供者個數多, 單一消費者無法壓滿提供者, 儘量不要用 dubbo 協議傳輸大文件或超大字符串.
  • 適用場景:常規遠程服務方法調用

(2) rmi協議

  • 連接個數:多連接
  • 連接方式:短連接
  • 傳輸協議:TCP
  • 傳輸方式:同步傳輸
  • 序列化:Java 標準二進制序列化
  • 適用範圍:傳入傳出參數數據包大小混合, 消費者與提供者個數差不多, 可傳文件.
  • 適用場景:常規遠程服務方法調用, 與原生RMI服務互操作

(3) hessian協議

  • 連接個數:多連接
  • 連接方式:短連接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:Hessian二進制序列化
  • 適用範圍:傳入傳出參數數據包較大, 提供者比消費者個數多, 提供者壓力較大, 可傳文件.
  • 適用場景:頁面傳輸, 文件傳輸, 或與原生hessian服務互操作.

(4) http協議

  • 連接個數:多連接
  • 連接方式:短連接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:JSON序列化
  • 適用範圍:傳入傳出參數數據包大小混合, 提供者比消費者個數多, 可用瀏覽器查看, 可用表單或URL傳入參數, 暫不支持傳文件.
  • 適用場景:需同時給應用程序和瀏覽器 JS 使用的服務.

(5) webservice協議

  • 連接個數:多連接
  • 連接方式:短連接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:SOAP 文本序列化
  • 適用場景:系統集成, 跨語言調用

爲什麼dubbo協議要使用異步單一長連接?

因爲服務的現狀大都是服務提供者少, 通常只有幾臺機器, 而服務的消費者多, 可能整個網站/APP都在訪問該服務. 通過單一連接, 保證單一消費者不會壓死提供者. 通過長連接, 減少連接握手驗證等, 並使用異步 IO, 來複用線程池, 防止 C10K 問題.

4. dubbo負載均衡策略和集羣容錯策略都有哪些?

爲了避免單點故障, 現在的應用通常至少會部署在兩臺服務器上, 這樣, 在同一環境下的服務提供者數量就會大於1, 服務消費者需要決定選擇哪個服務提供者進行調用, 這就是dubbo負載均衡策略. 另外, 服務調用失敗時的處理措施也是需要考慮的, 是重試, 還是拋出異常, 亦或是隻打印異常等, 這就是dubbo集羣容錯策略.
(1) dubbo負載均衡策略

  • RandomLoadBalance
    加權隨機算法.
  • LeastActiveLoadBalance
    最少活躍調用數算法
  • ConsistentHashLoadBalance
    一致性哈希算法
  • RoundRobinLoadBalance
    加權輪詢算法

(2) dubbo集羣容錯策略

  • Failover Cluster
    失敗自動切換, 默認, 常見於讀操作
  • Failfast Cluster
    快速失敗, 即一次調用失敗後就不再進行重試, 常見於寫操作
  • Failsafe Cluster
    失敗安全, 即出現異常時忽略掉, 常用於不重要的接口調用, 比如記錄日誌
  • Failback Cluster
    失敗自動恢復, 即失敗了後臺自動記錄請求, 然後定時重發, 比較適合於寫消息隊列這種
  • Forking Cluster
    並行調用多個服務提供者, 只要一個成功就立即返回.

5. dubbo的spi思想是什麼?

SPI 全稱爲 Service Provider Interface, 是一種服務發現機制. SPI 的本質是將接口實現類的全限定名配置在文件中, 並由服務加載器讀取配置文件, 加載實現類. 這樣可以在運行時, 動態爲接口替換實現類. 正因此特性, 我們可以很容易的通過 SPI 機制爲我們的程序提供拓展功能. SPI 機制在第三方框架中也有所應用, 比如 Dubbo 就是通過 SPI 機制加載所有的組件.

//配置通信協議爲dubbo.
<dubbo:protocol name="dubbo" port="20880" />

//dubbo配置文件
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol

6. 如何基於dubbo進行服務治理、服務降級、失敗重試以及超時重試?

(1) 什麼是服務治理?

  • 生成服務之間的依賴關係和調用鏈路圖
  • 統計每個服務的每個接口的每天調用次數, top50, top90, top99三個檔次的請求延時分別是多少.
  • 統計每個完整的請求鏈路每天的調用次數, top50, top90, top99三個檔次的請求延時分別是多少.
  • 每個服務的可用性監控, 即服務的接口調用成功率.(99.99%, 99.9%, 99%)
  • 服務分層, 避免循環依賴.
  • 調用鏈路失敗監控和報警.
  • 服務鑑權.

通過這些信息就能知道當前系統的壓力來自哪裏, 方便進行擴容和優化.

dubbo如何實現服務治理呢? 這裏就說公司沒有人力做服務治療, 我們可以回答下服務治理的思想.

(2) 什麼是服務降級?

服務A調用服務B, 服務B掛掉了, 服務A重試幾次後走備用邏輯, 返回響應給服務A. 下面我們來看下dubbo服務降級的配置:

a. 直接返回null

//消費方對該服務的方法調用都直接返回 null 值, 不發起遠程調用
<dubbo:reference id="bookService" interface="com.tyshawn.service.IBookService"  timeout="10000" check="false" mock="force:return+null">

//消費方對該服務的方法調用在失敗後, 再返回 null 值, 不拋異常
<dubbo:reference id="bookService" interface="com.tyshawn.service.IBookService"  timeout="10000" check="false" mock="fail:return+null">

b. 走自定義降級邏輯

//mock屬性配置爲true
<dubbo:reference id="bookService" interface="com.tyshawn.service.IBookService"  timeout="10000" check="false" mock="true">

//在BookServiceImpl的目錄下創建一個BookServiceImplMock類(實現類名+Mock後綴), 實現IBookService接口
public class BookServiceImplMock implements IBookService
{
	//降級邏輯	
}

(3) 失敗重試及超時

超時, 即調用接口在指定時間內沒有返回就認爲調用失敗.
失敗重試, 即調用接口失敗後再次發起調用.

<dubbo:reference id="bookService" interface="com.tyshawn.service.IBookService"  timeout="10000" check="false" retries="3">

7. 分佈式服務接口的冪等性如何設計(比如不能重複扣款)?

(1) 爲什麼要保證服務接口的冪等性?

爲了避免單點故障, 我們的服務都是多機部署的, 這些服務經常會遇到由於網絡超時導致接口重試問題, 比如扣款請求發送了兩次, 且路由到了兩臺服務器上. 我們需要保證相同的請求, 不管客戶端發送幾次, 最終的結果都是一樣的.

(2) 如何保證冪等性?

這個問題其實是一個業務問題, 我們要結合業務來回答, 比如如何避免重複扣款.

  • 先獲取分佈式鎖, 只有獲取到分佈式鎖的請求才能繼續操作.
  • 請求處理之前, 先從mysql中查詢對應的記錄是否已處理.
  • 請求處理完之後, 將mysql中對應記錄的狀態標記爲已處理.
  • 請求釋放分佈式鎖.

8. 分佈式服務接口請求的順序性如何保證?

絕大部分情況下都不用保證分佈式服務接口請求的順序性, 只有一些特殊情況需要, 比如服務A調用服務B的兩個接口, 要確保兩個接口的先後順序不能亂, 如先插入一條數據, 再刪除這條數據.

(1) 方法調用順序亂掉的情況

  • 服務A的兩次調用落在了服務B的兩臺服務器上, 無法保證哪次調用會先執行.
  • 服務A的兩次調用落在了服務B的同一臺服務器上, 但服務B是多線程處理的, 無法保證哪個線程會先執行.

(2) 解決辦法

在這裏插入圖片描述

  • 使用dubbo的一致性哈希負載均衡策略, 讓相同參數的請求落在同一臺服務器上.
  • 讓同一請求入同一個隊列, 每個隊列使用一個線程進行處理.

9. 如何自己設計一個類似dubbo的rpc框架?

手寫一個簡化版的Dubbo框架

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章