RPC實現原理之核心技術 路由與負載均衡

2021-10-21 19:34:40 字數 4300 閱讀 3450

為什麼要採用路由?

真實的環境中一般是以集群的方式提供服務,但對於服務呼叫方來說,乙個介面會有多個服務提供方同時提供服務,所以 rpc 在每次發起請求的時候,都需要從多個服務節點裡面選取乙個用於處理請求的服務節點

每次上線應用的時候都不止執行一台伺服器例項,上線就會涉及到變更,只要變更就可能導致原本正常執行的節點出現異常,尤其是發生重大變動或公升級的時候,導致應用服務的不穩定因素就很多。

為減少這種風險,一般會選擇灰度方式發布應用例項,比如可以先發布部分例項觀察是否存在異常,後續再根據使用的情況,選擇發布更多例項或是回滾已經上線的例項。

但這種方式也會存在缺陷,線上一旦出現問題,還是會有一定影響。對於我們的服務提供方來說,服務會同時提供給很多的呼叫方來呼叫,尤其像一些基礎性的服務,呼叫會更加頻繁複雜,比如商品、**等等,一旦線上例項有問題,將會導致所有的呼叫方業務受到影響。

如何減少上線變更導致的風險?這就需要在rpc應用中增加路由功能。

如何實現路由?

基於上面所講述的問題,是不是可以在上線完成之後,先讓一小部分的呼叫請求進行邏輯驗證,待沒問題後再接入其他的服務節點,從而實現流量隔離的效果。那麼在 rpc 框架裡面該具體如何實現呢?

1)服務註冊發現方式:

如果通過服務發現的方式來隔離呼叫方的請求,從邏輯上看是可行,但註冊中心在 rpc 裡面的作用是用來儲存資料並保證資料的一致性。如果把這種複雜的計算邏輯放到註冊中心內,當集群節點變多之後,就會導致註冊中心壓力很大,而且大部分情況下我們是採用開源軟體來搭建註冊中心,還需要進行二次開發。所以從實際的角度出發,通過服務發現方式來實現請求隔離並不理想。

2)rpc路由策略:

在 rpc 發起請求的時候,有乙個步驟就是從服務提供方節點集合裡面選擇乙個合適的節點(負載均衡),那麼就可以在選擇節點前再加上乙個「篩選邏輯」,把符合我們要求的節點篩選出來。這個就是路由策略:

接收請求–>請求校驗–>路由策略–>負載均衡–>

常見的有ip 路由策略,用於限制哪些可以呼叫服務方的客戶端 ip。使用了 ip 路由策略後,整個集群的呼叫拓撲如下圖所示:

有了 ip 路由之後,上線過程中就可以只讓部分請求呼叫到新上線的例項,相對傳統的灰度發布方式來講,這樣做我們可以把試錯成本降到最低。

但有些場景下,可能還需要更細粒度的路由方式,比如說根據sessionid要落到相同的服務節點上以保持會話的有效性,某個商品的請求都採用同乙個服務節點處理,那麼ip路由的方式就不能滿足我們的要求, 這個時候就可以採用引數化路由

相比 ip 策略路由,引數路由支援的灰度粒度更小,這也是乙個服務治理的手段。灰度發布功能是 rpc 路由功能的乙個典型應用場景,通過 rpc 路由策略的組合使用可以讓服務提供更加靈活地管理、合理分配流量,進一步降低上線可能導致的風險。

rpc框架中的負載均衡

rpc 的負載均衡是由 rpc 框架自身提供實現,rpc 的服務呼叫方會與「註冊中心」下發的所有服務節點建立長連線,在每次發起 rpc 呼叫時,服務呼叫方都會通過配置的負載均衡外掛程式,自主選擇乙個最佳的服務節點,發起 rpc 呼叫請求。

rpc 負載均衡策略一般包括輪詢、隨機、權重、最少連線等。其中隨機,輪詢策略應該屬最常用的策略,dubbo預設就是使用隨機負載均衡策略,這些策略基本可以保證每個節點接收到的請求流量是平均的;同時我們還可以通過控制節點權重的方式,來進行流量控制。比如預設每個節點的權重都設為 100,但我們把其中的乙個節點的權重更改為50 時,它接收到的流量就是其他節點的 一半。

自適應的負載均衡策略

rpc 的負載均衡完全由 rpc 框架自身實現,服務呼叫方發起請求時,會通過所配置的負載均衡元件,自主地選擇合適服務節點。呼叫方如果能知道每個服務節點處理請求的能力,再根據服務節點處理請求的能力來判斷分配相應的流量,集群資源就能夠得到充分的利用, 當乙個服務節點負載過高或響應過慢時,就少給它傳送請求,反之則多給它傳送請求。這個就是自適應的負載均衡策略。

具體如何實現?

這就需要判定服務節點的處理能力, 服務呼叫方收集與之建立長連線的每個服務節點的指標資料,比如服務節點的負載指標、cpu 核數、記憶體大小、請求處理的耗時指標、服務節點的狀態指標(cpu/記憶體佔用率)。通過這些指標,計算出乙個分數,比如總分 100 分,如果 cpu 負載達到 80%,就減它 10分,記憶體負載達到80%,再減10分,以此模擬,需要減多少分是需要乙個合理依據的計算策略。

主要步驟:

(1)新增計分器和指標採集器,將其作為自適應負載均衡演算法的元件,用於採集記錄服務節點的狀態, 並且評定相應的分數。

(2)指標採集器收集服務節點 cpu 核數、cpu 負載以及記憶體佔用率等指標,還包括請求耗時等資料,通過服務呼叫方與服務提供方的心跳資料來獲取。

(3)可以配置開啟哪些指標採集器,並設定這些參考指標的具體權重,再根據指標的實際資料和權重來綜合打分。

(4)通過對服務節點的綜合打分,最終計算出服務節點的實際權重,之後服務呼叫方會根據相應的路由策略,來選擇合適的服務節點。

dubbo路由負載原始碼剖析:

呼叫路徑:

abstractclusterinvoker.invoke() -> abstractclusterinvokerd.doinvoke() ->abstractinvoker.invoke()

原始碼剖析:

abstractclusterinvoker.invoke方法:

@override

public result invoke

(final invocation invocation)

throws rpcexception

list

> invokers =

list

(invocation)

;// 初始化負載均衡策略

loadbalance loadbalance =

initloadbalance

(invokers, invocation)

; rpcutils.

attachinvocationidifasync

(geturl()

, invocation)

;return

doinvoke

(invocation, invokers, loadbalance)

;}

最後呼叫的doinvoke是乙個抽象方法,該方法主要是負責dubbo集群呼叫容錯不同策略的具體實現:

protected

abstract result doinvoke

(invocation invocation, list

> invokers,

loadbalance loadbalance)

throws rpcexception;

dubbo預設採用的是failoverclusterinvoker策略。

failoverclusterinvoker.doinvoke方法:

public result doinvoke

(invocation invocation,

final list

> invokers, loadbalance loadbalance)

throws rpcexception

通過上述原始碼剖析, 我們就可以在dubbo中實現abstractloadbalance的doselect介面,自定義擴充套件實現自適應權重負載均衡策略,充分發揮rpc服務集群的資源,提公升整體效能。

RPC實戰與核心原理之非同步RPC

提公升吞吐量,其實關鍵就兩個字 非同步 提高cpu等資源的利用率 非同步,最常用的方式就是返回 future 物件的 future 方式,或者入參為 callback 物件的 方式,而 future 方式可以說是最簡單的一種非同步方式了。我們發起一次非同步請求並且從請求上下文中拿到乙個 future...

XGBoost核心技術與實現

在學習本文之前,需要掌握cart樹 boosting演算法。模型定義 在傳統gtb模型中新增了正則項,為了控制模型整體的複雜度和葉子結點權值分數。xgboost對gtb的優化 目標函式近似 模型的目標函式用傳統的方法很難在歐式空間進行優化,xgboost使用近似的方法解決。泰勒公式是乙個用函式某點的...

docker docker基礎原理,核心技術簡介

關於docker的核心技術,就是以下的三大技術 1.namespaces 命名空間 使用linux的命名空間實現的程序間隔離。docker 容器內部的任意程序都對宿主機器的程序一無所知。除了程序相關的命名空間,還會設定與使用者 網路 ipc 以及 uts 相關的命名空間。docker 通過命名空間成...