1. 程式人生 > >API 閘道器的選型和持續整合

API 閘道器的選型和持續整合

2019 年 8 月 31 日,OpenResty 社群聯合又拍雲,舉辦 OpenResty × Open Talk 全國巡迴沙龍·成都站,APISIX 作者溫銘在活動上做了《 API 閘道器的選型和持續整合 》的分享。

OpenResty x Open Talk 全國巡迴沙龍是由 OpenResty 中國社群、又拍雲發起,邀請業內資深的 OpenResty 技術專家,分享 OpenResty 實戰經驗,增進 OpenResty 使用者的交流與學習,推動 OpenResty 開源專案的發展。

溫銘,深圳支流科技聯合創始人,開源微服務 API 閘道器 APISIX PMC,OpenResty軟體基金會發起人,《OpenResty 從入門到實戰》專欄作者,創業之前在網際網路安全公司工作了 10 年,主要從事服務端的開發和架構,負責開發過木馬雲查殺、反釣魚系統和企業安全產品。曾在奇虎 360 擔任架構師,開源委員會發起人、委員。

以下是分享全文:

我和院生在做的一個開源的 API 閘道器專案叫 APISIX,今天介紹這個專案涉及到 OpenResty 的技術和選型,主要包括三個方面:

  • 第一, API 閘道器是什麼,它有什麼作用;
  • 第二,如何去做 API 閘道器,如何做選型;
  • 第三,APISIX 是一個開源專案,介紹我們在只有兩個人的情況下是怎麼去做測試和持續整合,裡面會涉及 OpenResty 的一些通用的東西,值得大家借鑑。

API 閘道器的作用

什麼是 API 閘道器

以 Kong 為例,左圖沒有 API 閘道器,但是後面掛了很多服務,如果每個服務都要實現包括認證、統計、安全校驗等功能,會有很多重複的工作。API 閘道器的作用就是把這些公共的東西抽取出來,如右圖,下面的這幾個服務,每個服務都只關心自身業務相關的東西,和業務無關的東西全部都丟到API 閘道器上,即 API 閘道器就是把公共的東西如統計、安全、限流、限速、快取等提取出來做了一箇中間層。

API 閘道器的傳統功能

  • 讓 API 請求更安全、更高效的得到處理。傳統的 API 閘道器有一些基本的功能直到現在都適用的,管理不管南北向的還是東西向的 API 流量可以能夠快速、安全地得到處理,這個是 API 閘道器最原始的目的。
  • 覆蓋 Nginx 的所有功能。API 的閘道器覆蓋了 Nginx 的所有功能,包括反向代理、負載均衡以及基本的快取、安全的認證、限流限速等。
  • 支援 Nginx 等 Web 伺服器實現不了的功能。如動態上游、動態 SSL 證書、動態限流限速,以及主動/被動健康檢查、服務熔斷等,這些動態的能力都是傳統的 Nginx、Apache 這類Web 伺服器支援不了的。
  • 全生命週期管理。在 API 閘道器領域,最大的玩家是谷歌,谷歌在 2016 年收購了一家上市公司 Apigee,它現在把整個功能整合在谷歌雲上。API 閘道器除了我們熟悉的反向代理、負載均衡、限流限速的外掛外,它還包括了 API 的設計、文件以及測試等,這一整套都屬於 API 閘道器的功能,我們叫做 API 的全生命週期管理,從專案設計到測試上線,所有的東西都在整個 API 閘道器的功能範疇內。

雲原生下的新功能

為什麼現在包括 Kong、APISIX 還要把傳統的東西再做一遍呢?這是因為在雲原生和微服務體系下,使用者和技術架構有了一些新的變化:

技術架構新變化

  • 需要對接雲原生裡面像 Prometheus、Zipkin、Skywalking 等重要元件;
  • gRPC 代理和協議轉換(REST<=>gRPC):HTTP 這種協議在微服務裡面用的越來越少,很多人開始用 gRPC,那在從 HTTP 到 gRPC 協議的轉換,這種功能也是需要的,包括 gRPC 的代理;
  • 身份認證方式改變:在傳統的 Nginx 裡面,一般是流量進來後根據路由的規則去做反向代理、負載均衡,很少對發流量的客戶端的身份做認證。但是在雲原生裡面就不一樣,因為很多是在微服務裡的流量,這裡面需要做嚴格的身份認證,包括加密、OpenID 之類的身份認證。這塊就是一些新的功能,可以把自己企業裡面需要做身份認證相關的東西放到第三方的外部認證的廠商去做;
  • Serverless 也是最近幾年非常火的一個概念,比如希望在邊緣節點上面動態地把一個函式跑起來或者把一個函式給停掉,或者動態地去改裡面的內容,你可以把你的 API 閘道器部署在邊緣節點上,具備了這種 FaaS 的功能,你的邊緣節點就會更加地靈活。APISIX 裡面最近就支援了 Serverless,可以讓你的一個 Lua 的函式動態地在邊緣結點跑起來;
  • 無狀態、隨意擴容和縮容:API 閘道器在十多年前效能要求沒有那麼高,因為當時網際網路的流量更多地是從瀏覽器到服務端,沒有手機和物聯網的裝置,也沒有微服務、內網這些流量。但是現在的流量很大,包括 4G、5G下面有很多的手機、IoT 裝置去訪問服務端,流量特別地大。此時,就需要一個性能更高的 API 閘道器去做支撐。雲原生的一個重要的標準是所有的服務都可以通過容器的方式隨意地去擴容和縮容,對 Kubernetes 友好;
  • 支援多雲和混合雲:現在上雲已經是一個趨勢,但是我們一般不太會把服務只放在一個雲上,比如騰訊雲、谷歌雲、阿里雲各放一部分,私有云再放一部分,根據它們的安全和價格做調整,私有的一些資料安全性更高的放在私有云上,資源比如和 CDN 相關的哪個便宜就放哪個雲上,做動態的切換,那麼此時就需要有一個和廠商無關的 API 閘道器放在前面做分發。

應用

舉兩個例子,介紹下新的 API 閘道器是做什麼的。

  • 替換 Nginx 的所有功能處理南北向的流量

它和 Nginx 比好處很明顯,是完全動態來實現的,不管是 Kong 或 APISIX,動態的都是最基本的點。在 Nginx 裡面修改任何一個配置檔案,都需要 reload 之後才能生效的。我們設想一個場景,用 Nginx 做最前面的路由,做負載均衡,突發的流量來了,此時需要快速地增加很多上游伺服器,就要不停地修改 Nginx 配置檔案,然後 reload,等突發流量過了之後再把上游的服務摘掉,那麼這時候還要再改 Nginx 檔案並 reload 。這個代價是很大的,但是你如果用 Kong、APISIX 這種 Web 伺服器,就不會有這樣的問題,通過 API 可以很輕鬆地實時修改整個叢集裡面所有機器上游的配置、動態證書的配置,當然效能會比 Nginx 稍微低一點,但是這個低也是可以接受的,因為它帶來了很大的靈活性。現在很多的廠商都是在做這樣的替換,不僅網際網路公司,還有一些傳統企業都在把 Nginx 慢慢地拿掉。

  • 零信任閘道器

近兩年安全領域裡很火的概念就是零信任,即zero trust。在傳統的安全領域裡面,我們認為邊界防護非常重要,所以會用防火牆對進來的流量做一層校驗,這個校驗其實是命中規則的校驗,如果是黑的就把它拒絕掉。那麼這個時候就會有一個問題:如果一些規則更新不及時,它就可以穿越防火牆,以前的安全更多是基於邊界的防護,過了邊界內網是可以暢通無阻的。

但是零信任閘道器可以徹底解決這個問題,它認為所有的流量都是不安全的,以前的邊界防護是非黑即白。現在的零信任安全閘道器則是非白即黑,你不是白的,那麼你就是黑的,所以它是完全基於身份來認證的。一個 API 的請求過來會到身份認證的伺服器,第三方的身份認證廠商比如 Author0、OKTA 的身份認證伺服器認證你的身份,身份認證過了,請求才可以通過,不然就直接拒絕掉,這是是安全領域的一個趨勢。

企業使用者的需求

  • 不鎖定,可回退

所有企業使用者的最大需求都是:不要鎖定使用者。API 閘道器是整個流量的入口,不能把使用者鎖定在裡面。比如你用了阿里雲的 API 閘道器,其實你就已經被它鎖定了,因為它是流量的入口,你沒有辦法分發到其它雲廠商上。此外還需要可回退,我使用了這個API 閘道器,比如原來是 Nginx,我可以很輕鬆地回退過去,這也是我們在做 APISIX 會考慮到的。可能使用者覺得用了一段時間不爽,想退回 Nginx,我們也可以支援這種能力。

  • 保持核心的穩定

APISIX 雖然每個月的迭代非常快,每個月有 200 多個 commit,有 10 個左右大的功能,但是 APISIX 裡面有一個叫 core 的目錄變化是很少的,我們會保持它的核心是穩定的。功能迭代可以很快,但是核心很穩定。

  • 支援企業個性需求的開發

無論是國內還是國外的企業,都沒有辦法拿產品去適應所有的需求。如果你適應了所有的需求,那麼你就做成了一個巨無霸,會是個很大很雜的產品,它的效能、可擴充套件性就會降的很低。所以我們就有外掛,如果你需要有個性化的東西,就去定製自己的外掛,需要什麼功能就把這個外掛放上去,不需要就把它拿掉。我可以保證最下面核心層是很穩定的,上面那層可以根據使用者需求定製。

如何做閘道器的選型

行業現狀瞭解

  • 參考 Gartner 報告

這個是我們選型的思路,我們做選型並不是先從技術上去做,而是先看整個行業,Gartner 的報告可以作為參考。如上圖所示,谷歌、IBM、RedHat 等頭部玩家吃掉全球大部分 API 市場,雖然技術圈都知道 Kong,但它其實處於遠見者的地位,此外Kong 作為新興的玩家還是第一個將自身 API 閘道器開源出來的。

  • 參考 CNCF 全景圖

Gartner 的報告更偏商業化,可以在此基礎之上參考開源社群中雲原生軟體基金會CNCF 維護的全景圖,很多開源和閉源專案都被其分層、分功能地羅列出來。全景圖中雲原生領域有十幾款軟體是做 API 閘道器選型時可以選擇的,其中有一半是大廠的產品,如 3SCALE 是Red Hat 的產品,剩下的 Kong、APISIX、TYK 等是開源專案,如果要做 API 選型可以在其中做選擇。

產品選型比較

在參考 Gartner 報告和 CNCF 全景圖之後,我們比較了主流的 API 閘道器,決定不用已有的 API 閘道器而是要自己做一個。

  • apigee

apigee 是最大的玩家,其優勢在於全生命週期,即從 API 設計、開發、文件、測試以及上線等全部是谷歌全家桶。但 apigee 是閉源專案,無法進行定製化開發,而且是被谷歌雲鎖定的。

  • Kong

Kong 解決了 apigee 的痛點,既不會鎖定也支援自定義開發,但 Kong 是 2015 年開發的,當時是把資料都放在Postgres 比較重的關係性資料庫裡,程式碼繁雜,效能存在問題。Kong 的優勢在於產品思路好,方向看得準。

  • APISIX

APISIX 借鑑 Kong 的思路,選型時完全基於 etcd,將所有的資料都放在 etcd 裡面,完成 Kong 在postgres 上做的大量重複程式碼,例如訊息分發、高可用和可擴充套件性都是基於 etcd 進行,操作更加簡單。APISIX 的不足在於開源時間短,從 2019 年 6 月 6 號開源到現在尚未經受大使用者的檢驗,但優勢明顯:二次開發難度比 Kong 小很多。以限流限速功能開發舉例, 在 APISIX 的檔案裡增加六七十行程式碼就能完成,但 Kong 則需要修改五六個檔案、兩三百行程式碼。

如何做閘道器的技術選型?

API 閘道器的核心元件:

  • 路由,路由可以認為是 Nginx 裡面的各個 location,怎麼把 location 分發到上游服務將各個外掛載入起來是路由的一個功能。選擇時需要思考的是做遍歷還是做一個樹?二者需要的時間和複雜程度是不一樣的,我們選擇像 Kong 一樣做遍歷。
  • 外掛,外掛是 API 閘道器的核心功能,有了外掛就可以很輕鬆地開發屬於自己的程式碼,而不用等開源社群增加相關功能。在做外掛時需要思考要不要做成熱載入,熱載入的意義在於新增外掛或者修改某一個外掛時,不需要重啟整個服務就能生效。我們希望做到修改或新增外掛時,可以通過 API 的呼叫馬上生效。
  • schema 的校驗,schema 的校驗指的是使用者請求進來後需要校驗上傳的欄位、型別等是否合法,如果自己寫外掛,其引數、輸入值是否合法,這相當於是對 API 的描述,使得個人和前端的配合十分便利。
  • 儲存, 放在關係型資料庫還是鍵值資料庫,亦或是放在 etcd 裡等同於是在做技術選型,需要把這些都選好後才能像搭積木一樣搭建起來。

選型原則:做雲原生友好的、高效能的、開源的 API 閘道器

  • 要對開發者友好。使用 API 閘道器的是開發者,我們希望不管是開發者看程式碼、學程式碼還是修改外掛都能很輕鬆,不用像我和院生當時看 Kong 的程式碼那樣痛苦。
  • 追求效能。雖說 OpenResty 的效能高,但是真正動手寫的時候會發現寫出來的程式碼效能不高,因為在 OpenResty 裡面程式碼都是很容易寫,但是很難保證寫出一個極致的程式碼,它裡面有非常多的坑,這是大部分人很難去注意到的。

APISIX 的選型

  • 路由:最開始選擇 lua-resty-r3,最近新增路由 FFI;
  • 外掛:靈感來自 Kong,但架構和設計完全不一樣,大幅簡化編寫難度,熱載入;
  • schema:借用騰訊開源的 rapidjson,在 rapidjson 實現 json schema,用 json schema標準做校驗;
  • 儲存:選用 etcd,當時沒有 Lua-resty-etcd 庫,需要從頭 lua 幫助 etcd 進行訪問。

APISIX 獨有的功能

  • 超強效能,效能是主打標籤,內部測試發現 APISIX 的效能是 Kong 的 10 倍;
  • 外掛熱更新,修改或增加外掛,不用重啟服務,所有的更新都是熱的;
  • 路由可以實現外掛化,如果不喜歡 r3 的複雜路由,可以使用字首匹配的路由;
  • 支援版本變更控制,如果釋出新版本出錯可以輕鬆回退老版本;
  • 以身份為基礎的零信任,新合併的 future 可以支援外部身份認證,此時很容易實現零信任,可以接入所有外部身份認證廠商的服務。使用時只需簡單調配部分引數,就可以將身份認證功能直接加入 API 中。Kong 的商業版也支援此功能,但 APISIX 直接開源。

測試、持續整合的最佳實踐

測試

大公司都有專門的 QA 團隊做測試,開發部門只需要寫完程式碼簡單自測後提交給 QA 團隊。但開源專案沒有 QA 團隊,甚至連開發團隊都是兼職,此時就必須用自動化的測試,即測試驅動開發的方式才能玩轉開源專案。

OpenResty 的開源專案將近 70 個,其商業公司有將近 100 個閉源的專案,總共將近 200 個專案不到 10 個人維護。如果手工測試,那就什麼都做不了,所以要想辦法實現解決這個問題。

  • 開發即測試

剛開始較慢,因為開發完一個新功能需要一塊提交對應的測試案例,否則PR 不會被合併。例如給 OpenResty 貢獻一個功能卻沒有提交對應的測試案例,或者提交了測試案例但不全,不管功能寫的有多好,此PR 一定不會被合併,因為破壞了整個開源專案的原則,測試需要是自動化跑起來的。

APISIX 多引入一個條件,即程式碼的覆蓋率不能低於70%,現在已經改為不能低於 80%。如果你的改動引入新程式碼,也增加了測試案例,但是降低了原有測試案例的覆蓋率,那也不能被接受合併。

  • 單元測試完全基於 test:nginx

測試案例完全基於 test:nginx ,可以認為 test:Nginx 是一個小語言或者一個DSL,文件較少,學習門檻比較高,我和院生對它比較熟悉才完全基於此進行測試。

  • 程式碼風格檢測:luackeck 和 lua-relang

Luackeck 非常好用,可以用於 Lua 和 OpenResty,提供有幾個引數進行選擇,還可以使用春哥寫的 lua-relang。我們是兩個程式都跑起來做程式碼風格檢測,以確保不管是新的提交者還是我們自己的程式碼風格的一致性。

  • 程式碼覆蓋率檢測:luacov

程式碼覆蓋率檢測使用luacov,這是標準 lua 的一個功能,可以將程式碼覆蓋率跑起來。

合併 PR 是在上述測試即 test:nginx 測試、程式碼風格測試、程式碼覆蓋率測試都跑過的前提下進行,每月 6 號發行新版本時進行效能測試,比較新老版本之間效能的差異。一般會跑火焰圖,同時定期做fuzzing 測試,混亂輸入如 uri、args 等做壓力測試。畢竟 APISIX 是一個 API 閘道器,作為流量的入口要保證足夠的穩定。

持續整合

測試不能依賴於人,否則總有一天會跑不下去。那麼如何讓單元測試、效能測試、程式碼風格檢測等測試不依賴於人穩定地執行呢?

  • 強依賴 GitHub:issue、Milestone、code review、PR approved。GitHub 的 code review 非常好用,它可以評論每一行程式碼,如果它覺得這行程式碼必須要改動,而實際沒有修改,是沒有辦法合併 approved。
  • 強依賴 travis CI:單元測試、程式碼風格檢測、多平臺測試(ubuntu 和 mac)、前端打包、自動提交。travis 是 GitHub 的持續整合外掛,APISIX 並沒有用自己的伺服器資源去跑測試,而是跑在雲端的,現在自帶APISIX 的前端,其打包、提交都是自動化進行。因為我們要從vue 的程式碼編譯為 html,這一切都是通過 travis 來做的。
  • http://coveralls.io,將程式碼覆蓋率的結果上傳到http://coveralls.io 網站,以視覺化的方式呈現所有和程式碼覆蓋率相關的東西,例如哪一行程式碼沒有被檢測到,和上一個版本有什麼變化等,使得程式碼覆蓋率檢測自動化進行。前文曾提到要始終保證 APISIX 的核心穩定,這就需要保證core 目錄裡所有檔案程式碼覆蓋率能夠達到 100%,即核心板塊的每一行程式碼都被測試到。

總結

  • 資源少不一定是壞事。不管是開源專案還是商業公司,只有在資源少的時候,才會思考如何藉助外部的力量或者是想出一些鬼點子解決問題;
  • APISIX 的選型、測試和 CI 都是找“取巧”和自動化的方式,藉助巧用外部力量的方式去做,沒有造輪子;
  • APISIX 的選型、測試和 CI 三者非常重要,比效能重要。雖然我們主打效能,但更值得大家琢磨的不只是程式碼,而是選型怎麼測試和 CI 的,大家可以將其運用到業務中,即使不用 OpenResty 和 APISIX,還是可以學習開源專案是怎麼做的;
  • GitHub 和 SaaS 能提供的服務,絕對不會自己去造,剋制住自己造輪子的衝動。

檢視演講PPT及視訊:

API 閘道器的選型 測試和持續整合

本文由部落格一文多發平臺 OpenWrite 釋出!