希沃 API 閘道器架構演進之路

語言: CN / TW / HK

本次內容來自我們團隊同學簡海青(視源股份運維負責人)在 APISIX 沙龍上的分享。

閘道器往期迭代與痛點

希沃閘道器的發展經歷了四個版本的迭代。2013 年公司開始嘗試網際網路業務,那時候採用了 OpenResty+NGINX 靜態配置的方式搭建了最初的閘道器,開發人員通過 SCP 來發布。與此同時一個比較嚴重的問題就是,每次上線釋出都需要運維人員的協助才能保證平滑上線。

隨著業務的發展和人員的擴充,2016 年我們開發了第二代釋出系統和相關迭代閘道器。這次是基於 OpenResty 集成了 upsync 模組,同時配合 Consul 來進行服務發現。第二代的系統解決了上一代開發人員無法獨立釋出上線的問題,但仍需要運維協助才能進行擴容。

之後公司業務開始了迅猛發展,開始對閘道器以及產品的彈性擴縮能力有了更高的要求。2018 年我們基於 K8s 開發了第三代系統。考慮到仍有部分應用遺留在陣列機上,所以整個閘道器架構是在 K8s 上使用 Ingress NGINX 來當作第二層的閘道器,第一層閘道器仍是 OpenResty 配合的雙層閘道器架構。這種情況下雖然解決了前代釋出擴容等自助問題,但又引入了新的麻煩。

業務的快速擴充致使對於整體穩定性的要求越來越高。採用這種雙層閘道器架構後,一層 NGINX reload 和二層閘道器的路由變更,都會造成長連線斷開。這對於一些長連線使用場景,比如軟體對老師的授課狀態獲取就會斷開,從而影響授課過程。

從上圖的閘道器流量拓撲圖可以看到我們前文提到的雙層閘道器架構,本身雙層架構就會帶來成本層面的一些增加。在雙層閘道器架構下,目前都會出現 reload 變更的場景,不管是在第一層閘道器新增域名、修改配置或者新增一些特殊規則等,都需要 reload NGINX。

同時從整體架構來看,元件的配合對於流量控制層面來說比較差。尤其是目前我們的業務使用者體量已達到千萬級別,一旦客戶端出現不可規避的異常,就有可能出現侵蝕服務端的情況,這種時候如果在閘道器層面沒有一定的流量控制能力,對於後端來說將會造成非常嚴重的雪崩。

因此,基於上述迭代遺留問題和架構痛點,在 2022 年我們引入了 APISIX 來解決上述問題。同時藉助 APISIX,也加強了在閘道器層面對於流量的控制能力。

但是在遷移 APISIX 的過程中,也會存在一些已知挑戰。比如:

  • ⼀層 NGINX 域名多,定製化規則複雜。目前我們的業務中有 700+ 域名,同時還存在非常多的定製化配置,比如重定向、黑⽩名單等,這些都需要適配 APISIX 的外掛。
  • 由於歷史遺留問題,⼀層 NGINX 和⼆層 Ingress 閘道器還是⼀對多的關係,對於後續的流量切換是不是會很複雜,這也是一個待解決問題。
  • 內部存在的雙層 DNS 架構。目前 DNS 解析主要用於處理公網和伺服器內部的解析,所以對於後續的方案我們更希望是一個能方便回滾同時可以優化內網呼叫效能的。

遷移 APISIX 後架構調整

面對上述已知的挑戰,在遷移過程中主要進行了以下三個角度的操作。由於整個遷移過程沒有涉及研發內容,所以全部都是由運維人員實施的。

在遷移過程中,首先要做的就是 APISIX 路由的生成。基於原本的架構,我們去掉了一層特殊功能,比如 rewrite、set-header 等。弱化一層閘道器的轉發,把所有功能都集中在二層的 Ingress 上,然後基於 Ingress 去生成 APISIX 的路由。同時在 NGINX 配置的基礎上,需要去適配 APISIX 的外掛。

路由生成後,就需要去校驗整個轉發過程是否正確。我們基於 goreplay 的錄製回放來驗證路由轉發的正確性,同時通過自動化指令碼來驗證外掛功能是否正常。在功能校驗通過的情況下,我們會繼續驗證 APISIX 在效能層面是否滿足內部需求。因此,在效能壓測過程中我們自研了 elastic-apm 外掛,同時針對部分影響 QPS 的外掛進行了效能優化。

處理完功能跟效能相關的問題後,最大的挑戰就是流量切換了,因為流量切換將直接關乎生產質量。

雖然前邊我們已經使用了 goreplay 進行流量錄製回放,但我們仍然需要一個比較可靠的回滾方案。假設流量切換造成了異常,比如轉發異常或者是 APISIX 出現崩潰時,能夠進行快速回滾操作。基於此,我們首先切換了公網流量,因為公網是通過 WAF 回源到 SLB 來進行流量切換的,這時如果我們切換到 APISIX,就可以很方便地去修改回源地址來將整個流量進行回滾,如上圖標註「切換」字樣所示。這個異常情況下的流量切換過程基本是在秒級別,可能 10 秒內就把所有流量都切回來了。

完成了公網流量切換的情況下,順利運行了幾天,我們就通過 APISIX 將內網流量也進行了變更,然後整個生產上的切換就全部完成了。但是這個上線過程中,其實我們還是遇到了一些問題的。

遷移過程中的問題與解決方案

Prometheus 外掛轉發延遲

這個是在我們內網測試環境中發現的一個問題。由於我們的內網是 all-in-one 的測試環境,所有部門都使用同一個 APISIX 的入口,所以路由規則非常多,達到 4000+。這樣就會導致每次拉取 Prometheus 外掛時, metrics ⼤⼩達到 80M+,造成單個 worker 程序跑滿,從而造成 worker 的轉發延遲。

這個問題是目前 APISIX 開源版本存在的一個現象,主要是因為業務流量和內部 API 流量(比如Prometheus metrics 和 Admin API)都共用 worker 造成的。我們在之前是針對 Prometheus 外掛進行了修改,其中延遲相關的metrics 佔用了90%以上,我們將這部分採集去掉了,還是滿足我們業務的監控需求。

不過最近我們針對這個問題又有了新的方案。這套新方案是對 Nginx 原始碼進行修改,通過多啟動⼀個或多個 worker 程序(isolation process) 來專⻔監聽特定端⼝(比如 Prometheus、admin、control 等),不監聽處理正常業務端⼝請求。其它的 worker 程序則取消監聽上述特定埠,只處理正常業務端⼝請求,來確保 APISIX 內部請求和正常業務請求不會互相影響。

詳細的文章可以參考:如何修改 Nginx 原始碼實現 worker 程序隔離

預設路由匹配異常

在上線 APISIX 後,我們發現域名並沒有走精確匹配模式,而是採用了萬用字元匹配,這跟 NGINX 的域名最長匹配是不一致的。為此,我們通過更換路由策略,將 URL 方式改成了 host+URL 的方式,解決了該問題。

但關於 APISIX 基於 URL 路由策略作為預設路由的問題,大家可以在自己的生產環境中進行壓測後再決定是否保留。

假如你的生產場景中屬於 URL 特別多、域名特別少的型別,那 APISIX 這種預設路由策略是完全 OK 的。但在我們的業務場景下,並沒有這麼多 URL,所以採用 host+URL 的方式是更滿足我們的效能需求。

預設自動綁核問題

在雲原生的背景下,大部分使用者都會選擇將 APISIX 部署在容器中使用。但 APISIX 在預設配置下會進行自動綁核,這樣就會導致在容器化場景下,可能只會用到前幾個核心,造成前幾個核心跑滿而後幾個核心仍處於空閒的狀態。雖然 CPU 使用率不高,但APISIX轉發會出現延遲。

不過 APISIX 社群最近已經開始調整這個配置,將 worker_cpu_affinity 配置的預設值從 true 改為了 false。因此這個問題目前在 APISIX 版本中已經解決了。

版本升級相容問題

在上線 APISIX 的過程中,我們還發現在較老的系統或 OpenSSL 庫中,它的 ssl_ciphers 和服務端預設值⽆交集,從而造成 SSL 握手失敗。

針對這個問題,我們建議大家在上線 APISIX 之前,先通過一些 SSL 工具先去探測一下當前舊閘道器與 APISIX 閘道器的 SSL 握手交集是否正確或滿足使用場景,然後再進行規模化的遷移調整。

除此之外,在 APISIX 釋出 2.15 LTS 版本後,我們就在內網進行了升級,但是升級後就發現了一些路由匹配相關的問題。

因為從舊版本升級到新版本時,存在一些相容性問題,導致 redirect 外掛引數 http_to_https 為true 時,引數 http_to_https 和 append_query_string 校驗失敗,進而路由載入失敗,導致路由丟失。這種情況下就會在路由匹配時出現 404 或者轉發到其他上游的情況。

目前這個問題已經在 APISIX 的 master 分支中解決了,但是並沒有針對 2.15 版本進行單獨解決,所以大家在使用該版本時也需要留意這部分問題。

應用 APISIX 的收益及展望

雖然前邊提到了一些我們在上線 APISIX 過程中遇到的問題,但是在應用 APISIX 之後,給公司業務層面還是帶來了很多價值的。比如:

  • 運維效率提升。使用 APISIX 後,再也不存在 reload 相關的煩惱,可以做到隨時更新路由和證書等,給開發人員帶來了操作上的便利。
  • 流量控制能力提升。使用 APISIX 後,我們在熔斷和限流方面都得到了提升,穩固了整個核心流程。
  • 自研外掛,增強閘道器能力。得益於 APISIX 的強拓展性和自身外掛效能的優異,我們也會更主動地去開發一些外掛。比如我們在 APISIX 上集成了統一鑑權的能力,新業務⽆需單獨對接鑑權系統,加快了產品迭代流程。

  • 去掉了冗餘的一層 NGINX,實現降本增效。之前的雙層閘道器架構中,一層的 NGINX 對於開發人員並不透明。現在將雙層網關合併為一層後,開發人員可以很清晰地看到整個架構的路由、外掛等配置,對於排查問題來說更加方便快捷。 在後續使用 APISIX 的規劃中,我們還是會繼續在閘道器層面進行增強。比如開發針對內部業務的自研外掛,提供多租戶的能力,或者是將 API 管理的功能帶到閘道器層面等等。

當然在這個過程中,我們也在積極回饋社群。目前已在社群中貢獻了 8 個 PR,幫忙完善和修復了一些生態外掛相關的問題。比如完善 batch_request ⽀持⾃定義 uri、為 hmac-auth 外掛提供請求 body 校驗等功能。

希望在後續的實踐過程中,我們可以更全面地去使用和發揮 APISIX 的特性,同時也會更加積極地去探索 APISIX 的使用場景,也非常期待未來有更多的共建功能上線。