AfterShip 億級流量 API 網關的演進

API Gateway 是隨 “微服務” 概念而興起的一種架構模式,原本一個龐大的單體應用系統被拆分成許多微服務系統並行獨立維護和部署,服務拆分帶來的變化是 API 規模成倍增長,所以使用 API Gateway 發佈和管理 API 逐漸成爲一種趨勢。

AfterShip 是一家業務和團隊遍佈全球的電商 B2B SaaS 公司,從 2012 年成立至今,AfterShip 已經與全球 800 多家物流公司,包括 Amazon、 Microsoft、 Wish、 eBay、Shopify、迪卡儂在內的 10 萬家客戶達成了合作,成爲了連接物流公司和電商平臺的橋樑,並進入了全球 200 多個國家地區。AfterShip 從成立至今,共發佈了 10 多款 to B 產品和 2 款 to C 產品,並且已經初步構建完成了電商 SaaS 產品矩陣。AfterShip 系統整體基於微服務架構之上,隨着越來越多新的產品發佈,及其產品之間的依賴越來越多,在服務治理上也面臨越來越大的挑戰。在此基礎上 AfterShip 期望引入統一的 API Gateway 來解決 統一鑑權、版本管理、灰度、流控、降級等一系列問題,同時也期望兼具有更好的擴展能力以應對特殊定製的需求。

AfterShip 最終選型使用 Kong 作爲 API Gateway 方案。業務研發人員通過配置,即可簡單對外開放功能和數據,無需在每個業務系統都實現通用的 API 管理功能,能更聚焦在業務邏輯本身。下面將進一步介紹 AfterShip API Gateway 的誕生和演進過程。如何兼顧效率和穩定性,平衡功能複雜性和系統性能,並向雲原生架構進行演進。

1. AfterShip API Gateway 需要解決的問題

1.1 服務治理訴求

基於微服務的架構,降低了服務的耦合度,但也增加了服務管理的難度。基於這樣的架構考慮,有一個全局的入口來統一管理這些服務的訴求就越來越大。

在業務發展的早期,AfterShip 的鑑權、流控等基礎能力是在每個業務服務中單獨實現,但是隨着業務的不斷髮展及其更多新的業務產品的出現,系統面臨越來越大的挑戰。作爲服務全球客戶的電商 SaaS 公司,安全、合規及其隱私保護方面一直被我們高度重視。我們通過了 ISO 27001 認證體系,並且也在嚴格遵循 GDPR 和 CCPA 相關的規範要求。我們需要有更好的機制來統一管理 API,在更好服務業務的同時,也儘可能多的規避潛在的安全風險。

 注: 引用自(https://github.com/Kong/kong)

1.2 服務暴露的痛點

公司的第一款產品 AfterShip 於 2012 年正式發佈上線,隨後陸續發佈了 10 多款產品,to B 和 to C 的產品均包括在內。系統也經歷多次的迭代演變,同時也由於有一些歷史原因,整體的的服務管理方式不太統一。

南北流量

早期因爲歷史包袱的問題,南北流向的服務暴露的管理方式不太統一:

東西流量

之前服務之間的 API 調用整體也不太統一,有通過 K8S Service 的,也有通過 GCE Ingress 暴露的,授權方面也是通過服務自定義的鑑權方式 。

這種方式的問題,主要是行爲不太統一,導致不太好做自動化授權。無論是服務提供方還是使用方,都需要關注服務的鑑權問題,嚴重影響開發效率。同時,服務的接入和監控層面都面臨不少挑戰。比如想知道當前服務被哪些服務所調用,比如想做一些 RateLimit 等的策略,這些服務治理方面的就比較難得到支持。

2. AfterShip API Gateway 整體架構

2.1 爲什麼選擇使用 Kong

AfterShip API Gateway 需要考慮能夠支撐:

AfterShip 自 2019 年初開始做網關,當時開源主要是有幾個方向,基於 Nginx 的 OpenResty,Envoy ,還有基於 Go 實現的網關 Tyk 等。

因爲 Nginx 性能較好,服務穩定,擴展能力不錯,且公司團隊對 Nginx 有比較豐富的維護經驗,所以更偏向於基於 OpenResty 相關生態的開源解決方案。

行業基於 OpenResty 有幾個開源項目:

2.2 基於 Kong 改造後的 API Gateway 架構

南北流量

我們將原來 Nginx SideCar 的方式,替換成統一的  Kong + GCE Ingress 方式暴露。同時提供多種鑑權方式:對應不同端和使用方,提供不同的鑑權和接入方式。

一個服務若想暴露 API 給外部使用,只需遵守對應的 API 規範便可。這樣既可減少開發一層 API Service,又能通過擴展,保證統一鑑權和用戶的登錄狀態。

東西流量

AfterShip 暫時沒有引入 Service Mesh 的方式,而是使用 Kong 的 Keyauth 做統一鑑權。對 AfterShip 而言,痛點是統一的鑑權方案和 API 服務治理能力,同時需要兼顧服務的改造成本和維護成本等。

2.3 穩定性保障實踐

API  Gateway 的 HA 機制

 

使用 GCE Ingress Load Balancer 接入流量,處理 TLS 的接入,可減少 Kong 處理 TLS 性能損耗。通過 GCP 給提供 NEG 的方式,可直接連接到 Kong 實例的 Pod IP,減少一層  iptables 轉發。同時穩定的接入層,可在 Kong 異常的時候發現問題,GCE Ingress Load Balancer 也是主備的架構,當出現問題的時候,可以通過工具腳本直接起到另一組實例。

多 AZ 部署 Kong , 同時通過 ClusterIP 的方式,代理到後端的服務。發佈時,可通過灰度發佈的方式,慢慢更新 Kong 實例。我們啓用時,還沒有 Kong Ingress Controller,直接採用了 ClusterIP 的方式。當然了,這塊如果量比較大的場景下,還是會有 iptables 性能上的問題,不過可以方便做調整。

根據不同業務做集羣隔離,不同端做不同實例的部署,防止單個業務的異常引發所有服務的不可用。

Kong 支持故障自愈,服務端接入了彈性伸縮模塊,可根據 CPU 流量等指標進行快速擴容。除此之外,還支持快速摘除問題節點,以及更細粒度的問題組件摘除。

灰度流量

注: 引用自(https://argoproj.github.io/argo-rollouts/architecture.html)

目前結合 Argo Rollout 做灰度流量的支持,可通過多個 Deployment 的方式控制 Pod 的數量來控制流量比例,也可在 API Gateway 裏支持基於按流量比例灰度的場景。

服務監控與日誌管理

我們通過結合多種監控策略來確保監控的完善性:

而告警方面,我們通過整合 PagerDuty(https://www.pagerduty.com/) 來作爲我們的告警服務。

2.4 擴展性與易用性

自定義 Kong Plugins

Kong 默認自帶的插件集,按照功能的不同大致可以分爲六大類:

Kong 除了提供衆多開箱即用的插件外,且有易於擴展的自定義插件接口,用戶可使用 Lua 自行開發插件,同時支持 Go 插件的方式。但我們測試發現 Go 開發插件時性能並不好,主要是它通過 hook 到 Go Server 上做協議解析時比較消耗性能,所以我們基本還是用 Lua 進行自定義插件的開發集成。

我們自定義了插件,去支持較特殊的流控機制、JWT 鑑權機制、簽名驗證機制、協議轉換機制、API Logging 等等。

權限管理平臺

每個服務都有自己的 API Key,一般服務可通過 API Key 訪問,但還是需要服務授權才能被訪問。AfterShip 開發了自助的 Access Platform ,服務可申請訪問權限,只要服務的提供方審批通過,就可以。

爲了保證安全性,所有的訪問都有對應的審計日誌,關聯到網關的 Access Log。

3. Kong 的一些實踐經驗

3.1 基於 Kong 所面臨的問題

Konga 的權限問題

目前社區 Dashboard  Konga 在權限設置做得較粗,沒法控制到 Service 級別。企業版有一個付費的 Dashboard,但收費較貴。所以我們根據自己的權限體系,開發了一個後臺系統支持 Service 級別的權限管理。

Prometheus Plugins 性能

早期版本 Prometheus Plugins 的性能不太好,同時支持的 Metrics 的指標也不夠多。我們通過擴展 HTTP Log Plugins 的方式,以類似 Log By Metrics 的方式,實現了 Metrics。

Admin 接口的保護

Admin API 接口這塊,官方鏡像沒有做保護,要暴露到內網,需添加一個鑑權的方式。

防止直接訪問 SVC

爲了防止服務調用跳過網關,直接通過 SVC 的方式訪問服務,可以使用 K8S NetworkPolicy 的方式:

內網和外網網絡隔離

因爲 Kong 本身擴展較多,但會帶來一些潛在的安全隱患,要做好網絡隔離以避免安全問題。如通過 IP 白名單,防止因內部漏洞引發的安全風險。

3.2 Kong 配置管理和快速暴露 API

AfterShip 當前沒有使用 Ingress 的方式,因早期引入 Kong 時還不支持。現在引入對架構調整較大,社區有幾個工具可以做配置管理 Deck + Konga。

在較早期時,AfterShip 基於 Deck 這個工具做了擴展去管理配置,主要是擴展了基於 Service 級別劃分文件,基於環境區分目錄。好處是修改時,比較容易看出做了哪些修改,以及做 diff 配置,同時通過模板和腳本的方式,快速暴露 API。

Konga 主要是給業務看相關的配置和規則,這是因爲 Konga 不太好做基於 Service 的權限管理。後續爲了滿足服務的需求,我們做了進一步優化,基於 Service 維度的權限管理平臺,這樣業務就可以快速管理部分插件,如 RateLimit 和 Ban 等策略。同時通過包裝一層的服務暴露的自助平臺,幫助業務暴露服務。

3.3 如何對 Kong 進行性能優化

雖然 Nginx 本身有着不錯的性能,但 Kong 在 Nginx 之上擴展了很多插件,容易引入性能問題。下面介紹對 Kong 性能分析和優化的幾種方式。

方式一:Perf

如果是 C 語言層面的性能定位,可用 Perf + 火焰圖的方式,工具幫助我們去排查問題。需要特別注意,編譯參數上需添加一些符號表的編譯參數 -g -o0,不然會出現顯示不了函數名,要自行計算服務號位。

方式二:SystemTap

OpenResty 提供了 openresty-systemtap-toolkit, stap++ 兩個工具可以動態的 trace Nginx 和解析 LuaVM 的 Stack。不過這兩個工具都是基於 SystemTap,原理也是通過編譯 Linux 動態內核模塊的方式加載到系統上跑,對環境有不少的依賴,需要內核的 debuginfo。

方式三:eBPF

基於 Linux 內核的 uprobes or kprobes 機制, 可通過 kubectl trace 的方式注入到宿主機中運行。但如果需要 Profile Lua 的堆棧,需自己寫代碼去解析 LuaVM 的一些堆棧。

方式四:OpenResty XRay

注: 引用自(https://blog.openresty.com.cn/cn/lua-cpu-flame-graph/?src=xray_web)

通過 Openresty XRay 可以比較容易獲取到 Lua 的堆棧,同時分析內存使用的模塊做進一步的優化。

總結

AfterShip 基於 Kong 構建了 API Gateway,架構在一定程度上滿足了現有業務需求。我們也逐步聚焦在解決 API 如何更好的治理方面,及如何做到更好的安全和穩定保障方面。

Kong 有着活躍的社區,不錯的擴展能力,不過它也有一些不足。隨着業務發展,以及 Cloud Native 技術的演進,我們也持續在做相應的架構演進,同時也在逐步推動回饋開源社區,爲開源社區做更多的貢獻,相互的促進。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KBCN2-6lSGJC9fTtSTGr3A