何運田 張青清
(中國銀聯股份有限公司 上海 200120)
隨著云計算[1]和互聯網技術的快速發展,越來越多的企業開始重視微服務[2-3]、云原生等新一代技術架構設計模式。以國內為例,知名互聯網公司都開始發力云技術,逐步對外提供獨立自主開發的公有云產品,比如阿里云、華為云、騰訊云等。這些云平臺不僅很好地支撐了各自企業內部的需求,也為不具備開發云平臺能力的廣大中小企業提供了開箱即用的云產品,滿足了應用上云的需求。云上應用大多數采用微服務的架構;在各類業務場景中,一個業務系統往往分解成若干個子系統。子系統之間以API為形態,進行跨系統跨組織的開放、共享、重組和調用。如果在服務資源入口不做統一的管理,紛亂的協議、不同格式的網絡數據、繁雜的調用拓撲會讓整個服務集成和運維的過程變得異常復雜和不穩定。因此,如何有效地治理和管控各個業務子系統,并通過有效的監控手段來保障微服務功能有效、安全可靠,將成為各團隊組織上云之前必須考慮的問題[4]。
為了解決上述問題,本文基于開源技術,設計并搭建了一套API網關集成及監控系統,并在公司的私有云環境中進行了部署和實踐,取得了很好的效果。系統整體架構如圖1所示。

圖1 整體系統架構
根據圖1,系統整體上劃分成兩個VPC(虛擬私有云):VPC1(內部局域網)和VPC2(互聯網連接區)。VPC1隸屬公司生產區,有嚴格的防火墻控制,具備較高的安全策略;VPC2類似通常所說的DMZ區,可以通過配置有限的連接互聯網。兩個網絡之間通過對等網絡連接,這樣VPC1和VPC2可以通過私有IP地址進行通信,就像兩個VCP在一個網絡中一樣。為了實現高可用,VPC1和VPC2之間以及VPC2和互聯網之間都增設了負載均衡設備,既增強系統穩定性,也在一定程度上屏蔽了VPC之間網絡的復雜性[5]。
除了網絡上的職責劃分,系統在功能上分成三個部分:
(1) 服務集成網關。Kong是一個在Nginx中運行的開源Lua應用程序,兼具了Nginx優秀的反向代理功能和Lua-Nginx模塊的擴展特性。基于Kong技術設計API網關,可以很容易通過插件的形式來擴展負載均衡、日志審計、身份驗證、速率限制、請求轉換等非業務功能。為了統一管理的微服務之間的互相調用,所有的微服務開放的API統一遵循RESTful[6]的風格。該風格的接口通過每個URI代表一種資源,客戶端通過HTTP協議來對服務端資源進行操作,并獲取JSON格式的結果。
(2) 網關管理平臺。為了更方便運維人員可視化配置及管理API,本系統以KONGA開源項目為藍本,進行二次開發。使用人員可以很方便地通過網關管理平臺對Kong集群進行配置。
(3) 網關監控系統。監控系統由Dashboard(智能監控大屏)、Kong-syncer(日志同步服務器)、Monitor-server(監控后臺服務器)三部分組成。通過監控系統,不僅可以實時采集并查看網關中配置的API訪問信息,還可以按需進行聚合分析等增值服務。
單體服務不需要API維度的網關,因為它匯總了一個業務系統所提供的所有API,可以統一對這些服務做調度、鑒權、限流等控制。但在微服務架構的應用中,因為功能模塊的拆分,每個子業務系統都會獨立提供服務;這些服務有可能互相之間進行調度,也可能對外提供服務。面向微服務的API網關[7]定位于解決對外提供服務這塊內容,通常也稱之為邊緣服務。它的定義為類似面向對象設計模式中的Facade模式,它的存在就像整個微服務架構系統中的門面一樣,所有的外部客戶端訪問云平臺,都需要經過網關來做統一的調度和管控。具體而言,主要體現在以下方面:
(1) 服務統一管理。其包括對服務接口格式、元數據、服務提供方、服務消費方等的管理。涵蓋API的上線、發布、下線等整個生命周期。
(2) 服務調用管理。主要體現在權限控制方面,比如調用權限的認證過濾、調用頻次、調用總額、黑白名單等。
(3) 服務質量(QoS)控制。網關為上游服務提供多種策略來解決應用過程中可能出現的服務性能問題,比如負載均衡、緩存、熔斷、降級、流量控制等,以提高服務的穩定性和可用性。
(4) 服務監控與報警。微服務體系中因系統繁多、交互復雜,更需要有較好的運維監控和報警體系。網關系統需要從用戶、服務、應用多種維度分析統計API調用情況,并針對可能出現和已經出現的問題進行及時預警和報警。
本系統中,網關集群是基于開源技術Kong[8]來實現。Kong是Mashape公司的開源API網關,其底層是基于Nginx驅動的,幾乎沒有任何性能消耗,性能可以達到1 600次/s,增加安全鑒權后訪問也沒有明顯性能下降,性能跟原生Nginx不相上下。
Kong支持主流數據庫的讀寫,目前官方給定的選擇包括PostgreSQL和Cassandra。因為Cassandra[9]具備較成熟的集群解決方案,因此本文中采用Kong+Cassandra來組成集群。由于Kong本身不具備集群能力,因此需要配置前置負載來實現Kong節點之間的流量均衡。該方案可以使Kong支持更多的訪問流量,同時保證較低的網絡延遲。出于性能考量,為了避免頻繁的數據訪問,集群中的每個節點都會在本地緩存一部分數據。
另外,Kong具備模塊性。開發者可以通過給Kong節點增加插件的方式來擴展網關的功能。官方已經提供了很多可以開箱即用的插件,比如Auth2.0、logging、CORS(Cross-Origin Resource Sharing)等。開發者也可以通過Lua語言編寫自定義插件,并通過Lua-Nginx-module模塊來集成進Nginx[10]的生命周期中。具體集群架構見圖2。

圖2 Kong集群架構
Kong提供了完善的管理接口,用來對Kong實現管理功能。默認情況下,Kong服務會監聽8001端口用于管理API的響應,監聽8000端口用來接收需要轉發的RestFul請求。為了方便管理API,Kong抽象了若干個概念:
(1) 服務(Service)。服務等價于Nginx的upstream指令中的server,用來代指上游的真實服務。當有多個上游服務實例時,可以配置權重來實現流量分配。
(2) 路由(Route)。路由定義了匹配客戶端請求的路徑規則,一個服務可以包含若干路由。
(3) 消費者(Consumer)。消費者代指一個服務接入方,可以根據消費者的ID來對特定路由設置訪問權限。
(4) 插件(Plugin)。插件代指想要對Kong擴展的小功能,比如日志插件,可以在請求到網關時,記錄日志到數據庫。插件使用Lua語言開發,通過Kong的管理端口來啟用,使得功能定制化擴展非常方便。
以上概念是Kong的核心概念,也是我們管理Kong網關的主要目標。由于Kong提供了管理接口,我們可以通過命令行Curl進行配置,以創建OCR識別應用的API轉發為例,配置命令如下:
curl -X POST "http:kongHost:8001/apis/
-H ′Content-Type: application/json′
-d ′{
"name": "ocr_api",
"uris": "OCR",
"upstream_ url": "http://OCR_ HOST",
"strip _ uri": " true"
}′
考慮到Curl的配置方式對使用者來說不是很友好,而且容易出錯,本系統以開源項目KongA為基礎,進行了二次開發,實現了Kong的可視化配置,簡化了操作。具體管理界面效果見圖3。

圖3 KongA配置Service示意圖
很多時候,服務的提供者和服務的調用者都有監控服務的性能、服務調用量、網絡帶寬、出錯告警等需求。因此,一個成熟的網關系統少不了監控體系。本系統針對這部分需求,采用集成開源分布式搜索引擎Elasticsearch[11]加自研組件的方式,實現客戶端API請求的日志存儲、分析及實時監控預警等功能。其中,Elasticsearch具體的架構如圖4所示。

圖4 監控子系統架構示意圖
如圖4所示,監控子系統主要包括Dashboard、monitor、Elasticsearch集群,以及自研數據同步集群Kong-syncer。其中:Dashboard主要負責對外實時展示各種統計圖表;monitor用來管理及實現統計邏輯;Elasticsearch集群負責存儲、搜索、聚合各種日志信息;Kong-syncer類似ETL工具,用來從數據源監聽拉取原始數據,清洗及格式化后導入ES集群。
Kong本身具備模塊特性,支持自定義插件來擴展所需功能。本系統啟用http-log插件,在Kong接收到客戶端請求的響應所有body信息時會自動將請求的日志信息發送到自研的sync-server進行歸并并存儲到ES集群。啟動日志插件可以通過管理平臺來可視化完成操作。為了方便后續的統計和分析,針對請求的日志格式需要具備良好的擴展性和可讀性。本系統采用JSON的格式來定義和解析日志,日志格式如下:
{
"request": {
"method": "請求方式",
"uri": "請求URI",
"url": "完整請求路徑",
"size": "請求體",
"querystring": ["請求參數組"],
"headers": ["請求頭鍵值對"]
},
"upstream_uri": "上游服務轉發路徑",
"response": {
"status": "響應code",
"size": "響應大小",
"headers": ["響應頭鍵值對"]
},
"route": {
"id": "請求匹配的路由Id",
"paths": ["匹配的路徑數據"],
"service": {
"id": "關聯的service ID"
}
},
"service": {
"host": "匹配的服務的host",
"id": "匹配服務的ID",
"name": "服務名",
"path": "服務路徑 ",
"port": "服務端口",
"protocol": "服務協議"
},
"consumer": {
"username": "請求業務方的名字"
},
"latencies": {
"proxy": "代理延遲",
"kong": " 網關本身的延遲",
"request": " 請求處理的延遲時長"
},
"client_ip": "業務方IP",
"started_at": " 請求的時間戳"
}
Elasticsearch是一個基于Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基于RESTful web接口。ElasticSearch用于云計算中,能夠達到實時搜索、穩定、可靠、快速。本系統采用ES集群作為日志的持久化組件,既能滿足JSON格式的文本存儲的需求,又能利用Elastic開放的RestFul接口,實現日志的統計查詢和聚合功能。
根據請求的路由id來查詢當日訪問量top5的Api為例,利用Elasticsearch的msearch接口,就可以通過以下post請求來實現,非常靈活便捷。
curl -X POST "http://es_host:9200/_msearch
-H ′Content-Type: application/json′ -d
{"index":"kong","ignore_unavailable":true,"timeout":30000,"preference":1580535845202}
{"aggs":{"top5":{"terms":{"field":"route.id","size":5,"order":{"_count":"desc"}}}},"size":0,"version":true,"stored_fields":["*"],"docvalue_fields":[{"field":"request.headers.date","format":"date_time"},{"field":"startedAt","format":"date_time"}],"query":{"bool":{"must":[{"match_all":{}},{"range":{"startedAt":{"gte":"startTime","lte":"endTime","format":"epoch_millis"}}},{"bool":{"should":["filtersArray"],"minimum_should_match":1}}]}}}
查詢的結果通過解析處理后就可以按照約定的格式發送給前端的Dashboard進行展示;用戶可以決定是在大屏上顯示,還是通過H5頁面嵌入的方式在移動端顯示。以移動端顯示為例,部分效果如圖5所示。

圖5 監控平臺移動端展示Dashboard
為了解決實際私有云環境中API網關的建設及監控運維問題,本文以Kong、Elasticsearch等開源組件為基礎,結合自有編碼,設計并實踐了一套API網關及監控體系,取得了很好的效果。通過API集成網關,私有云可以按照統一格式轉發、配置、管理、監控所有的API請求,實現了API接口的統一管理和運維,減少了開發人員和接口使用方的工作量,也減少了二次人員開發學習的成本。同時,基于Nginx的網關集群技術也在最大程度保證并發的同時,兼顧了響應速度。