得物彩虹橋架構演進之路-負載均衡篇

得物技术發表於2024-11-19

一、前言

一年一更的彩虹橋系列又來了,在前面兩期我們分享了在穩定性和效能2個層面的一些演進&最佳化思路。近期我們針對彩虹橋 Proxy 負載均衡層面的架構做了一次升級,目前新架構已經部署完成,生產環境正在逐步升級中,藉此機會更新一下彩虹橋架構演進之路系列的第三篇。

閱讀本文預計需要20~30分鐘,建議不熟悉彩虹橋的同學在閱讀本文前,可以先看一下前兩篇彩虹橋架構演進的文章:

得物資料庫中介軟體平臺“彩虹橋”演進之路
彩虹橋架構演進之路-效能篇|得物技術

二、背景

彩虹橋目前依賴 SLB 做負載均衡和節點發現,隨著業務發展流量越來越高,SLB 頻寬瓶頸逐漸暴露,雖然在半年前做過一次雙 SLB 改造臨時解決了頻寬瓶頸,但運維成本也隨之變高。除了頻寬瓶頸外,SLB 無法支援同區優先訪問,導致難以適配雙活架構。所以準備去除彩虹橋對 SLB 的強依賴,自建彩虹橋後設資料中心,提供負載均衡和節點發現等能力,同時支援同區訪問等能力來更好的適配雙活架構。下面會詳細介紹一下彩虹橋後設資料中心以及 SDK 相關能力的相關細節。

三、核心名稱解釋

圖片

四、現有架構

回顧在開始介紹彩虹橋後設資料中心之前,我們先來回顧一下彩虹橋目前架構,以及存在的一些痛點。

現有架構

圖片

  • 業務服務整合 SDK 透過域名訪問,請求經過 SLB 轉發到具體的 Proxy 節點。
  • 每個叢集掛載雙 SLB,SDK 透過 DNS 解析輪訓路由到2個 SLB,2個 SLB 掛載不同的後端節點。
  • 每個叢集部署的 Proxy 節點均為一個可用區,雙活架構為叢集維度多可用區部署。
  • 業務側大多數為多可用區混布,單同一個邏輯庫只會連線一個彩虹橋叢集,由於彩虹橋一個叢集內的節點均為同一可用區,所以業務服務-彩虹橋這條鏈路必然會出現一半節點跨區訪問。
  • 彩虹橋叢集按照業務域劃分,彩虹橋叢集所屬業務域的 RDS 大多數都會跟彩虹橋叢集同區。比如彩虹橋交易叢集為i區,歸屬交易叢集的邏輯庫掛載的 RDS 大多數也都是i區。

主要痛點

  • SLB 頻寬已達瓶頸(5Gb/s,歷史上出現過多次 SLB 頻寬達到 100%的情況),目前彩虹橋單叢集掛載了雙 SLB 暫時解決頻寬瓶頸但仍存在痛點:
    1.SLB 擴容流程較複雜(配置監聽、配置虛擬伺服器組、監聽繫結虛擬服務組,配置排程演算法、更新域名解析的等),基於目前釋出系統能力無法實現全自動化。根據之前混沌工程演練結果,SLB 擴容流程需要30分鐘左右。
    2.SLB 擴容後,需要改域名解析,DNS 解析生效需要一段時間(域名 TTL 1 分鐘,本地快取10分鐘),新 SLB 需要10分鐘左右才開始逐漸承載流量,無法實現 SLB 快速擴容。
  • 單可用區故障時,需要人工操作切流到其他可用區叢集,SLA 難以保證(目前無法自動化判定單可用區故障,且叢集級別流量排程需要人工預估叢集負載,難以實現自動化切流)。
  • SLB 目前支援最低權重為1/100,粒度較粗,無法支撐釋出過程中的更小流量灰度需求。
  • Proxy 單個叢集所有節點均為同一個 AZ,需要與下游 RDS 保證同 AZ,跨叢集流量排程靈活性差,很難實現多可用區流量均衡(目前由於大部分 RDS 為 I 區,Proxy 多可用區流量非常不均衡:i區 90%/k 區流量 10%)。

五、自建後設資料中心&SDK 增強

圖片
後設資料中心獨立部署

  • 新增 Metadata 資料庫,多可用區部署(需要跟叢集中的 Proxy 同區)。
  • 新增 MetaCenter 服務,多可用區部署。
  • Proxy 連線所有 Metadata 資料庫,註冊&心跳都會寫入到所有資料庫。
  • MetaCenter 服務定時查詢所有 metadata 資料庫,基於心跳版本號和多個資料庫的並集篩選出健康的節點列表儲存到記憶體中。
  • MetaCenter 服務提供 API,查詢 MetaCenter 記憶體中的可用節點列表資料。
  • SDK 啟動時會去透過7層 SLB 訪問 MetaCenter 提供的 API 拉取節點列表並儲存到記憶體,執行中每隔 5s 更新一次。
  • MetaCenter 每次計算時如果有節點下線,透過 ARK 實時下發拉取事件給 SDK,SDK 會立刻重新拉取一次節點列表。
  • SDK 透過下發的節點列表做負載均衡,優先路由到同可用區的 Proxy 節點,其次按照節點權重輪訓。
  • SDK 輪訓間隔時間和節點變更事件下發開關均為可配置,實時生效。

架構詳解

Metadata 資料庫

圖片
節點表結構設計

  • beat_version:心跳版本號,只有上報心跳時會更新。
  • config_version:配置版本號,更新權重&狀態時會更新。
  • enabled:是否啟用
Proxy

節點啟動時

  • 註冊:啟動時會去所有 metadata 資料庫註冊當前節點,如果 node_info 不存在對應節點記錄,則新增,如果存在則修改權重為初始權重。
  • 啟動完成後需要呼叫 bifrost-admin 提供的呼叫節點啟用 API(釋出指令碼)

    update node_info 
    set weight = 1, config_version = #{config_version}
    where cluster_name = ? and address = ?

節點執行時

  • 心跳:定時更新所有 metadata 資料庫節點記錄的 beat_version 欄位

    update node_info set beat_version = beat_version + 1 
    where cluster_name = ? and address = ?

節點下線

  • 呼叫 bifrost-admin 提供的下線 OPEN API(釋出指令碼)
MetaCenter( Heimdall)

 * 啟動時
初始化心跳版本號:記錄所有 metadata 資料庫每個節點最新 beat_version 和初始化心跳丟失次數到記憶體
圖片

圖片

  • 執行時
    定時查詢節點資訊(3s 一次),篩選可用節點並寫入到記憶體中,提供 OpenAPI 給 SDK 呼叫,每個庫均執行以下操作,最終會得到每個庫的可用節點列表,最後把多個 list 求並集,得到最終的可用列表,寫入到記憶體中。

查出所有列表資料後,對比記憶體中的 beat_version 與資料庫中的 beat_version,如不相同則更新記憶體,如果相同說明對應節點心跳有丟失,如果丟失次數超過閾值,則剔除此節點。

節點列表中除了 ip、埠資訊外,還有權重,啟用狀態屬性, 這些屬性都屬於控制流變更,如果出現2邊資料庫不一致場景,以 config_version 最大的為準。
圖片
1.2.3.20節點與K區網路斷開
圖片
1.2.3.20節點當機

如果本次計算時有節點列表變化,會下發一個變更事件到 ARK(value 為時間戳-秒),SDK 在收到次配置變更後會立刻到 MetaCenter 拉取一次節點列表,以彌補定時輪訓的延時。

  • 兜底配置
    MetaCenter 提供的 OpenAPI 是透過計算後存入記憶體的資料,為了可以人工干預節點列表,需要支援開關一鍵切換至人工配置的節點列表資料。
    圖片
SDK( Rainbow) 
  • SDK 啟動時會去透過7層 SLB 拉取節點列表並儲存到記憶體,執行中每隔5s更新一次。
    如果拉取失敗,啟動時報錯,執行中不做任何處理,等待下次拉取。
    如果拉取的可用節點列表為空,啟動時報錯,執行時兜底不做任何處理,等待下次拉取。
  • 拉取的可用節點列表與記憶體中做對比,如果有節點被移除,需要優雅關閉對應的存量連線(如果被移除節點超過1個,則不做驅逐)。  
    當可用節點數量/所有節點數量 < X%時,忽略本次變更,不更新記憶體中的可用節點列表。
  • 拉取的節點資料會按照可用區進行分組,分為同可用區&跨可用區2個佇列負載均衡時優先從同 AZ 節點佇列中進行加權輪訓。  
    當同AZ節點權重總和/所有節點權重總和 < Y%時,同 AZ 節點優先策略失效,退化為所有節點加權輪訓。 
    當同AZ可用節點 < Z時,同 AZ 節點優先策略失效,退化為所有節點加權輪訓 。
  • 需要新增查詢節點列表的監控埋點&以上三種計算結果的埋點
    圖片
    另外 SDK 支援一鍵動態切換至走老架構方式(4層 SLB)
管理後臺
  • 新增頁面【節點管理】,用於查詢&管理節點
    圖片
  • 新增頁面【兜底節點管理】,用於管理兜底節點列表。
    圖片
  • 提供節點上下線 API,給釋出系統呼叫。

修改狀態會去所有 metadata 資料庫執行,只有一個庫成功就返回成功,如所有庫都修改失敗,則返回失敗。

update node_info 
set enabled = 0, config_version = #{config_version}
where ip = ? and port = ?
容災能力

表格中的是否有影響和故障恢復時間均指 SDK-Proxy 的訪問鏈路,Proxy-DB 鏈路不在範圍內。
圖片

  • 可用區i全部當機舉例

參考以下時間線,可在30s左右完成恢復。
圖片

  • i區 Metadata 資料庫故障,無影響。
    圖片

一些思考

Q:為什麼不用 sylas(得物註冊中心產品)做註冊中心,而是要自建後設資料中心做服務發現?

彩虹橋和 sylas 均為 P0 級別服務,對穩定性要求極高,在架構設計之初需要充分考慮到互相依賴可能帶來的級聯故障,在與註冊中心相關同學溝通後,決定自建彩虹橋後設資料中心,實現自閉環。

Q:為什麼不是傳統的基於 Raft 協議的三節點來實現服務發現,而是用多套資料來源做 merge?
Raft 是工程上使用較為廣泛的強一致性、去中心化、高可用的共識演算法,在分散式系統中,適用於高一致性、容錯性要求高的場景。但 Raft 協議需要維護領導者選舉和日誌複製等機制,效能開銷較大,其次 Raft 協議相對複雜,在開發、維護、排障等方面會非常困難,反之採用多資料來源求並集的方式更簡單,同時也具備單節點故障、整個可用區故障以及跨區網路中斷等多種複雜故障下的容災能力。

Q:如何在 SLB 切換到新架構的過程中保障穩定性?
可灰度:支援單個上游節點粒度的灰度
可回滾:支援一鍵動態切換至 SLB 架構
可觀測:大量埋點資料可實時進行觀測,有問題可快速回滾。
圖片

圖片

六、總結

自建後設資料中心後,將給彩虹橋帶來一系列收益:
應用服務透過 SDK 直接連線 Proxy 節點,擺脫了對 SLB 的依賴,解決了頻寬瓶頸和額外網路開銷問題,並提高了流量灰度控制的精細度。
簡化了擴容流程,擴容時只需增加 Proxy 節點大大縮短整個擴容時間。
多可用區容災實現自動故障轉移,無需人工干預。
SDK 具備了同 AZ 路由能力,更好適配雙活架構。

往期回顧

1.基於IM場景下的Wasm初探:提升Web應用效能|得物技術

2.供應鏈PC實操落地實踐|得物技術

文 / 新一
關注得物技術,每週一、三更新技術乾貨
要是覺得文章對你有幫助的話,歡迎評論轉發點贊~
未經得物技術許可嚴禁轉載,否則依法追究法律責任。

相關文章