技術分享:淺談Service Mesh在瓜子的實踐

過去三年,微服務成爲業界的技術熱點,大量互聯網公司都在做微服務架構落地,新一代微服務開發技術悄然興起,Service Mesh 便是其中之一,該技術起初由 Linkerd 的 CEO William 提出,其中文翻譯爲服務網格,功能在於處理服務間通信,負責實現請求的可靠傳遞。本文,瓜子效能團隊分享了在 K8S 的基礎上,通過 Sidecar 模式進行 Service Mesh 的實踐經歷。

一、背景

起初,瓜子內部各業務線團隊爲了方便、快速地開發後端服務,使用了各種傳統後端開發框架,順利保障各項業務上線。隨着時間的推移,瓜子的系統規模越來越大,架構複雜度也越來越高。爲了更好的應對傳統開發方式帶來的挑戰,瓜子開始落地微服務化,後端項目不斷拆分。在這個過程中,微服務化給我們帶來了更好的靈活性、擴展性,良好的故障彈性以及不受技術棧限制等優勢。

但是,隨着瓜子業務的高速發展,業務開發範圍進一步增大,微服務的缺點逐漸暴露出來。綜合前期的技術框架以及微服務架構,主要存在如下不足:

  1. 當前通信框架過多、依賴版本衆多,維護及後續擴展存在諸多不便,比如加入 SSO 驗籤中間件、黑白名單中間件時,需要針對不同的框架進行開發,效率及維護都有很大挑戰;
  2. 前期框架在服務治理方面能力較弱,沒有服務註冊與服務發現,不便於後續微服務架構推行;
  3. 服務實例快速增長,請求在各服務間穿梭變得越來越複雜,每個服務出現問題都可能造成整個項目出現異常,並且不容易定位到具體問題,給運維加大了難度;
  4. 每個微服務都需要重複實現一些基礎功能,比方說鑑權管理、負載均衡、熔斷等,對代碼侵入性強,重複工作的同時提升後續技術替換成本。

根據上述不足,瓜子內部開始考慮實踐 Service Mesh,這給瓜子帶來了如下好處:

  1. 業務團隊更加專注核心業務邏輯和功能,不用過多關注基礎設施;
  2. 一套基礎設施能夠靈活支持多種語言的業務開發,很好的解決服務異構化程度較高的場景;
  3. 業務團隊與基礎架構團隊解耦,基礎設施與業務應用代碼解耦。

二、Service Mesh 實踐

2.1 整體架構

作爲一種基礎設施,K8S 的 pod 天然可以支持多個 Container,能夠非常方便地運行 sidecar 模式。因此,我們決定在 K8S 的基礎上,通過 sidecar 模式進行 Service Mesh 實踐。

具體架構圖如下所示:

圖1 Service Mesh框架圖

在 Sidecar 部署方式中,每個應用容器都會部署一個伴生容器。對於 Service Mesh,sidecar 接管進出應用程序容器的所有網絡流量。

基於 sidecar,我們可以實現服務之間的調用攔截,服務之間的的所有流量都會經過 sidecar,並通過其進行轉發。所有 sidecar 組成了一個服務網格,再通過統一的地方與各 sidecar 交互,就能控制網格中的流量運轉。

2.2 gRPCx(Service Mesh 實現的載體)

我們採用 gRPC 作爲通信框架,在原生 gRPC 的基礎上,結合瓜子業務情況對其進行增強,幫助用戶更加方便的使用 gRPC 相關功能。同時,整合並收斂前期 web 框架,解決前期框架過多維護及擴展困難的問題。gRPCx 提供可插拔的中間件,用戶在使用過程中能夠方便地加入埋點、驗籤、鑑權、監控等功能。支持上下文穿透,gRPCx 能夠將 traceID、用戶 ID 等信息合併到 gRPC 請求中,一起發給服務端。另外,gRPCx 較爲完整地滿足服務開發及治理的基礎功能,包括優雅的服務註冊、發現及下線,服務端負載均衡及高可用等功能。基於服務註冊與服務發現,服務在 K8S 上部署時可以沒有域名,直接通過 IP 訪問服務,減少 DNS 服務的壓力。

gRPCx 是我們實現 Service Mesh 的關鍵所在,其框架如下圖所示:

圖 2 gRPCx 框架圖

gRPCx 相關組件可以被定義爲在微服務拓撲結構中處理各個服務之間通信的基礎設施層,不僅能夠幫助降低微服務體系結構的相關複雜性,同時也能夠提供服務治理等功能。

Registry:使用 ETCD 作爲註冊中心,用於服務註冊及發現;

gRPC server:使用 gRPCx 框架實現,用於提供業務服務功能;

gRPC bridge:與 gRPC server 通過 sidecar 的方式部署在 K8S 的同一個 pod 中,用於獲取 gRPC server 的服務信息,並將其註冊到 Registry 中。同時提供 HTTP 橋接功能,將 HTTP 請求轉換爲 gRPC 請求發送給 gRPC server;

gRPC proxy:作爲 gRPC 請求的入口,根據 gRPC 請求的服務信息在 Registry 中查找服務信息進行服務發現,然後將 gRPC 請求轉發到目標業務服務器,從而訪問 gRPC 服務;

gRPC gateway:作爲 HTTP 請求的入口,根據請求的服務信息在 Registry 中查找服務信息進行服務發現,然後將 HTTP 請求轉換爲 gRPC 請求發往目標業務服務器上,從而使得 HTTP 請求能夠訪問 gRPC 服務。

2.3 服務治理

基於 K8S 的 sidecar 模式,我們將複雜的服務治理從業務服務中分離出來,並將這部分功能放入到 sidecar 中進行處理。sidecar 中的服務代理提供諸如流量及熔斷控制、服務註冊與發現、監控、驗籤以及安全埋點等功能特性,開發人員在使用時只關注自己的業務功能開發即可。同時,通過 sidecar 與 gRPCx 結合的方式,我們實現了 gRPC 應用提供 HTTP 以及 gRPC 兩種訪問接口,使用起來較爲靈活。

2.3.1 HTTP 請求橋接

圖 3 gRPC bridge 請求橋接工作流程圖

基於服務調用方可以通過 HTTP 方式訪問 gRPC 服務,gRPC bridge 會將 HTTP 請求轉換爲 gRPC 請求,然後再發往 gRPC server。這種方式使 gRPC server 也具備提供 HTTP 服務的能力,方便需要使用 HTTP 請求的調用。

2.3.2 服務註冊

圖4 服務註冊工作流程圖服務發佈

gRPC server 使用 gRPCx 框架創建服務後,將提供服務信息獲取接口。我們基於 K8S 將 gRPC bridge 作爲 sidecar 與 gRPC server 部署在同一個 pod 中,gRPC bridge 通過配置信息獲取 gRPC server 的端口信息,然後監聽 gRPC server 服務信息獲取接口,當 gRPC server 服務啓動後,將服務信息註冊到 Registry 中。

服務下線

gRPC bridge 提供服務下線功能,當 gRPC server 服務停止後,其會從 Registry 摘除對應節點信息,並通過監聽 gRPC server 服務信息獲取接口,當 gRPC server 服務信息更新後,會更新 Registry 中對應節點的信息。

用戶能夠通過 Registry 的 web UI,方便查看其服務被註冊的具體情況。

2.3.3 服務發現

考慮到 K8S 的服務發現基於 DNS 尋址實現,部署到 K8S 上面的服務會生成一條 DNS 記錄指向其被分配的的 cluster IP,其他服務在通過 K8S namespace+ 服務名去調用服務。我們基於 gRPC 實現的服務發現的粒度更細,能夠使用具體接口(service name+method name)進行服務發現,並且支持 HTTP 與 gRPC 兩種調用的服務發現,使用起來更加靈活方便。而且服務發現會有降級策略,Registry 宕機後,服務發現將會基於內存中存儲的信息進行。因此,我們並沒有使用 K8S 的服務發現。

基於 gRPC proxy 的服務發現

圖 5 gRPC proxy 服務發現工作流程圖

當 gRPC 請求發往 gRPC proxy(該服務地址確定,後續不會發生變化)後,proxy 根據服務信息進行服務發現,獲取 Registry 中對應的服務地址,然後會將 gRPC 請求轉發到目標 gRPC server 上。

基於 gRPC gateway 的服務發現

圖6 gRPC gateway 服務發現工作流程圖

當 HTTP 請求發往 gRPC gateway(該服務地址確定,後續不會發生變化)後,gateway 根據服務信息進行服務發現,獲取 Registry 中對應的服務地址,然後會將 HTTP 請求轉換爲 gRPC 請求併發送到目標 gRPC server 上。

當服務部署多個實例時,gRPC gateway 跟 gRPC proxy 會採用 RoundRobin 負載均衡策略,最終路由到其中一個服務實例上。

2.4 健康檢查與容災

2.4.1 健康檢查

使用 gRPCx 框架創建服務後,gRPC server 將提供 heartbeat 的 gRPC 接口。我們的健康檢查是基於宿主機提供的 HTTP 形式的心跳檢查,將心跳檢查發送給 gRPC bridge,由 gRPC bridge 將 HTTP 形式的心跳檢查轉換爲 gRPC 形式的心跳檢查,gRPC bridge 並將 gRPC 的返回轉換爲 HTTP 的返回,發給心跳發起服務。

Liveliness

在服務啓動成功後心跳檢測間隔時間,如果檢測的 StatusCode 非 200 會自動重啓服務所在容器。

Readiness

屬性在服務啓動成功後心跳檢測間隔時間,連續 3 次檢查失敗後,會將當前流量摘除,應用不會重啓。當下一次檢測正常時,就會恢復流量。在滾動更新實例時,會先將其中一個老實例摘除流量並終止老實例,同時起一個新實例。在 readiness 檢測正常後,就會分配流量給新實例,同時更新下一個老實例。這樣就會保證流量不丟失。

服務關閉或者服務不可用時,gRPC bridge 會從 Registry 中摘除服務對應的相關信息;服務啓動或者可用時,gRPC bridge 會將服務對應的 IP 及 API 信息註冊到 Registry 中。

2.4.2 容災單獨

通過 gRPC bridge 服務主動探測也存在隱患,當 gRPC bridge 出現問題或者是 gRPC bridge 到 gRPC server 網絡存在問題時,其無法調用 gRPC server 接口,從而無法到 Registry 中更新與摘除相關服務。此時,我們通過一個獨立運行的 gRPC monitor 實例監控 gRPC server 服務的可用性,若 gRPC server 服務存在問題不可用時,gRPC monitor 會到 Registry 中摘除相關節點信息,調用方能夠及時感知服務下線,進一步保障服務註冊與下線功能的完整性。

Registry 採用的是 ETCD 集羣,隨着業務發展,服務進一步增多,Registry 的壓力會越來越大。由於 ETCD 使用 Raft 協議維護集羣內各個節點狀態的一致性,通過水平擴展 Registry 的節點數量來提升讀性能,但是會降低集羣的寫性能,這是我們後續需要優化的一個點。

圖7 Registry 不可用時, 服務發現工作流程圖

我們的服務發現採用本地內存緩存作爲降級方案,當 Registry 集羣完全宕機或者 Registry 集羣連接不可達時,不會影響服務的正常調用。此外,基於 ETCD 的 watch 機制,當 Registry 中的服務信息發生變化時,能夠及時更新內存中存儲的服務信息。

出於對系統穩定性及安全性考慮,我們在服務 sidecar 中的 gRPC bridge 加入了熔斷機制,當滿足一定條件後,gRPC bridge 直接將請求熔斷,並不會將請求轉發給 gRPC server,減輕了服務端壓力。接下來,我們會圍繞 sidecar 中的 gRPC bridge 擴展出更多實用功能,方便開發人員使用。

2.5 日誌與安全

圖8 日誌全鏈路追溯示意圖

在微服務架構中,隨着服務數量的增多,各節點之前的調用關係變得越來複雜,對我們查找問題帶來了挑戰。我們有時會爲了追溯一個問題,統計幾個甚至幾十個服務日誌信息,然後再進行問題查找,這樣使用起來非常不方便,不能快速、準確的定位問題。gRPCx 框架服務在其他服務調用請求傳入時就可通過 gRPCx 中間件自動加上標籤 (traceID,如果傳入的請求已經存在標籤,則後續使用已存在的標籤),該 traceID 與請求一起傳入到後臺服務中,後臺服務從 context 中獲取該 traceID,與瓜子日誌組件聯合使用,在日誌收集時自動加上 traceID,方便追蹤全鏈路上與該請求相關的調用。如果涉及到多個服務之間的調用,通過該 traceID 能夠很好地串聯請求調用鏈,使開發人員非常容易的進行問題查找及追溯,減少與微服務結構相關的複雜性。

同時,基於 gRPCx 中間件,方便實現鑑權、驗籤、安全統一埋點等功能。我們在中間件提供了鑑權、驗籤等功能,統一接入瓜子 SSO,避免開發人員在業務代碼中重複加入這些功能,將鑑權、驗籤等功能從業務代碼中剝離出來,減少與業務代碼的耦合,讓業務代碼更加乾淨。基於中間件,可以方便地進行安全埋點,將請求數據中需要收集的信息發送至 Kafka,並通過 Kafka 存入 Hive,方便後續分析使用。

三、總結與展望

在 K8S 的基礎上,瓜子通過 sidecar 模式,使用一個與主服務獨立的代理服務(使用 gRPC 與主服務進行通信),讓服務之間的通信更加簡單、高效。在 sidecar 中運行的 gRPC bridge 不僅能夠提供業務之外的功能,比如路由、監控、日誌收集和訪問控制等,而且還能作爲一個透明的基礎結構層,存在於微服務與外部網絡之間。在 gRPC bridge 的幫助下,一套 gRPC 服務代碼能夠同時提供 HTTP、gRPC 的服務接口,方便開發人員使用,也方便將業務拆分。調用方使用 gRPC gateway、gRPC proxy 能夠更加方便、快捷的調用各個微服務,再輔以鑑權、驗籤以及安全埋點等中間件,配合可靠的全鏈路日誌追溯、優雅的服務治理、成熟的健康檢查機制等,瓜子整個微服務體系變得更加完善。

現階段,瓜子的 Service Mesh 實踐還處於起步階段,存在諸多不足。未來,瓜子將結合複雜的業務環境,在不斷完善現有 gRPCx 生態的基礎上,圍繞 Service Mesh 開展工作,例如,更加完善的微服務監控體系、故障注入和容錯、高級服務路由。服務熔斷與降級、更加完備的容災、高可用策略等,降低單個應用自身複雜度,並在 K8S 的支撐下,簡化部署、管理、監控、維護等較爲繁瑣性的工作。我們的開發人員只用在此基礎上享受基於 gRPCx 生態的 Service Mesh 帶來的使用便利。

作者介紹

zeyaries,瓜子效能團隊一員,效能團隊致力於提升瓜子技術團隊的研發效率,爲瓜子研發相關人員提供工具支撐。通過對前沿技術不斷地探索與研究,落地應用到實際中,幫助業務團隊提升交付速率以及交付質量。

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