技术分享:浅谈Service Mesh在瓜子的实践
作者 | zeyaries
過去三年,微服務成為業界的技術熱點,大量互聯網公司都在做微服務架構落地,新一代微服務開發技術悄然興起,Service Mesh 便是其中之一,該技術起初由 Linkerd 的 CEO William 提出,其中文翻譯為服務網格,功能在于處理服務間通信,負責實現請求的可靠傳遞。本文,瓜子效能團隊分享了在 K8S 的基礎上,通過 Sidecar 模式進行 Service Mesh 的實踐經歷。
一、背景??
起初,瓜子內部各業務線團隊為了方便、快速地開發后端服務,使用了各種傳統后端開發框架,順利保障各項業務上線。隨著時間的推移,瓜子的系統規模越來越大,架構復雜度也越來越高。為了更好的應對傳統開發方式帶來的挑戰,瓜子開始落地微服務化,后端項目不斷拆分。在這個過程中,微服務化給我們帶來了更好的靈活性、擴展性,良好的故障彈性以及不受技術棧限制等優勢。
但是,隨著瓜子業務的高速發展,業務開發范圍進一步增大,微服務的缺點逐漸暴露出來。綜合前期的技術框架以及微服務架構,主要存在如下不足:
當前通信框架過多、依賴版本眾多,維護及后續擴展存在諸多不便,比如加入 SSO 驗簽中間件、黑白名單中間件時,需要針對不同的框架進行開發,效率及維護都有很大挑戰;
前期框架在服務治理方面能力較弱,沒有服務注冊與服務發現,不便于后續微服務架構推行;
服務實例快速增長,請求在各服務間穿梭變得越來越復雜,每個服務出現問題都可能造成整個項目出現異常,并且不容易定位到具體問題,給運維加大了難度;
每個微服務都需要重復實現一些基礎功能,比方說鑒權管理、負載均衡、熔斷等,對代碼侵入性強,重復工作的同時提升后續技術替換成本。
根據上述不足,瓜子內部開始考慮實踐 Service Mesh,這給瓜子帶來了如下好處:
業務團隊更加專注核心業務邏輯和功能,不用過多關注基礎設施;
一套基礎設施能夠靈活支持多種語言的業務開發,很好的解決服務異構化程度較高的場景;
業務團隊與基礎架構團隊解耦,基礎設施與業務應用代碼解耦。
二、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,瓜子效能團隊一員,效能團隊致力于提升瓜子技術團隊的研發效率,為瓜子研發相關人員提供工具支撐。通過對前沿技術不斷地探索與研究,落地應用到實際中,幫助業務團隊提升交付速率以及交付質量。
總結
以上是生活随笔為你收集整理的技术分享:浅谈Service Mesh在瓜子的实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一条简单的 SQL 执行超过1000ms
- 下一篇: 一次服务器CPU占用率高的定位分析