王院生:Apache APISIX 微服務閘道器極致效能架構解析
2019 年 10 月 27 日,又拍雲聯合 Apache APISIX 社群舉辦 API 閘道器與高效能服務最佳實踐丨Open Talk 杭州站活動,Apache APISIX PPMC 成員王院生做了題為《 Apache APISIX 微服務閘道器極致效能架構解析》的分享。本次活動,邀請了來自阿里巴巴、螞蟻金服、Apache APISIX、PolarisTech、又拍雲等企業的技術專家,分享閘道器和高效能服務的實戰經驗。
王院生,深圳支流科技創始人,Apache APISIX PPMC 成員,OpenResty 社群發起人,《 OpenResty 最佳實踐》作者。
以下是分享全文:
前言
大家好,我是來自深圳支流科技的王院生。今年 3 月份,我和志同道合的夥伴一起創業,發起了 APISIX 專案,目前這個專案已進入 Apache 孵化器。Apache APISIX 是一個高效能、可擴充套件的微服務 API 閘道器。它是基於 Nginx 和 etcd 來實現,和傳統 API 閘道器相比,APISIX 具備動態路由、外掛熱載入、gRPC 協議轉換等功能,特別適合微服務體系下的 API 管理。
Apache APISIX 是一個蓬勃發展的開源專案,在 2019 年 6 月 6 號開源後,很快就獲得了開發者的關注和興趣,並在開源一個月後被收錄到 CNCF(雲原生軟體基金會) 的全景圖中。現在 Apache APISIX 在 GitHub 有 1500 多個 star,近40 多名貢獻者,是一個聚集了 800 多人的開發者社群。從開源之初,APISIX 保持每個月釋出一個版本,並堅持測試驅動開發、自動化 CI/CD 等理念,以保證程式碼的質量和穩定性。
Apache APISIX 微服務閘道器
微服務 API 閘道器
API 閘道器並非一個新興的概念,在十幾年前就已經存在了,它的作用主要是作為流量的入口,統一處理和業務相關的請求,讓 API 更加安全、快速和準確的得到處理,它有以下傳統功能:
- 反向代理和負載均衡,這和 Nginx 的定位和功能是一致的;
- 動態上游、動態 SSL 證書和動態限流限速等執行時的動態功能,這是開源版本 Nginx 並不具備的功能;
- 上游的主動和被動健康檢查,以及服務熔斷;
- 在 API 閘道器的基礎之上進行擴充套件,成為全生命週期的 API 管理平臺。
最近幾年,業務相關的流量不再僅僅是由 PC 客戶端和瀏覽器發起,更多的來自手機、IoT 裝置等,未來隨著 5G 的普及,這些流量會越來越多。同時,隨著微服務架構的結構變遷,服務之間的流量也開始爆發性的增長。在這種新的業務場景下,對 API 閘道器有了更多新需求:
- 雲原生友好,架構要輕巧,便於容器化;
- 對接 Prometheus、Zipkin、Skywalking 等監控元件;
- 支援 gRPC、Dubbo、websocket、MQTT 等協議的代理,以及 http 到 gRPC 之間的協議轉換,以便適應更廣泛的場景;
- 做身份驗證,與 Auth0、okta 等身份認證提供商的服務對接,把流量的安全作為頭等大事;
- 通過執行時動態執行使用者函式的方式來實現 serverless,讓閘道器的邊緣節點更加靈活;
- 支援外掛的熱載入,新增、刪除和修改外掛,都不用重啟服務;
- 開源不鎖定使用者,支援混合雲的部署架構;
- 最後是閘道器節點自身要無狀態,可以隨意的擴容和縮容。
有了這些功能,微服務只需關心業務本身,而與業務相關的周邊管理功能,比如服務發現、服務熔斷、身份認證、限流限速、統計、效能分析等,均可以在獨立的閘道器層面解決。從這個角度來看,API 閘道器既可以替代 Nginx 的所有功能處理南北向的流量,也可以勝任 Istio 控制面和 Envoy 資料面的角色,處理東西向的流量。
目前已經有很多可選的閘道器產品,為什麼我們還要進入這個行業進行摸索?我們對現有的產品進行了分析:
- ⾏業老大:大多基於 Java + JS,閉源效能差,不支援⼆次開發
行業老大們的技術方案大多基於 Java + JS 無一例外,因為他們都是十幾年前起步,倒退到那個年代能選的方案也只有 Java 。如果阿里是現在才起步的,我相信他也會有不同的技術選擇,但是在那個年代做大應用,只有 Java 可選。如果要做動態,基本也就只有 JS 這條路,最後的組合均為 JAVA + JS 技術方案。它的問題也比較明顯:效能差,體態臃腫,二次開發較困難。
- 行業遠見者:多基於 OpenResty 或 Golang,少數開源
在 Ganter 中遠見者行列採用的技術方案目前多是基於 OpenResty 和 Golang,能夠看到這些行業遠見者在具體實現上,整體都比較重。程式碼量重往往代表結構複雜,最後也發現他們確實效率不高。
- Apache APISIX 機會:輕巧 + 極致效能 + 熱外掛
在起步之初,我們意識到必須要比遠見者還要好十倍以上,我們才有成功的可能。此時我們看清了要走的一條路:第一要輕巧,第二需要效能極致。最後如果再有豐富的外掛生態,就更完美了。
Apache APISIX 發展歷程
4 月初,我們開始第一行程式碼,我們選擇在 6 月 6 日開源,因為產品名叫 APISIX,我們希望它容易被大家記住。
7 月,APISIX 進入 CNCF 全景圖,這是目前最火的軟體基金會。
8 月,我們擁有了第一家商業使用者,搞定商業使用者的過程確實非常爽,藉助 APISIX 核心前兩週,就幫使用者把 QPS 提升了一倍。
9 月,開源使用者貝殼找房正式上線,現在每天至少有 1 億的流量需要處理(截止目前已經有 2.5 億日流量),它的 CPU 大約 1% 左右。
9 月我們也開始和 Apache 接觸,著手準備捐贈,10 月就真正成功了。這應該是國內第一家由初創公司捐贈的 Apache 專案。通常一個專案要進入 Apache 基本都是以年為單位,但我們只用了一個月。
10 月,我們在繼續奔跑,已實現了全平臺支援。除了常見的作業系統,兩大主流 X86 架構和 ARM64 架構也均全部支援,並經過完整用例迴歸。APISIX 是一個測試驅動的專案,測試覆蓋率到 80% 以上,只要測試用例能完整執行,可以確保在生產中正常使用。
Apache APISIX 的優勢
以下是 Apache APISIX 引以為傲的點,它們大多是是競品完全沒有的:
- ASF 第一個 API ⽹關類項⽬
- 極簡核⼼程式碼量,不到 4000 ⾏,去除空行、註釋行數甚至不到 3000 行
- 極致的動態轉發效能,測試報告顯示屬於 NO.1
- 最低的平均請求延遲:740 us
- 外掛熱載入/解除安裝,新舊外掛均可,同類競品中獨一無二
- 允許外掛掛載 Nginx 任何階段
- 所有的元件都是外掛,包括路由自身,這在業內是獨一份的,把自由交給使用者
- 完整支援 ARM64
- 完整支援 IPv6
- 動態轉發物聯⽹ MQTT 協議
- 執行時可以是 OpenResty / Tengine ,自由選擇
- 極致效能校驗器 iresty / jsonschema ,已知 jsonschema 校驗器實現方案中效能最高
Apache APISIX 技術選型
API 閘道器產品形態演化
如上圖所示,圖 ① 為閘道器最初的產品形態,左側是客戶端,右側是服務,閘道器在他們中間;由於服務會做聚集分類,如圖 ② 中服務分成兩類,此時 API 閘道器的重要性就體現出來,它需要對外做無感知,需要根據使用者請求的流量資訊做分發,此時 API 閘道器就會成為單點故障;由此演化出圖 ③ 的形態,有兩個 API 閘道器,它們都可以訪問後面的任何一個服務叢集,互為備份,是一個高可用的基本形態,客戶端可以請求任意一個閘道器;在圖 ④ 中,API Gateway 負責流量轉發,etcd 負責配置儲存,API Gateway 是管理人員的控制檯,所以如果只有 API Gateway 高可用是遠遠不夠的。
真正能夠讓使用者安心的方案應該是 API Gateway、配置中心、控制中心都能夠完整支援高可用,作為一個微服務 API 閘道器需要部署靈活,API Gateway、etcd、管理控制檯均需要滿足任意數量伸縮,需要多少就部署多少。
這對我們的開源版本提出了一個非常高的挑戰,安裝形態到底應該什麼樣子?
我們需要有上圖中的三種形態都允許使用者去部署:Admin、Gateway、Gateway+Admin。我們的解決方案首先是 All In One,即只有一個 “Gateway+Admin” 的包,當用戶需要將 Gateway 和 Admin 分別部署時,只需修改配置,是否啟用 Admin 就可以實現。
我們通過配置的方式簡單區分節點型別,而任何一個節點裡面,既可以單獨包含一部分,如 Admin 或者 Gateway,也可以同時包含二者,這種方式讓使用者能夠很容易地解決一堆問題,實現高可用、彈性伸縮、分散式、叢集以及故障自動轉移。
API 閘道器基本架構
下面介紹 API 閘道器的基本架構,這裡簡單對它做了拆分:
整個流程是管理員通過 admin API 告訴閘道器需要做什麼並儲存下來,這也就是我們常說的控制面。相對的是資料面部分處理外部使用者真實請求,要根據管理員的規則,對當前請求根據路由匹配得到配置,然後執行配置中的外掛並轉發到指定上游。
這裡涉及三個最基本問題:
- 路由:匹配使用者請求,需要功能強大,並且效能足夠好
- 校驗器:校驗使用者請求資料是否合法,需要通用、高效能
- 配置中心:儲存配置,高可用易用,支援增量訂閱
如果這三個基本問題回答好,那麼這個閘道器質量也就基本確定了。
Apache APISIX 技術選型
核心思路:技術選型時需要思考到底需要解決什麼問題?
- 配置中心:高可用、增量訂閱、歷史記錄
- 語言或開發平臺:動態、高效能、閘道器的周邊資源豐富
- 資料校驗:開放標準、有一定的生態系統
- 加分項:頂級路由實現
- 選型捷徑:學習競對,從 Ganter 報告中獲取前輩列表,做分析和比較,嘗試站在巨人肩膀總是對的
配置中心:etcd why?
APISIX 配置中心並沒有選擇傳統的關係型資料庫,而是選用了 etcd,當時主要考慮到以下要素:
- 優雅的叢集支援
- 支援歷史,可以獲取到歷史的修改記錄
- 要能夠支援事務,有些資料的存放是有條件的
- 低於毫秒級別的變化通知
通過分析發現 etcd 非常適合我們,當真正看到官方的 why etcd 的說明列表時(如下圖),我們就知道我們選對了。
語言和開發平臺:OpenResty
新選型 API 閘道器開發平臺基本只有兩條路,一個是Lua,即 OpenResty,另一個就是 Golang。Golang 是靜態語言,其動態能力不如 Lua ,所以最後選擇 OpenResty。我個人從 2014 年到現在一直沉浸在 OpenResty 社群,對它的理解和把控力也會更好。
我們是全新的專案,所以我們直接基於最新的版本來做,OpenResty >= 1.15.8,Tengine>= 2.3.2,二者都是基於 Nginx,搭配他們任何一個作為執行時都可以執行 APISIX。
我們需要藉助更通用的語言來吸納它的周邊生態,這方面 Lua 與 C/C++ 是不在一個量級,常見做法可以通過呼叫 C/C++ 的動態庫來這麼做。此外,也可以呼叫基於 Golang 的庫。從這個角度看,我們選擇 OpenResty 作為基礎平臺開展 APISIX 業務開發會很順暢,不用擔心周邊庫匱乏的問題。而且 OpenResty 這幾年被用在 API 閘道器比較多,有很多現成元件也可以利用,APISIX 可能只需要拿過來做二次整合。當然整合過程中也發現了一些專案的開源版本寫得不好,二次優化的事情也沒少幹。
資料校驗:jsonschema
jsonschema 的資料校驗規範 Google 排名第一,換而言之,如果有校驗規範且已經排名第一,我們沒有必要自己造一個,知識一定要可以複用,於是選擇了 jsonschema 這個標準。這個校驗標準幾乎涵蓋了 C、Java、JS 等主流語言,而且官方提供現成的壓測結果。我們任何選型都會格外關注效能表現,如果有現成的壓測框架和結果就非常棒。
當然,在實際操作中經歷了一些波折:最開始選型在 jsonschema 官方找實現,結果發現沒有適合我們的,他們大多都是開源庫中用了一點便聲稱支援,實際上耦合度比較高。
我們找到的第一個選型是 lua-rapidjson,它並不在 jsonschema 官方的推薦列表裡,是騰訊開源的。但 rapidjson 有一個比較大的問題是編譯條件高,它是一個 C/C++ 的實現,而我們做的是開源的專案,簡單易用是我們追求的。此外 rapidjson 只支援了 draft4 裡 95% 的內容,有些特性也不支援,比如經常用到的 default 。
於是我們根據一個開源的方案進行改造,實現了新的 iresty / jsonschema,主要增加了下面一些點:
- 執行時支援 OpenResty
- 完整支援 draft4
- 完整支援 draft6、draft 7
這個庫採用了編譯器的思維方式。我們對其進行了測試:一個簡單的物件裡面有兩個欄位,分別是字串和一個 int 型別,反覆進行迴圈壓力測試,跑一百萬次,將跑完的時間做比較。iresty / jsonschema 的效能是 lua-rapidjson 的 5-10倍,是 gojsonschema(golang) 效能的 500-1000 倍。
路由:為什麼造了 resty-radixtree 路由?
路由是 API 閘道器的生命,沒有高效能的路由,就沒有快速的匹配過程,API 閘道器的效能無法提升。只有路由是 100% 每次參與使用者請求的,配置中心和引數校驗也不是,因此路由必須要高效能。同時路由匹配條件也要足夠靈活和強大,除了要支援最基本的 uri、host,其他可選的如 IP 地址、請求引數、請求頭、Cookie 等也需要。
原本以為做到這一步就可以了,但開源專案的使用者還是會有其他的需求,最後我添加了自定義函式,使用者可以寫 Lua 指令碼,這也再次使用了 Lua 的動態特性。換而言之,使用者完全可以建立判斷規則,涉及特別不好表達或還未支援的邏輯,都可以用自定義函式方式先繞著走。
集大成者的路由 resty-radixtree,目前單核心每秒可以達到百萬次的匹配,相比之前的選型 libr3,radixtree 的效能至少提升了一個數量級。並且它允許引用任意的 nginx 的內建變數,索引的自由建立也讓它輕鬆支援 uri 或 host+uri 的使用場景。
自此三個選型確定:路由 resty-radixtree,校驗器 iresty / jsonschema,配置中心 etcd,Apache APISIX 雛形誕生。
Apache APISIX 架構
如上圖,這是 Apache APISIX 目前的業務架構:左側是管理員,右側是使用者請求。管理員把資訊錄入放到 etcd 裡面快取後,使用者訪問 APISIX 做路由,根據路由資訊得到結果,匹配到路由交給具體的微服務、serverless 等。
如上圖,APISIX 軟體層面基本架構並沒有採用傳統的層層巢狀的方式,只有基礎層和業務層,基礎層完全脫離於 APISIX 核心,完全無業務繫結,大家可以在任何 OpenResty 專案中引用。
外掛可以熱插拔,不用重啟服務。並且已經內建了常見的限流限速、身份認證、請求改寫、URI 重定向、opentracing、serverless 等外掛,開箱即用。APISIX 對外掛的支援和友商不太一樣,具體表現在以下幾點:
- 按需“繼承”
- 優先順序排序
- 允許掛載 Nginx 所有階段
- 外掛熱載入、解除安裝
- 外掛臨時禁⽤
總結 Apache APISIX 三板斧如下:
- 配置分發藉助 etcd ,精簡核心
- 基於 resty-radixtree 的高效能字首匹配
- 高效能基礎庫apisix/core:Nginx 變數提取增強 ;錯誤日誌優化;table 池優化
Apache APISIX 效能測試
Apache APISIX 目前已經具備 30 多個功能,已經基本超過大多開源競品。通常來說,引入了前面提到的幾十項功能,會伴隨著效能的下降,那麼究竟下降了多少呢?這裡我做了一個性能的測試對比。
如上圖,右側是我為了測試寫的一個虛假的服務,這個服務是空的,只是把 ngx_lua 裡的一些變數拿出來,傳給了什麼都不做的 fake_fetch,後面的 http filter、log 階段等一樣,沒有任何計算量。
隨後對 APISIX 和右邊的虛假服務分別跑壓力測定,對比結果發現 APISIX 的效能僅僅下降了 15%,也就是說在接受了 15% 的效能下降的同時,就可以享受前面提到的所有功能。我們在阿里雲的計算平臺,單核下可以跑到 23-24k QPS,4 核可以跑到 68k 的 QPS。
歡迎大家通過 github 檢索 APISIX 瞭解更多,同時我們也對外提供一對一的企業服務,歡迎感興趣的同學和我們聯絡。
演講視訊觀看及 PPT 下載:
Apache APISIX 微服務閘道器極致效能架構解析