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 下載:
