http://architect.dataguru.cn/article-11431-1.htmlhtml
API Gateway(API GW / API 網關),顧名思義,是出如今系統邊界上的一個面向 API 的、串行集中式的強管控服務,這裏的邊界是企業 IT 系統的邊界,主要起到隔離外部訪問與內部系統的做用。在微服務概念的流行以前,API 網關的實體就已經誕生了,例如銀行、證券等領域常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的。
API 網關的流行,源於近幾年來,移動應用與企業間互聯需求的興起。移動應用、企業互聯,使得後臺服務支持的對象,從之前單一的 Web 應用,擴展到多種使用場景,且每種使用場景對後臺服務的要求都不盡相同。這不只增長了後臺服務的響應量,還增長了後臺服務的複雜性。隨着微服務架構概念的提出,API 網關成爲了微服務架構的一個標配組件。
網關的幾種使用場景
我司王延炯博士的文章《談 API 網關的背景、架構以及落地方案》中,提到了網關的幾種使用場景:
面向 Web App 的網關。這類場景,在物理形態上相似先後端分離,此時的 Web App 已經不是全功能的 Web App,而是根據場景定製、場景化的 App。
面向 Mobile App 的網關。這類場景,移動 App 是後端 Service 的使用者,此時的 API GW 還須要承擔一部分 MDM(此處是指移動設備管理,不是主數據管理)的職能。
面向 Partner OpenAPI 的網關。這類場景,主要爲了知足業務形態對外開放,與企業外部合做夥伴創建生態圈,此時的 API GW 須要增長配額、流控、令牌等一系列安全管控功能。
面向 Partner ExternalAPI 的網關。這類場景,主要是爲了知足企業自身業務的須要,實現對企業自有業務的映射。一個典型的例子就是使用「合做方帳號登陸」、「使用第三方支付平臺支付」等等。此時的 API GW 就須要在邊界上,爲企業內部 Service 統一調用外部的 API 作統一的認證、受權、以及訪問控制。
面向 IoT SmartDevice 的網關。這類場景主要在傳統企業,尤爲是工業企業,傳感器、物理設備從工業控制協議向 IP 轉換,致使物理鏈路上會存在一部分公網鏈路。此時的 API GW 所須要知足的「內外兼修」的雙向數據流,設備通常經過一個「客戶側」的集中網關在和企業的接入網關進行通訊。
在咱們講的微服務架構下的 API 網關,通常指的是前兩種使用場景。即,主要是把企業內部的 API 能力,暴露給其餘應用或合做夥伴使用。
網關的做用和價值
網關層做爲客戶端與服務端的一層擋板,主要起到了三大類做用:
第一類做用是隔離做用,做爲企業系統邊界,隔離外網系統與內網系統。
第二類做用是解耦做用,經過解耦,使得微服務系統的各方可以獨立、自由、高效、靈活地調整,而不用擔憂給其餘方面帶來影響。
第三類做用是腳手架做用,提供了一個地點,方便經過擴展機制對請求進行一系列加工和處理。
內外的隔離
企業爲了保護內部系統的安全性,內網與外網都是隔離的,企業的服務應用都是運行在內網環境中,爲了安全的考量,通常都不容許外部直接訪問。API 網關部署在防火牆外面,起到一層擋板做用,內部系統只接受 API 網關轉發過來的請求。網關經過白名單或校驗規則,對訪問進行了初步的過濾。相比防火牆,這種軟件實現的過濾規則,更加動態靈活。
多方的解耦
在微服務架構下,整個環境包括服務的提供者、服務的消費者、服務運維人員、安全管理人員等,每一個角色的職責和述求都不一樣。例如:服務消費者已經須要提出一些新的服務需求,以快速應對業務變化;服務提供者,做爲業務服務的沉澱方,但願保持服務的通用性與穩定性,很難應對快速的變化。有了 API 網關這一層,能夠很好的解耦各方的相互依賴關係,讓各方更加專一本身的目標。
1. 解耦功能與非功能。
企業在把服務提供給外部訪問時,除了實現業務邏輯功能外,還面臨許多非功能性的要求。例如:須要防範黑客攻擊,須要應對突發的訪問量、須要確認用戶的權限,須要對訪問進行監控等。這些非功能邏輯,不能與業務邏輯的開發混在一塊兒,須要有專業的人員甚至專業的團隊來處理。
2. 解耦客戶端與服務提供者
客戶端與服務提供者分屬於不一樣的團隊,工做性質要求也不相同。對於服務提供者來講,他主要的職責是對業務進行抽象,提供可複用的業務功能,他們須要對業務模型進行深刻的思考和沉澱,不能輕易爲了響應外部的需求而破壞業務模型的穩定性。而業務的快速變化,又要求企業快速提供接口來知足客戶端需求。這就須要一箇中間層,來對服務層的接口進行封裝,以及時響應客戶端的需求。
經過解耦,服務層可使用統一的接口、協議和報文格式來暴露服務,而沒必要考慮客戶端的多種形態。
3. 網關層是否須要實現服務的編排?
在介紹 API 網關的一些文章中,提到了網關層的服務編排能力。從解耦的角度出發,服務的編排不適合在網關層進行。對服務的編排,實際上是提供了一種業務能力,若是把服務的編排放在了網關層,其實是把一部分業務能力放在了網關層,這樣一來,服務層、網關層都有一些業務能力,形成團隊職責的不清,也不利於業務能力的沉澱。
插件的腳手架
網關層除了請求的路由、轉發外,還須要負責安全、鑑權、限流、監控等。這些功能的實現方式,每每隨着業務的變化不斷調整。例如權限控制方面,早期可能只須要簡單的用戶 + 密碼方式,後續用戶量大了後,可能會使用高性能的第三方解決方案。又例如,針對不一樣的監控方案,須要記錄不一樣的日誌文件。
因此,這些能力不能一開始就固化在網關平臺上,而應該是一種可配置的方式,便於修改和替換。這就要求網關層提供一套機制,能夠很好地支持這種動態擴展。
帶來的好處
這裏總結下網關的價值:
網關層對外部和內部進行了隔離,保障了後臺服務的安全性。
對外訪問控制由網絡層面轉換成了運維層面,減小變動的流程和錯誤成本
減小客戶端與服務的耦合,服務能夠獨立發展。經過網關層來作映射。
經過網關層聚合,減小外部訪問的頻次,提高訪問效率。
節約後端服務開發成本,減小上線風險。
爲服務熔斷,灰度發佈,線上測試提供簡單方案。
便於擴展。
企業級 API 網關須要具有的條件
微服務架構下,企業 API 網關的定位
API 網關做爲對外提供服務的入口,就像企業服務的大門。一方面,要有足夠的能力,應對大量的對外訪問,另外一方面,還要給對內的服務提供必定的安全保障。
除此以外,企業提供的 API 服務多種多樣,API 網關要可以對這些 API 的全生命週期進行便捷的管理,例如服務發佈、調整、下架、計費、監控等。
企業環境下,API 網關須要考慮哪些要素
1. 安全性問題
企業在把服務暴露給外部使用時,首先要確保服務使用的安全,防止外部的惡意訪問對公司業務的影響,特別是涉及交易方面的服務,更是要全面考慮安全性。爲確保安全,須要考慮在通信鏈路的創建、通信數據的加密、數據的完整性、不可抵賴性等方面。
2.性能問題。
做爲企業 API 的入口,全部的請求都會通過 API 網關進行轉發,可想而知,對 API 網關的訪問壓力是巨大的,有的網站甚至達到每分鐘上千萬的訪問量。特別是在一些互聯網企業,海量的移動終端每時每刻都須要與後端的服務進行交互,若是不能保證網關的高性能,企業在網關層須要投入大量的設備和成本。曾在一家互聯網公司發生過,因爲網關性能問題,網關的機器數量,須要與後臺服務器的數量保持同步增加。這種狀況顯然是企業服務忍受的。
3.高可用問題。
API 網關做爲邏輯上的單點,一旦發生問題,將形成企業服務的不可用,對企業來講可能形成的致命的影響。計算短期的不可用,也會給企業帶來直接的經濟損失。因此,如何保證 API 網關的 7*24 小時的穩定運行,網關的自動伸縮、API 的熱更新等問題,都是企業級的網關須要考慮的。
4.擴展性問題
前面說到,企業網關提供了一個腳手架,一些非功能性的問題,例如日誌、安全、負載均衡策略、鑑權等。這些插件會隨着企業業務規模等的變化進行不斷的強化與調整。這就須要網關層提供這樣一種機制,使得能夠靈活地進行這些調整和變化,而不用頻繁對網關層進行改動,確保網關層的穩定性。
5.API 高效運維的問題
API 在上線、發佈過程當中,都須要涉及到網關層的配合,例如,須要網關層知道 API 發佈的地址,API 的接口形式、報文格式,也須要網關層對後臺 API 進行封裝。在 API 調整後,須要做出相應的修改。因此,API 網關設計時,須要明確網關層與服務層的職責切分與協做模式,使得 API 的管理、發佈更加高效。
6. API 全生命週期管理的問題
API 服務的全生命週期,包括服務的開發、測試、上線發佈;服務使用的申請、開通;服務分類分級別的管理、服務使用狀況的監控、計費等等。
一個企業可能會暴露成百上千個 API,平常也會常常進行 API 的發佈、升級、改造、下架等操做。對不一樣的服務,不一樣的訪問者,須要提供不一樣的服務訪問策略。有的商業 API 公司,還須要對 API 的使用進行付費。因此,與 API 網關配套的,須要一套完善的自助系統,提供給服務的提供者、管理者、使用者,來對服務的發佈、使用、和運營。
業界經常使用的 API 網關方案
業界 API 網關解決方案有不少,包括商業的、開源的。例如 Tyk、Kong、API Umbrella、ApiAxle、Netflix Zuul、WSO2 API Manager、ClydeIO 等。下面介紹三種常見的 API 網關方案。
Nginx + Lua
Nginx 是由 Igor Sysoev 爲俄羅斯訪問量第二的 Rambler.ru 站點開發的,一個高性能的 HTTP 和反向代理服務器。2012 年,Nginx 榮獲年度雲計算開發獎,併成長爲世界第二大 Web 服務器。全世界流量最高的前 1000 名網站中,超過 25% 都使用 Nginx 來處理海量的互聯網請求。
Nginx 性能極高,Nginx 先天的事件驅動型設計、全異步的網絡 I/O 處理機制、極少的進程間切換以及許多優化設計,都使得 Nginx 天生善於處理高併發壓力下的互聯網請求。Nginx 的穩定性也在各大網站獲得驗證。官方提供的經常使用模塊都很是穩定,每一個 worker 進程相對獨立,master 進程在 1 個 worker 進程出錯時能夠快速「拉起」新的 worker 子進程提供服務。支持熱部署,能夠不停機更新配置文件、更新日誌文件、更新服務器程序版本。
Nginx 的設計極具擴展性,它徹底是由多個不一樣功能、不一樣層次、不一樣類型且耦合度極低的模塊組成。所以,當對某一個模塊修復 Bug 或進行升級時,能夠專一於模塊自身,無須在乎其餘。
Nginx 使用最自由的 BSD 許可協議,容許用戶在本身的項目中直接使用或修改 Nginx 源碼,有大量的插件能夠利用。可是,Nginx 模塊須要用 C 開發,並且必須符合一系列複雜的規則。雖然經過第三方模塊,能夠支持 Nginx 與 Perl、Lua 等腳本語言集成工做,但對使用者的要求仍是很高。
Nginx 能夠說是一款可以工業化 API 網關,在國內的不少互聯網公司,例如阿里、新浪等都獲得很好的應用。
Spring Cloud Zuul
Zuul Netflix 公司開源的一個 API 網關組件。提供了認證 & 鑑權、限流、動態路由,監控,彈性,安全、負載均衡、協助單點壓測、靜態響應等邊緣服務的框架。
Zuul 的基本功能:
驗證與安全保障: 識別面向各種資源的驗證要求並拒絕那些與要求不符的請求。
審查與監控: 在邊緣位置追蹤有意義數據及統計結果,從而爲咱們帶來準確的生產狀態結論。
動態路由: 以動態方式根據須要將請求路由至不一樣後端集羣處。
壓力測試: 逐漸增長指向集羣的負載流量,從而計算性能水平。
負載分配: 爲每一種負載類型分配對應容量,並棄用超出限定值的請求。
靜態響應處理: 在邊緣位置直接創建部分響應,從而避免其流入內部集羣。
Netflix 公司還利用 Zuul 的功能經過金絲雀版本實現精確路由與壓力測試。
雖然提供的功能還算豐富,但都比較弱,很難知足高要求的場景。
Zuul 處理每一個請求的方式是針對每一個請求是用一個線程來處理。一般狀況下,爲了提升性能,全部請求會被放處處理隊列中,從線程池中選取空閒線程來處理該請求。2016 年末,Netflix 將它們的網關服務 Zuul 進行了升級,全新的 Zuul 2 將 HTTP 請求的處理方式從同步變成了異步,以提高其處理性能。除了 Netflix 公司,目前 Zuul 在企業中用的還比較少,性能和穩定性方面還有待進一步觀察。
從 Zuul 的架構圖上能夠看出,Zuul 更像是一個過濾器框架,其自身的路由、日誌、反向代理、ddos 預防等功能都是經過過濾器實現的。提供了 PRE、ROUTING、POST 和 ERROR 四個擴展點,能夠很容易的添加自定義的過濾器。
Zuul 的搭建很是簡便,使用和配置也很簡單。Zuul 的開源社區比較活躍,一直在更新狀態,但版本不算太穩定,在使用的過程當中,還有一些坑要踩。例如重定向問題、異常處理問題,尚未解決的很好,須要本身重寫一些 filter。
若是從通盤考慮, 這種方案不是最佳方案。但若是本身的團隊對總體技術設施把控有限,且團隊規模不大,沒有專門的網關開發人員的狀況下,Zuul 是一款快速上手的最佳方案。
Mashape Kong
Kong 是 Mashape 提供的一款 API 管理軟件,它自己是基於 Ngnix+Lua 的,但比 Nginx 提供了更簡單的配置方式,數據採用了 Apache Cassandra/
Postgre
SQL 存儲,而且提供了一些優秀的插件,好比驗證,日誌,調用頻次限制等。
Kong 的一個很是誘人的地方就是提供了大量的插件來擴展應用,經過設置不一樣的插件能夠爲服務提供各類加強的功能。Kong 默認插件插件包括:
身份認證:Kong 提供了 Basic Authentication、Key authentication、OAuth2.0 authentication、HMAC authentication、JWT、LDAP authentication 認證明現。
安全:ACL(訪問控制)、CORS(跨域資源共享)、動態 SSL、IP 限制、爬蟲檢測實現。
流量控制:請求限流(基於請求計數限流)、上游響應限流(根據 upstream 響應計數限流)、請求大小限制。限流支持本地、
Redis 和集羣限流模式。
分析監控:Galileo(記錄請求和響應數據,實現 API 分析)、Datadog(記錄 API Metric 如請求次數、請求大小、響應狀態和延遲,可視化 API Metric)、Runscope(記錄請求和響應數據,實現 API 性能測試和監控)。
轉換:請求轉換、響應轉換
Kong 自己也是基於 Nginx 的,因此在性能和穩定性上都沒有問題。Kong 做爲一款商業軟件,在 Nginx 上作了很擴展工做,並且還有不少付費的商業插件。Kong 自己也有付費的企業版,其中包括技術支持、使用培訓服務以及 API 分析插件。
從對上面三種方案的比較中能夠看到,Spring Cloud Zuul 很是適合創業初期的團隊,快速搭建一個「基本可用」的 API 網關。Nginx 適合有較強研發團隊,自主開發企業本身的 API 網關。Kong 適合於沒有自身研發團隊,但須要擁有企業級 API 網關能力的公司。
如何設計一個好的企業級 API 網關產品
功能上的考量
API 生命週期管理功能
覆蓋 API 的定義、測試、發佈的整個生命週期管理,便捷的平常管理、版本管理,支持熱升級和快速回滾。
開發和使用支持功能
提供頁面調試工具,自動生成 API 文檔和 SDK,大大下降人力成本。
安全防禦功能
API 請求到達網關須要通過嚴格的身份認證、權限認證,才能到達後端服務。支持
算法簽名,支持 SSL 加密。
流量控制功能
可控制單位時間內 API 容許被調用次數。用來保護企業的後端服務,實現業務分級和用戶分級。
支持對 API 流控,您能夠根據 API 的重要程度來配置不一樣流控,從而保障重要業務的穩定運行;
支持用戶、應用和例外流控,您能夠根據用戶的重要性來配置不一樣流控,從而能夠保證大用戶的權益;
流控粒度:分鐘、小時、天。
請求管理功能
可根據配置進行參數類型、參數值(範圍、枚舉、正則、Json Schema)的校驗,減小後端對非法請求、無效請求的資源消耗和處理成本。
能夠在 API 網關定義參數映射規則,網關經過映射規則將後端服務經過映射翻譯成任何形式,以知足不一樣用戶的不一樣需求,從而避免功能重複開發。
監控告警功能
提供實時、可視化的 API 監控,包括:調用量、調用方式、響應時間、錯誤率,讓您可以清楚的瞭解 API 的運行情況和用戶的行爲習慣。
支持自定義報警規則,來針對異常狀況進行報警,下降故障處理時間。
提供可訂閱的數據分析報表和智能分析。
API 交易功能
提供 API 交易市場,計量計費、Quota 控制、運營售賣等需求。
網關的高性能設計
傳統的基於線程的併發模型(Thread-based concurrency),爲每個請求分配一個線程或進程。這種模型編程簡單,能夠將處理一個完整請求的代碼編寫在一個代碼路徑中。這種模型的弊端是,隨着線程 (進程) 數的上升,操做系統在這些線程 (進程) 之間的頻繁切換,將急劇下降系統的性能。
另外一種更高效的併發模型是事件驅動的併發模型(Event-driven concurrency)。在這種模型中,每個請求在系統被表示成一個有限狀態機(FSM)。每個 FSM 的狀態表示請求的一系列的操做。服務器由一組線程 / 進程(通常是 one per CPU)循環處理各類來自隊列的事件 (Event)。
這種模型要求每個狀態的操做是短暫的而且是非阻塞的,因此 Event-driven concurrency 模型通常都用了非阻塞的 I/O 接口(NIO)。
普元的產品中,爲增長系統的吞吐量,是採用了基於事件的併發模型的 SEDA 的架構。SEDA 架構的核心思想是:把一個請求處理過程分紅幾個 Stage,每一個 Stage 可由不一樣的 handle 進行處理,不一樣資源消耗的 Stage 使用不一樣數量的線程來處理,handle 之間採用異步通信的模式。
網關的高可用設計
保證高可用通常作法是解決單點故障給系統總體帶來的影響。普元在產品設計時,爲確保高可用,考慮了以下幾點要素:
一、無狀態設計原則。網關層爲保證高能夠,易於伸縮,快速啓動,須要設計成無狀態的。用戶的狀態數據咱們一般使用 session 對象來封裝,網關層要設計成無狀態的,也就是說,不能由網關來負責 session 的維護。那由誰來維護 session 相關的信息呢?咱們是採用 cookie+session 服務器的方式 ;
a) 用戶在登陸頁完成登陸操做後,服務器會生成一個登陸 session 信息,保存起來,設置個失效時間,並設置到用戶的 cookie 裏。
b) 用戶後續的每次請求裏會帶着這個 cookie 信息,服務端會對這個 cookie 信息進行校驗,經過了就認爲是合法用戶,執行請求操做。
二、優雅下線原則:當網關發現某一個節點不可用時(例如請求響應時間超過閥值),不是直接斷開與此節點的鏈接,而是先把此節點標記爲不可用(後續不在發送請求到此節點),但還會留出一段時間讓以前的請求都響應完畢。
三、Slow start 特性:當網關監聽到有一臺新的服務註冊上來時,考慮到有些服務啓動後,剛開始會有許多初始化的工做,此時服務對請求的響應速度是比較慢的。若是一開始就給這臺服務分配太多的壓力,有可能致使服務瞬間被壓垮。爲了不這種狀況,網關層須要考慮支持 Slow Start 特性。即,通過一段時間,逐漸把壓力增長到預設的值。
網關的擴展性設計
網關的擴展性設計時,須要考慮下面幾點:
在哪些地點進行攔截處理
攔截器的處理順序
如何在攔截器間傳遞數據
支持在線關閉或啓動一個攔截器
在哪些地點進行攔截處理
咱們知道,網關對請求的處理,能夠分爲三個階段:接受請求、路由並轉發請求、接受服務的返回數據並返回給請求者,除此以外,還有一種狀況是處理錯誤。因此咱們也能夠在這四個地方添加擴展點。
接受到請求後
定位到一個服務,並準備轉發以前
接受到服務的返回數據,返回給客戶端以前
當服務調用失敗後
攔截器的處理順序
攔截器的處理順序,能夠分爲兩大類:一類爲網關平臺自帶的攔截器,例如安全校驗、日誌記錄等;一類爲網關層邏輯開發的,例如格式轉換等。通常來講,網關先執行網關平臺自帶的攔截器,再執行爲了業務邏輯編寫的攔截器。固然,網關也須要提供一種機制,能夠較容易地調整攔截器的執行順序。最簡單的一種方法,就是給每一個攔截器定義一個優先級,網關按優先級順序依次調用各攔截器。
如何在攔截器間傳遞數據
對網關層來講,它接收和處理的數據都是 Request 對象,網關層在接收到請求後,把請求封裝爲 Request 對象,爲了讓後續的 filter 可以得到這個對象,能夠考慮把 Request 對象保存在線程變量中。
支持在線關閉或啓用一個攔截器
有些攔截器,例如一些調試日誌的攔截器,一般狀況下都是關閉的,只有在出現問題的時候才須要打開。爲了保證網關的高可用,網關層必須具有在線啓用或關閉攔截器的能力。通常,網關須要提供 restful 接口方式,來關閉和啓用一個攔截器。相似這樣的命令:PUT /apigateway/v1/filters/filterName?enable=value
API 管理與動態發佈設計
對服務管理來講,分爲前端服務管理與後端服務管理。前端服務指的是網關層暴露給客戶端使用的服務 API,後端服務指的是服務層提供的業務服務 API。一個服務暴露給客戶端使用,除了網關層和服務層提供服務的代碼外,還須要配置前端服務與後端服務的映射關係。
API 的描述
要對 API 進行管理,首先要對 API 進行描述。咱們常見的接口描述語言有 yaml、json、xml、PB 等,這幾種語言各有優劣。普元選擇的對 API 契約的描述方式,是參考 swagger spec 規範,使用 yaml 語言來描述。固然,swagger 的描述是針對 restful 接口的,咱們能夠針對本身接口定義的須要,自定義本身的描述屬性。例如,普元在對微服務描述的時候,擴展了 x-primeton-service、x-primeton-operation 等屬性來對服務進行描述。例如:
有了 API 接口契約,除了用來描述服務接口外,還能夠:
使用契約,自動生成服務的 API 文檔。
使用契約,自動生成客戶端的調用代碼。
使用契約,生成服務接口的測試框架代碼。
先後端服務映射
網關層 API 調用服務層 API,有多種方式。例如,能夠由按照服務層 API 的服務契約,生成一段客戶端代碼,發佈給網關層使用。這種方式的弊端是,網關層代碼依賴於服務層代碼,服務層頻繁修改和調整接口時,致使網關層的代碼很難維護。
能夠經過配置先後端服務映射的方式,解耦網關層對服務層的依賴。當服務層的 API(例如服務名、參數名等)發生變化時,只需調整映射關係,無需對網關層的代碼進行調整。網關層按照映射,自動裝配服務層 API 所須要的數據格式。這樣,網關層團隊與服務層團隊能夠相互不受干擾地開發各自的服務。
映射的設置,包括服務 URL 的映射與參數的映射。有了前面提供的服務契約描述,能夠可視化的配置這種映射關係。
API 上架
先後端的服務發佈後,並配置了映射關係後,就能夠把服務暴露給外部使用了。在上架過程當中,還須要設置訪問權限、流量控制等信息。這一塊,每一個企業的業務要求都不同,就不作過多介紹了。
總結
API 網關做爲企業能力開放的一個門戶,除了具有基本的請求轉發、協議轉換、路由等功能,以及高性能和高穩定性外,還需具有良好的擴展性,已便於網關能力的不斷加強。在網關實施過程當中,要規劃好網關層與服務層的交互方式,儘可能使得網關層與服務層解耦,便於各個團隊工做的獨立性。另外,在 API 的管理上,須要提供 API 全生命週期的發佈、配置、鑑權、流控、監控等配套的管理功能。這樣,才能讓 API 網關真正在企業中運轉起來