網(wǎng)絡(luò)資源訪問層ral設(shè)計

一,介紹

resource access layer,簡稱ral。我們暫且將lar層的一個網(wǎng)絡(luò)實例稱為raler。
下面的講解以bd ral為例。ral是以php拓展的形式提供的一個客戶端,來實現(xiàn)對后端服務(wù)的網(wǎng)絡(luò)請求。用戶在ral.conf配置相應(yīng)的下游地址(支持ip:port,也支持dns這種域名)后,即可使用ral一站式接口與下游服務(wù)進(jìn)行網(wǎng)絡(luò)交互。

二,功能列表

作為資源訪問層,ral層設(shè)計包含如下幾方面的功能:

1,支持多種交互協(xié)議和數(shù)據(jù)打包格式

ral將網(wǎng)絡(luò)交互過程分成了:

  • 打包
  • 網(wǎng)絡(luò)傳輸交互
  • 解包
    三個過程。并且支持常用的后端交互協(xié)議(http,nshead等)。目前支持http,nshead,fcgi三種交互協(xié)議;支持string、mcpack1,mcpack2,json,form五種數(shù)據(jù)打包協(xié)議。打包,解包,網(wǎng)絡(luò)交互對用戶透明,在配置文件中正確配置即可。

2,支持資源定位,統(tǒng)一配置,降低運維成本。

支持通過zookeeper和bns方式獲取服務(wù)配置,在zookeeper or bns服務(wù)端更新節(jié)點配置信息后,觸發(fā)客戶端回調(diào)并更新服務(wù)列表配置。此外ral也支持local方式來資源定位,在zookeeper or bns宕機后也可以訪問下游。

3,支持本機配置健康檢查和負(fù)載均衡策略。

支持多種均衡策略:

  • random
  • random robin,即輪詢
  • 一致hash

4,支持服務(wù)變更后自動加載

ral支持服務(wù)配置自動加載。修改配置文件或者資源定位數(shù)據(jù)發(fā)生變更時,ral客戶端會首選校驗配置合法性,通過后會動態(tài)加載新的配置文件,并更新本地備份。

總的來說,ral高度封裝了交互過程,集成了負(fù)載均衡,超時重試,資源定位,配置自動加載等功能,讓調(diào)用方不再需要關(guān)心繁瑣的通用邏輯。

三,配置示例

local配置示例:

# 新增服務(wù),請先找到 [..Local] 父節(jié)點,在這個父節(jié)點底下添加 Local 的服務(wù)的配置
[..Local]
[...@Service]
# 服務(wù)名
Name : demoService
DefaultPort : 8080
DefaultRetry : 2
# 連接類型,目前僅支持 SHORT,即短連接
DefaultConnectType : SHORT
# 連接超時,單位ms,默認(rèn)值 200
DefaultConnectTimeOut : 200
# 讀超時,單位ms,默認(rèn)值 500
DefaultReadTimeOut : 500
# 寫超時,單位ms,默認(rèn)值 500
DefaultWriteTimeOut : 500
[....@Server]
IP : 10.10.10.10
# 此處的 Tag 表示這臺后端 Server 屬于 jx 機房,在負(fù)載均衡的時候會優(yōu)先考慮訪問本機房的后端
Tag: jx
[....@Server]
IP : 10.10.10.11
# 此處如果不配置 Tag,該后端 Server 對全部機房有效
# Tag: yf
# 此處如果配了 Port, 可覆蓋上面的 DefaultPort
# Port :8080
[....@Server]
# 除了 IP,還可以配 Hostname,RAL 會幫你做域名解析
Hostname: cq01-ksarch-rdtest00.vm
# 如果同時配了 IP 和 Hostname,以 IP 為準(zhǔn)
# 訪問內(nèi)網(wǎng)服務(wù)建議使用 IP 方式
IP : 10.10.10.12
[....Protocol]
# 交互協(xié)議名稱 支持 http / nshead / pshead / fcgi
Name : http
[....Converter]
# 打包協(xié)議名稱 支持 form / mcpack1 / mcpack2 / json / string 
Name : mcpack2
[....SuperStrategy]
# 直接使用配置套餐
# 可選套餐: RANDOM_PACK / CONSISTENCY_PACK / ROUNDROBIN_PACK
Package : RANDOM_PACK
# 若不使用套餐,可參考以下詳細(xì)配置
# 超級負(fù)載均衡均衡策略 Random / Consistency / RoundRobin
# Random 隨機選擇一個可用的后端
# Consistency一致性hash 根據(jù)傳入的第四個參數(shù)(bk),加server ipport進(jìn)行計算后hash
# RoundRobin 輪詢各個后端
#Balance : Random
#【以下如果配置不完整表示關(guān)閉對應(yīng)的健康狀態(tài)】
#連接失敗率的狀態(tài)隊列,表示記錄過去多少次連接狀態(tài),不可reload
#ConnectQueueSize : 100
# 控制連接失敗率
#ConnectX1 : 10
#ConnectY1 : 95
#ConnectX2 : 40
#ConnectY2 : 5
#讀取健康狀態(tài),表示記錄過去多少秒的讀取狀態(tài),不可reload
#HealthyQueueSize : 100
# client端讀的超時時間,單位ms
#HealthyTimeout : 100
#計算選擇概率的時間間隔,以s為單位
#HealthyCheckTime : 3
#選擇概率的最小值,0.1表示最小概率為10%
#HealthyMinRate : 0.1
#速度大于這個倍數(shù)才能做流量切分,用于不對稱節(jié)點的負(fù)載平衡
#HealthyBackupThreshold : 3
# 是否允許跨機房連接
#CrossRoom : Off
#是否打開全混聯(lián), 相當(dāng)于該服務(wù)全部機器接受任意機房tag請求
#Hybrid : Off

webfoot配置示例:

[...@Service]
Name: group.icc-qta.iknow.cn
Rename: Qta
Timeout: 1500

四,不同數(shù)據(jù)打包格式的操作

  • string 格式,指不做任何打包、解包操作,直接將 payload(ral() 的第三個參數(shù),即“有效負(fù)載數(shù)據(jù)”) 發(fā)到后端;
  • json格式,需要傳一個php array作為payloa
    ,ral做json_encode得到j(luò)son string。
  • form 格式,指 www-form-urlencoded,需要傳一個 php array 作為 payload,若 payload 有嵌套的 array,內(nèi)層 array 進(jìn)行 json_encode 處理。例如:payload = array( 'user' => 'tom', 'love' => array( 'first' => 'lily', 'second' => 'anna' ) ); 如果是 "post" 方式發(fā)送的,后端收到的_POST 請求是
    array( 'user' => 'tom', 'love' => '{"first":"lily","second":"anna"}` );
  • mcpack 格式,需要遵守 mcpack 打包格式規(guī)范。

idc匹配和idc mapping

支持按優(yōu)先級選擇不同機房的實例。多機房部署的時候可能會用到。具體見文末參考。

五,負(fù)載均衡

對每一次負(fù)載均衡處理,均衡過程首先會對一個服務(wù)多個實例的優(yōu)先級進(jìn)行排序,一次請求的均衡過程如下:

ral目前支持隨機,輪詢和一致性hash三種均衡策略。首先要清楚,負(fù)載均衡要解決的問題:

  • 如何合理利用后端資源,避免浪費
  • 提高服務(wù)吞吐量,降低平響
  • 特定應(yīng)用的負(fù)載均衡,比如有cache的應(yīng)用,如何提高cache命中率
  • 有部分實例掛掉時,如何對外保障服務(wù)穩(wěn)定性
  • 前端請求壓力過大時,如何對后端進(jìn)行過載保護(hù)。

目前ral的負(fù)載均衡支持的功能:

  • 確定機器選擇的優(yōu)先級
  • 根據(jù)連接健康狀態(tài)選擇
  • 根據(jù)讀取健康狀態(tài)選擇
  • 根據(jù)機器的處理能力選擇
    下面分別詳細(xì)介紹本文的重點:隨機,輪詢和一致性hash三種均衡策略。

1,隨機均衡

隨機(Random)是最傳統(tǒng)的均衡方式,每個服務(wù)實例得分通過隨機的方式獲取。
這種方式服務(wù)請求會比較均勻的分配到不同的實例上,以保證后端機器資源使用比較均勻,避免某臺機器壓力過大而導(dǎo)致服務(wù)不穩(wěn)定。這種方式也是最常使用的一種均衡策略。

2,輪詢均衡

輪詢也是一種比較傳統(tǒng)的均衡方式。這種均衡方式,可以確保對后端服務(wù)實例的訪問在任何時刻都是非常均勻的。 考慮到還有健康檢查等處理流程,輪詢策略并不會直接確定本次請求的實例,只保本次輪詢到的實例具有最高優(yōu)先級。在計算優(yōu)先級得分時,是按照以下方式進(jìn)行:
均衡時確保每次輪詢到的server實例得分最高,其它機器則退化為隨機取模的方式計算均衡得分:
本期輪詢到server實例得分:N + 1
其它實例得分:rand() % N
最后根據(jù)得分對均衡的優(yōu)先級進(jìn)行排序,以保證輪詢到的機器具有最高優(yōu)先級,其他實例優(yōu)先級隨機排序。

3,一致性hash均衡

一致性hash(consistency)的均衡策略常用于存在cache的服務(wù),對于這類服務(wù)均衡時需考慮其cache命中率,特定的請求應(yīng)盡可能的映射到同一臺機器。
使用Hash的方式做均衡時,要考慮兩點:

  • hash均勻性
    選取合適的hash函數(shù),盡量保證均勻映射。
  • hash單調(diào)性
    hash單調(diào)性是指,如果某個raler實例下線,只會影響這個raler前后兩個實例,而不至于所有的hash都要重排。這樣可以最大限度保證cache命中率。

六,根據(jù)連接健康狀態(tài)進(jìn)行選擇

在經(jīng)過均衡策略處理后,每個下游服務(wù)的實例按照優(yōu)先級從高到低排。然后在這一步,根據(jù)健康狀態(tài)對實例進(jìn)行淘汰。

對每個實例的連接狀態(tài)都需要進(jìn)行記錄,以判斷該機器的健康狀態(tài),實現(xiàn)時會為每個服務(wù)實例都維護(hù)一個連接狀態(tài)的隊列,記錄最近一段時間的連接情況。當(dāng)然這個隊列的長度是可以進(jìn)行配置的,也就是ral配置文件中的ConnectQueueSize。每次有連接失敗的情況進(jìn)隊,失敗計數(shù)加一,失敗狀態(tài)出隊時,則連接失敗次數(shù)減一。


X軸表示連接失敗次數(shù),Y軸表示連接健康狀態(tài)(100%為正常)

從上圖可以看出,隊列(長度為ConnectQueueSize)中失敗次數(shù)與健康狀態(tài)的關(guān)系,在連續(xù)多次失敗時,一旦隊列中的失敗次數(shù)超過P點的X坐標(biāo),健康狀態(tài)便會降到最低。這里K點及P點的坐標(biāo)在RAL中都有其對應(yīng)的配置:
ConnectX1 : 10 (K點X坐標(biāo))
ConnectY1 : 95 (K點Y坐標(biāo))
ConnectX2 : 40 (P點X坐標(biāo))
ConnectY2 : 5 (P點Y坐標(biāo))

最后根據(jù)連接健康狀態(tài)進(jìn)行選擇,健康得分就是該實例的選擇概率,健康得分越低淘汰的概率也就越大。
另外,需要注意的是,RAL中要使這個隊列生效,需要運行在php-cgi的情況下,因為對于CLI方式,每次執(zhí)行PHP連接健康狀態(tài)的隊列每次都會被重新初始化,從而無法保留狀態(tài)信息。

七,根據(jù)讀取健康狀態(tài)選擇

在根據(jù)連接健康狀態(tài)進(jìn)行選擇后,連接異常的實例已經(jīng)歷過一次淘汰了。
負(fù)載均衡并未就此結(jié)束,對于一個穩(wěn)定運行的服務(wù)實例,其時處理時間也應(yīng)當(dāng)收斂。 基于這點考慮,負(fù)載均衡還進(jìn)一步支持根據(jù)服務(wù)訪問的健康狀態(tài)進(jìn)行選擇淘汰。 這里需要注意的是, 讀取健康狀態(tài)的判斷是建立在服務(wù)處理時間收斂的基礎(chǔ)上。對于穩(wěn)定運行時處理時間不收斂的服務(wù),該過程并不適合。
為了記錄每個實例處理時間的歷史狀態(tài),負(fù)載均衡會為每個實例都維護(hù)一個讀取時間的隊列,該隊列保留過去一段時間內(nèi)的狀態(tài),這里保留多久也是支持配置的,配置項為:HealthyQueueSize。 那么已經(jīng)知道了最近一段時間內(nèi)服務(wù)讀取的時間,該如何進(jìn)一步計算讀取的健康狀態(tài)呢,這里的思路如下:

每隔一段時間(M秒)計算該時間段內(nèi)讀取的平均時間,即上述的recent_avg(M)。將該平均時間與隊列中總的平均處理時間進(jìn)行比較,如果M秒內(nèi)出現(xiàn)波動且耗時增加,健康狀態(tài)便會有所降低,而耗時減少健康狀態(tài)則會提高。但如果服務(wù)確實耗時增加且整體處理時間又穩(wěn)定下來,那么經(jīng)過一段時間,健康狀態(tài)又會收斂到正常水平。

上式的間隔時間M和健康超時時間timeout(read)都可在配置文件中指定,對應(yīng)的配置項分別是:HealthyCheckTime和HealthyTimeout。如果無HealthyTimeout配置則不啟用讀取健康狀態(tài)選擇。 得到健康得分f(healthy)后,選擇或淘汰將按如下方式進(jìn)行(其中R是選擇概率的最小值,對應(yīng)配置項是HealthyMinRate):

八,根據(jù)機器處理能力進(jìn)行選擇

在經(jīng)過了前面兩步健康選擇和淘汰的過程后,負(fù)載均衡會進(jìn)一步考慮根據(jù)機器的處理能力對請求進(jìn)行分流,即流量切分。 當(dāng)后端某個實例的性能過低時,應(yīng)該考慮將流量切分給性能更好機器。至于性能差距在多大時考慮流量切分,可以通過配置HealthyBackupThreshold來指定流量切分閾值。 那么首先面臨的問題是:該如何定義某個機器實例的性能呢?
可以通過該實例的平均處理時間來判斷,即1/avgtime。 在獲取機器實例性能的基礎(chǔ)上,就可以對其進(jìn)行流量切分,盡可能的將請求分配到性能更好的實例去處理,切分思路如下:

  • 首先:高于平均水平的機器并不需要進(jìn)行流量切分。
  • 其次:對性能低于平均水平的實例,需要考慮對其進(jìn)行流量切分,性能越低的后端實例被切流量的概率也就越大,切流量時會以配置的切分閾值為標(biāo)準(zhǔn)來查找更優(yōu)的實例,當(dāng)然如果找不到符合要求的后端實例就不作切分。最終切流量機器選擇時,仍然會按照均衡策略給定優(yōu)先級順序考慮。

其實個人覺得這一步跟上一步的根據(jù)讀取健康狀態(tài)的工作,是重復(fù)的。

即使有一些服務(wù)實例處理時間較長或網(wǎng)絡(luò)延遲較大,通過負(fù)載均衡的切流量就可以避免請求延遲較大的服務(wù)實例,使服務(wù)整體對外的性能較優(yōu)。

九,最終選擇

在負(fù)載均衡經(jīng)歷了以上三個選擇過程后,常規(guī)的負(fù)載均衡過程就以完成,這時已經(jīng)能夠確定本次交互優(yōu)先選擇的服務(wù)實例。
不過除了以上功能,負(fù)載均衡還支持進(jìn)行跨機房訪問。 考慮到有時服務(wù)會分機房部署,為降低網(wǎng)絡(luò)延遲及帶寬成本會優(yōu)先請求當(dāng)前機房的機器。當(dāng)單邊機房不穩(wěn)定或宕機的情況下,為了避免拒絕服務(wù),可以配置嘗試跨機房。服務(wù)可通過CrossRoom配置開啟跨機房。

在后端實例配置了機房且啟用跨機房,那么當(dāng)前機房的實例在經(jīng)過以上三種狀態(tài)選擇被淘汰時,便可嘗試跨機房去請求其他機房的實例。 如果不啟用跨機房,便會在經(jīng)歷過以上選擇淘汰的結(jié)果中,選擇最高優(yōu)先級且未因健康狀態(tài)被淘汰的那個實例。

整個下游服務(wù)實例選擇過程如下:

下游實例選取過程

十,參考文章

1,資源訪問層

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容