本文從百億流量交易系統(tǒng)微服務(wù)網(wǎng)關(guān)(API Gateway)的現(xiàn)狀和面臨的問(wèn)題出發(fā),闡述微服務(wù)架構(gòu)與 API 網(wǎng)關(guān)的關(guān)系,理順流量網(wǎng)關(guān)與業(yè)務(wù)網(wǎng)關(guān)的脈絡(luò),分享API網(wǎng)關(guān)知識(shí)與經(jīng)驗(yàn)。
“計(jì)算機(jī)科學(xué)領(lǐng)域的任何問(wèn)題都可以通過(guò)增加一個(gè)間接的中間層來(lái)解決。”
——David Wheeler
請(qǐng)求接入:作為所有API接口服務(wù)請(qǐng)求的接入點(diǎn),管理所有的接入請(qǐng)求。
業(yè)務(wù)聚合:作為所有后端業(yè)務(wù)服務(wù)的聚合點(diǎn),所有的業(yè)務(wù)服務(wù)都可以在這里被調(diào)用。
中介策略:實(shí)現(xiàn)安全、驗(yàn)證、路由、過(guò)濾、流控、緩存等策略,進(jìn)行一些必要的中介處理。
統(tǒng)一管理:提供配置管理工具,對(duì)所有API服務(wù)的調(diào)用生命周期和相應(yīng)的中介策略進(jìn)行統(tǒng)一管理。
3. API網(wǎng)關(guān)的關(guān)注點(diǎn)
API網(wǎng)關(guān)并不是一個(gè)典型的業(yè)務(wù)系統(tǒng),而是一個(gè)為了讓業(yè)務(wù)系統(tǒng)更專(zhuān)注于業(yè)務(wù)服務(wù)本身,給API服務(wù)提供更多附加能力的一個(gè)中間層。
在設(shè)計(jì)和實(shí)現(xiàn)API網(wǎng)關(guān)時(shí),需要考慮兩個(gè)目標(biāo):
(1)開(kāi)發(fā)維護(hù)簡(jiǎn)單,節(jié)約人力成本和維護(hù)成本。即應(yīng)選擇成熟的簡(jiǎn)單可維護(hù)的技術(shù)體系。
(2)高性能,節(jié)約設(shè)備成本,提高系統(tǒng)吞吐能力。要求我們需要針對(duì)API網(wǎng)關(guān)的特點(diǎn)進(jìn)行一些特定的設(shè)計(jì)和權(quán)衡。
當(dāng)并發(fā)量小的時(shí)候,這些都不是問(wèn)題。一旦系統(tǒng)的API訪問(wèn)量非常大,這些都會(huì)成為關(guān)鍵的問(wèn)題。
海量并發(fā)的API網(wǎng)關(guān)最重要的三個(gè)關(guān)注點(diǎn):
(1)保持大規(guī)模的inbound請(qǐng)求接入能力(長(zhǎng)短連接),比如基于Netty實(shí)現(xiàn)。
(2)大限度地復(fù)用outbound的HTTP連接能力,比如基于HttpClient4的異步HttpClient實(shí)現(xiàn)。
(3)方便靈活地實(shí)現(xiàn)安全、驗(yàn)證、過(guò)濾、聚合、限流、監(jiān)控等各種策略。
1. API網(wǎng)關(guān)的分類(lèi)
如果對(duì)上述的目標(biāo)和關(guān)注點(diǎn)進(jìn)行更深入的思考,那么所有需要考慮的問(wèn)題和功能可以分為兩類(lèi)。
一類(lèi)是全局性的,跟具體的后端業(yè)務(wù)系統(tǒng)和服務(wù)完全無(wú)關(guān)的部分,比如安全策略、全局性流控策略、流量分發(fā)策略等。
一類(lèi)是針對(duì)具體的后端業(yè)務(wù)系統(tǒng),或者是服務(wù)和業(yè)務(wù)有一定關(guān)聯(lián)性的部分,并且一般被直接部署在業(yè)務(wù)服務(wù)的前面。
隨著互聯(lián)網(wǎng)的復(fù)雜業(yè)務(wù)系統(tǒng)的發(fā)展,這兩類(lèi)功能集合逐漸形成了現(xiàn)在常見(jiàn)的兩種網(wǎng)關(guān)系統(tǒng):流量網(wǎng)關(guān)和業(yè)務(wù)網(wǎng)關(guān),如圖7-5所示。
圖7-5
2. 流量網(wǎng)關(guān)與WAF
我們定義全局性的、跟具體的后端業(yè)務(wù)系統(tǒng)和服務(wù)完全無(wú)關(guān)的策略網(wǎng)關(guān),即為流量網(wǎng)關(guān)。這樣流量網(wǎng)關(guān)關(guān)注全局流量的穩(wěn)定與安全,比如防止各類(lèi)SQL注入、黑白名單控制、接入請(qǐng)求到業(yè)務(wù)系統(tǒng)的負(fù)載均衡等,通常有如下通用性的具體功能:
全局性流控;
日志統(tǒng)計(jì);
防止SQL注入;
防止Web攻擊;
屏蔽工具掃描;
黑白名單控制。
通過(guò)這個(gè)功能清單,我們可以發(fā)現(xiàn),流量網(wǎng)關(guān)的功能跟Web應(yīng)用防火墻(WAF)非常類(lèi)似。WAF一般是基于Nginx/OpenResty的ngx_lua模塊開(kāi)發(fā)的Web應(yīng)用防火墻。
一般WAF的代碼很簡(jiǎn)單,專(zhuān)注于使用簡(jiǎn)單、高性能和輕量級(jí)。簡(jiǎn)單地說(shuō)就是在Nginx本身的代理能力以外,添加了安全相關(guān)功能。用一句話描述其原理,就是解析HTTP請(qǐng)求(協(xié)議解析模塊),規(guī)則檢測(cè)(規(guī)則模塊),做不同的防御動(dòng)作(動(dòng)作模塊),并將防御過(guò)程(日志模塊)記錄下來(lái)。
一般的WAF具有如下功能:
防止SQL注入、部分溢出、fuzzing測(cè)試、XSS/SSRF等Web攻擊;
防止Apache Bench之類(lèi)壓力測(cè)試工具的攻擊;
屏蔽常見(jiàn)的掃描黑客工具,比如掃描器;
禁止圖片附件類(lèi)目錄執(zhí)行權(quán)限、防止webshell上傳;
支持IP白名單和黑名單功能,直接拒絕黑名單的IP訪問(wèn);
支持URL白名單,定義不需要過(guò)濾的URL;
支持User-Agent的過(guò)濾、支持CC攻擊防護(hù)、限制單個(gè)URL指定時(shí)間的訪問(wèn)次數(shù);
支持支持Cookie過(guò)濾,URL與URL參數(shù)過(guò)濾;
支持日志記錄,將所有拒絕的操作記錄到日志中。
以上WAF的內(nèi)容主要參考如下兩個(gè)項(xiàng)目:
https://github.com/unixhot/waf;
https://github.com/loveshell/ngx_lua_waf。
流量網(wǎng)關(guān)的開(kāi)源實(shí)例還可以參考著名的開(kāi)源項(xiàng)目Kong(基于OpenResty)。
3. 業(yè)務(wù)網(wǎng)關(guān)
我們定義針對(duì)具體的后端業(yè)務(wù)系統(tǒng),或者是服務(wù)和業(yè)務(wù)有一定關(guān)聯(lián)性的策略網(wǎng)關(guān),即為業(yè)務(wù)網(wǎng)關(guān)。比如,針對(duì)某個(gè)系統(tǒng)、某個(gè)服務(wù)或某個(gè)用戶分類(lèi)的流控策略,針對(duì)某一類(lèi)服務(wù)的緩存策略,針對(duì)某個(gè)具體系統(tǒng)的權(quán)限驗(yàn)證方式,針對(duì)某些用戶條件判斷的請(qǐng)求過(guò)濾,針對(duì)具體幾個(gè)相關(guān)API的數(shù)據(jù)聚合封裝,等等。
業(yè)務(wù)網(wǎng)關(guān)一般部署在流量網(wǎng)關(guān)之后、業(yè)務(wù)系統(tǒng)之前,比流量網(wǎng)關(guān)更靠近業(yè)務(wù)系統(tǒng)。我們大部分情況下說(shuō)的API網(wǎng)關(guān),狹義上指的是業(yè)務(wù)網(wǎng)關(guān)。如果系統(tǒng)的規(guī)模不大,我們也會(huì)將兩者合二為一,使用一個(gè)網(wǎng)關(guān)來(lái)處理所有的工作。
常見(jiàn)的開(kāi)源網(wǎng)關(guān)如圖7-6所示。
圖7-6
目前常見(jiàn)的開(kāi)源網(wǎng)關(guān)大致上按照語(yǔ)言分類(lèi)有如下幾類(lèi)。
Nginx+Lua:Open Resty、Kong、Orange、Abtesting Gateway等;
Java:Zuul/Zuul 2、Spring Cloud Gateway、Kaazing KWG、gravitee、Dromara soul等;
Go:Janus、fagongzi、Grpc-Gateway;
.NET:Ocelot;
Node.js:Express Gateway、MicroGateway。
按照使用范圍、成熟度等來(lái)劃分,主流的有4個(gè):OpenResty、Kong、Zuul/Zuul 2、Spring Cloud Gateway,此外fagongzi API網(wǎng)關(guān)最近也獲得不少關(guān)注。
1. Nginx+Lua網(wǎng)關(guān)
OpenResty
項(xiàng)目地址:http://openresty.org/
OpenResty基于Nginx,集成了Lua語(yǔ)言和Lua的各種工具庫(kù)、可用的第三方模塊,這樣我們就在Nginx既有的高效HTTP處理的基礎(chǔ)上,同時(shí)獲得了Lua提供的動(dòng)態(tài)擴(kuò)展能力。因此,我們可以做出各種符合我們需要的網(wǎng)關(guān)策略的Lua腳本,以其為基礎(chǔ)實(shí)現(xiàn)網(wǎng)關(guān)系統(tǒng)。
Kong
項(xiàng)目地址:https://konghq.com/與https://github.com/kong/kong
Kong基于OpenResty,是一個(gè)云原生、快速、可擴(kuò)展、分布式的微服務(wù)抽象層(MicroserviceAbstraction Layer),也叫API網(wǎng)關(guān)(API Gateway),在Service Mesh里也叫API中間件(API Middleware)。
Kong開(kāi)源于2015年,核心價(jià)值在于其高性能和擴(kuò)展性。從全球5000強(qiáng)的組織統(tǒng)計(jì)數(shù)據(jù)來(lái)看,Kong是現(xiàn)在依然在維護(hù)的、在生產(chǎn)環(huán)境使用最廣泛的網(wǎng)關(guān)。
核心優(yōu)勢(shì)如下。
可擴(kuò)展:可以方便地通過(guò)添加節(jié)點(diǎn)實(shí)現(xiàn)水平擴(kuò)展,這意味著可以在很低的延遲下支持很大的系統(tǒng)負(fù)載。
模塊化:可以通過(guò)添加新的插件來(lái)擴(kuò)展Kong的能力,這些插件可以通過(guò)RESTful Admin API來(lái)安裝和配置。
在任何基礎(chǔ)架構(gòu)上運(yùn)行:Kong在任何地方都能運(yùn)行,比如在云或混合環(huán)境中部署Kong,或者單個(gè)/全球的數(shù)據(jù)中心。
ABTestingGateway
項(xiàng)目地址:https://github.com/CNSRE/ABTestingGateway
ABTestingGateway是一個(gè)可以動(dòng)態(tài)設(shè)置分流策略的網(wǎng)關(guān),關(guān)注與灰度發(fā)布相關(guān)的領(lǐng)域,基于Nginx和ngx-lua開(kāi)發(fā),使用Redis作為分流策略數(shù)據(jù)庫(kù),可以實(shí)現(xiàn)動(dòng)態(tài)調(diào)度功能。
ABTestingGateway是新浪微博內(nèi)部的動(dòng)態(tài)路由系統(tǒng)dygateway的一部分,目前已經(jīng)開(kāi)源。在以往的基于Nginx實(shí)現(xiàn)的灰度系統(tǒng)中,分流邏輯往往通過(guò)rewrite階段的if和rewrite指令等實(shí)現(xiàn),優(yōu)點(diǎn)是性能較高,缺點(diǎn)是功能受限、容易出錯(cuò),以及轉(zhuǎn)發(fā)規(guī)則固定,只能靜態(tài)分流。ABTestingGateway則采用 ngx-lua,通過(guò)啟用lua-shared-dict和lua-resty-lock作為系統(tǒng)緩存和緩存鎖,系統(tǒng)獲得了較為接近原生Nginx轉(zhuǎn)發(fā)的性能。
功能特性如下。
支持多種分流方式,目前包括iprange、uidrange、uid尾數(shù)和指定uid分流;
支持多級(jí)分流,動(dòng)態(tài)設(shè)置分流策略,即時(shí)生效,無(wú)須重啟;
可擴(kuò)展性,提供了開(kāi)發(fā)框架,開(kāi)發(fā)者可以靈活添加新的分流方式,實(shí)現(xiàn)二次開(kāi)發(fā);
高性能,壓測(cè)數(shù)據(jù)接近原生Nginx轉(zhuǎn)發(fā);
灰度系統(tǒng)配置寫(xiě)在Nginx配置文件中,方便管理員配置;
適用于多種場(chǎng)景:灰度發(fā)布、AB測(cè)試和負(fù)載均衡等。
據(jù)了解,美團(tuán)網(wǎng)內(nèi)部的Oceanus也是基于Nginx和ngx-lua擴(kuò)展實(shí)現(xiàn)的,主要提供服務(wù)注冊(cè)與發(fā)現(xiàn)、動(dòng)態(tài)負(fù)載均衡、可視化管理、定制化路由、安全反扒、Session ID復(fù)用、熔斷降級(jí)、一鍵截流和性能統(tǒng)計(jì)等功能。
2. 基于Java語(yǔ)言的網(wǎng)關(guān)
Zuul/Zuul2
項(xiàng)目地址:https://github.com/Netflix/zuul
Zuul是Netflix開(kāi)源的API網(wǎng)關(guān)系統(tǒng),它的主要設(shè)計(jì)目標(biāo)是動(dòng)態(tài)路由、監(jiān)控、彈性和安全。
Zuul的內(nèi)部原理可以簡(jiǎn)單看作很多不同功能filter的集合(作為對(duì)比,ESB也可以簡(jiǎn)單被看作管道和過(guò)濾器的集合)。這些過(guò)濾器(filter)可以使用Groovy或其他基于JVM的腳本編寫(xiě)(當(dāng)然Java也可以編寫(xiě)),放置在指定的位置,然后可以被Zuul Server輪詢(xún),發(fā)現(xiàn)變動(dòng)后動(dòng)態(tài)加載并實(shí)時(shí)生效。Zuul目前有1.x和2.x兩個(gè)版本,這兩個(gè)版本的差別很大。
Zuul 1.x基于同步I/O,也是Spring Cloud全家桶的一部分,可以方便地配合Spring Boot/SpringCloud配置和使用。
在Zuul 1.x里,F(xiàn)ilter的種類(lèi)和處理流程如圖7-7所示,最主要的就是pre、routing、post這三種過(guò)濾器,分別作用于調(diào)用業(yè)務(wù)服務(wù)API之前的請(qǐng)求處理、直接響應(yīng)、調(diào)用業(yè)務(wù)服務(wù)API之后的響應(yīng)處理。
Zuul 2.x大的改進(jìn)就是基于Netty Server實(shí)現(xiàn)了異步I/O來(lái)接入請(qǐng)求,同時(shí)基于Netty Client實(shí)現(xiàn)了到后端業(yè)務(wù)服務(wù)API的請(qǐng)求。這樣就可以實(shí)現(xiàn)更高的性能、更低的延遲。此外也調(diào)整了Filter類(lèi)型,將原來(lái)的三個(gè)核心Filter顯式命名為Inbound Filter、Endpoint Filter和Outbound Filter,如圖7-8所示。
圖7-7
圖7-8
Zuul 2.x的核心功能:服務(wù)發(fā)現(xiàn)、負(fù)載均衡、連接池、狀態(tài)分類(lèi)、重試、請(qǐng)求憑證、HTTP/2、TLS、代理協(xié)議、GZip、WebSocket。
SpringCloud Gateway
項(xiàng)目地址:https://github.com/spring-cloud/spring-cloud-gateway/
Spring Cloud Gateway基于Java 8、Spring 5.0、Spring Boot 2.0、Project Reactor,發(fā)展得比Zuul 2要早,目前也是Spring Cloud全家桶的一部分。
Spring Cloud Gateway可以看作一個(gè)Zuul 1.x的升級(jí)版和代替品,比Zuul 2更早地使用Netty實(shí)現(xiàn)異步I/O,從而實(shí)現(xiàn)了一個(gè)簡(jiǎn)單、比Zuul 1.x更高效的、與Spring Cloud緊密配合的API網(wǎng)關(guān)。
Spring Cloud Gateway里明確地區(qū)分了Router和Filter,內(nèi)置了非常多的開(kāi)箱即用功能,并且都可以通過(guò)Spring Boot配置或手工編碼鏈?zhǔn)秸{(diào)用來(lái)使用。
比如內(nèi)置了10種Router,直接配置就可以隨心所欲地根據(jù)Header、Path、Host或Query來(lái)做路由。
核心特性:
通過(guò)請(qǐng)求參數(shù)匹配路由;
通過(guò)斷言和過(guò)濾器實(shí)現(xiàn)路由;
與Hystrix熔斷集成;
與Spring Cloud DiscoveryClient集成;
非常方便地實(shí)現(xiàn)斷言和過(guò)濾器;
請(qǐng)求限流;
路徑重寫(xiě)。
graviteeGateway
項(xiàng)目地址:https://gravitee.io/與https://github.com/gravitee-io/gravitee-gateway
KaazingWebSocket Gateway
項(xiàng)目地址:
https://github.com/kaazing/gateway與https://kaazing.com/products/websocket-gateway/
Kaazing WebSocket Gateway是一個(gè)專(zhuān)門(mén)針對(duì)和處理WebSocket的網(wǎng)關(guān),宣稱(chēng)提供世界一流的企業(yè)級(jí)WebSocket服務(wù)能力。具體如下特性:
標(biāo)準(zhǔn)WebSocket支持,支持全雙工的雙向數(shù)據(jù)投遞;
線性擴(kuò)展,無(wú)狀態(tài)架構(gòu)意味著可以部署更多機(jī)器來(lái)擴(kuò)展服務(wù)能力;
驗(yàn)證,鑒權(quán),單點(diǎn)登錄支持,跨域訪問(wèn)控制;
SSL/TLS加密支持;
WebSocket keepalive和TCP半開(kāi)半關(guān)探測(cè);
通過(guò)負(fù)載均衡和集群實(shí)現(xiàn)高可用;
Docker支持;
JMS/AMQP等支持;
IP白名單;
自動(dòng)重連和消息可靠接受保證;
Fanout處理策略;
實(shí)時(shí)緩存等。
Dromara soul
項(xiàng)目地址:https://github.com/Dromara/soul。
Soul是一個(gè)異步的、高性能的、跨語(yǔ)言的、響應(yīng)式的API網(wǎng)關(guān),提供了統(tǒng)一的HTTP訪問(wèn)。
支持各種語(yǔ)言,無(wú)縫集成Dubbo和SpringCloud;
豐富的插件支持鑒權(quán)、限流、熔斷、防火墻等;
網(wǎng)關(guān)多種規(guī)則動(dòng)態(tài)配置,支持各種策略配置;
插件熱插拔,易擴(kuò)展;
支持集群部署,支持A/B Test。
3. 基于Go語(yǔ)言的網(wǎng)關(guān)
fagongzi
項(xiàng)目地址:https://github.com/fagongzi/gateway
fagongzi Gateway是一個(gè)Go實(shí)現(xiàn)的功能全面的API網(wǎng)關(guān),自帶了一個(gè)Rails實(shí)現(xiàn)的Web UI管理界面。
功能特性:流量控制、熔斷、負(fù)載均衡、服務(wù)發(fā)現(xiàn)、插件機(jī)制、路由(分流,復(fù)制流量)、API聚合、API參數(shù)校驗(yàn)、API訪問(wèn)控制(黑白名單)、API默認(rèn)返回值、API定制返回值、API結(jié)果Cache、JWT認(rèn)證、API Metric導(dǎo)入Prometheus、API失敗重試、后端Server的健康檢查、開(kāi)放管理API(gRPC、RESTful)、支持WebSocket協(xié)議。
Janus
項(xiàng)目地址:https://github.com/hellofresh/janus
Janus是一個(gè)輕量級(jí)的API網(wǎng)關(guān)和管理平臺(tái),能實(shí)現(xiàn)控制誰(shuí)、什么時(shí)候、如何訪問(wèn)這些REST API,同時(shí)它也記錄了所有的訪問(wèn)交互細(xì)節(jié)和錯(cuò)誤。使用Go實(shí)現(xiàn)API網(wǎng)關(guān)的一個(gè)好處在于,一般只需要一個(gè)單獨(dú)的二進(jìn)制文件即可運(yùn)行,沒(méi)有復(fù)雜的依賴(lài)關(guān)系。功能特性:
熱加載配置,不需要重啟網(wǎng)關(guān)進(jìn)程;
HTTP連接的優(yōu)雅關(guān)閉;
支持OpenTracing,從而可以進(jìn)行分布式跟蹤;
支持HTTP/2;
可以針對(duì)每一個(gè)API實(shí)現(xiàn)斷路器;
重試機(jī)制;
流控,可以針對(duì)每一個(gè)用戶或key;
CORS過(guò)濾,可以針對(duì)具體的API;
多種開(kāi)箱即用的驗(yàn)證協(xié)議支持,比如JWT、OAuth 2.0和Basic Auth;
Docker Image支持。
4. .NET
Ocelot
項(xiàng)目地址:https://github.com/ThreeMammals/Ocelot
功能特性:路由、請(qǐng)求聚合、服務(wù)發(fā)現(xiàn)(基于Consul或Eureka)、服務(wù)Fabric、WebSockets、驗(yàn)證與鑒權(quán)、流控、緩存、重試策略與QoS、負(fù)載均衡、日志與跟蹤、請(qǐng)求頭、Query字符串轉(zhuǎn)換、自定義的中間處理、配置和管理REST API。
5. Node.js
Express Gateway
項(xiàng)目地址:
https://github.com/ExpressGateway/express-gateway與https://www.express-gateway.io/
Express Gateway是一個(gè)基于Node.js開(kāi)發(fā),使用Express和Express中間件實(shí)現(xiàn)的REST API網(wǎng)關(guān)。
功能特性:
動(dòng)態(tài)中心化配置;
API消費(fèi)者和憑證管理;
插件機(jī)制;
分布式數(shù)據(jù)存儲(chǔ);
命令行工具CLI。
MicroGateway
項(xiàng)目地址:
https://github.com/strongloop/microgateway與https://developer.ibm.com/apiconnect
StrongLoop是IBM的一個(gè)子公司,MicroGateway網(wǎng)關(guān)基于Node.js/Express和Nginx構(gòu)建,作為IBM API Connect,同時(shí)也是IBM云生態(tài)的一部分。MicroGateway是一個(gè)聚焦于開(kāi)發(fā)者,可擴(kuò)展的網(wǎng)關(guān)框架,它可以增強(qiáng)我們對(duì)微服務(wù)和API的訪問(wèn)能力。
核心特性:
安全和控制,基于Swagger(OpenAPI)規(guī)范;
內(nèi)置了多種網(wǎng)關(guān)策略,API Key驗(yàn)證、流控、OAuth 2.0、JavaScript腳本支持;
使用Swagger擴(kuò)展(API Assembly)實(shí)現(xiàn)網(wǎng)關(guān)策略(安全、路由、集成等);
方便地自定義網(wǎng)關(guān)策略。
此外,MicroGateway還有幾個(gè)特性:
通過(guò)集成Swagger,實(shí)現(xiàn)基于Swagger API定義的驗(yàn)證能力;
使用datastore來(lái)保持需要處理的API數(shù)據(jù)模型;
使用一個(gè)流式引擎來(lái)處理多種策略,使API設(shè)計(jì)者可以更好地控制API的生命周期。
核心架構(gòu)如圖7-9所示。
圖7-9
1. OpenResty/Kong/Zuul 2/SpringCloud Gateway重要特性對(duì)比
各項(xiàng)指標(biāo)對(duì)比如表7-1所示。
以限流功能為例:
Spring Cloud Gateway目前提供了基于Redis的Ratelimiter實(shí)現(xiàn),使用的算法是令牌桶算法,通過(guò)YAML文件進(jìn)行配置;
Zuul2可以通過(guò)配置文件配置集群限流和單服務(wù)器限流,也可通過(guò)Filter實(shí)現(xiàn)限流擴(kuò)展;
OpenResty可以使用resty.limit.count、resty.limit.conn、resty.limit.req來(lái)實(shí)現(xiàn)限流功能,可實(shí)現(xiàn)漏桶或令牌通算法;
Kong擁有基礎(chǔ)限流組件,可在基礎(chǔ)組件源代碼基礎(chǔ)上進(jìn)行Lua開(kāi)發(fā)。
對(duì)Zuul/Zuul 2/Spring Cloud Gateway的一些功能點(diǎn)分析可以參考Spring Cloud Gateway作者Spencer Gibb的文章:https://spencergibb.netlify.com/preso/detroit-cf-api-gateway-2017-03/。
2. OpenResty/Kong/Zuul 2/SpringCloudGateway性能測(cè)試對(duì)比
分別使用3臺(tái)4Core、16GB內(nèi)存的機(jī)器,作為API服務(wù)提供者、Gateway、壓力機(jī),使用wrk作為性能測(cè)試工具,對(duì)OpenResty/Kong/Zuul 2/SpringCloud Gateway進(jìn)行簡(jiǎn)單小報(bào)文下的性能測(cè)試,如圖7-10所示。
圖7-10
圖中縱坐標(biāo)軸是QPS,橫軸是一個(gè)Gateway的數(shù)據(jù),每根線是一個(gè)場(chǎng)景下的不同網(wǎng)關(guān)數(shù)據(jù),測(cè)試結(jié)論如下:
實(shí)測(cè)情況是性能SCG~Zuul 2 << OpenResty~< Kong << Direct(直連);
Spring Cloud Gateway、Zuul 2的性能差不多,大概是直連的40%;
OpenResty、Kong的性能差不多,大概是直連的60%~70%;
大并發(fā)下,例如模擬200并發(fā)用戶、1000并發(fā)用戶時(shí),Zuul 2會(huì)有很大概率返回出錯(cuò)。
1. 開(kāi)源網(wǎng)關(guān)的測(cè)試分析
脫離場(chǎng)景談性能,都是“耍流氓”。性能就像溫度,不同的場(chǎng)合下標(biāo)準(zhǔn)是不一樣的。同樣是18攝氏度,老人覺(jué)得冷,年輕人覺(jué)得合適,企鵝覺(jué)得熱,冰箱里的蔬菜可能容易壞了。
同樣基準(zhǔn)條件下,不同的參數(shù)和軟件,相對(duì)而言的橫向比較才有價(jià)值。比如同樣的機(jī)器(比如16GB內(nèi)存/4核),同樣的Server(用Spring Boot,配置路徑為api/hello,返回一個(gè)helloworld),同樣的壓測(cè)方式和工具(比如用wrk,10個(gè)線程,20個(gè)并發(fā)連接)。我們測(cè)試直接訪問(wèn)Server得到的極限QPS(QPS-Direct,29K);配置了一個(gè)Spring Cloud Gateway做網(wǎng)關(guān)訪問(wèn)的極限QPS(QPS-SCG,11K);同樣方式配置一個(gè)Zuul 2做網(wǎng)關(guān)壓測(cè)得到的極限QPS(QPS-Zuul2,13K);Kong得到的極限QPS(QPS-Kong,21K);OpenResty得到的極限QPS(QPS-OR,19K)。這個(gè)對(duì)比就有意義了。
Kong的性能非常不錯(cuò),非常適合做流量網(wǎng)關(guān),并且對(duì)于service、route、upstream、consumer、plugins的抽象,也是自研網(wǎng)關(guān)值得借鑒的。
對(duì)于復(fù)雜系統(tǒng),不建議業(yè)務(wù)網(wǎng)關(guān)用Kong,或者更明確地說(shuō)是不建議在Java技術(shù)棧的系統(tǒng)深度定制Kong或OpenResty,主要是出于工程性方面的考慮。舉個(gè)例子:假如我們有多個(gè)不同業(yè)務(wù)線,鑒權(quán)方式五花八門(mén),都是與業(yè)務(wù)多少有點(diǎn)相關(guān)的。這時(shí)如果把鑒權(quán)在網(wǎng)關(guān)實(shí)現(xiàn),就需要維護(hù)大量的Lua腳本,引入一個(gè)新的復(fù)雜技術(shù)棧是一個(gè)成本不低的事情。
Spring Cloud Gateway/Zuul 2對(duì)于Java技術(shù)棧來(lái)說(shuō)比較方便,可以依賴(lài)業(yè)務(wù)系統(tǒng)的一些通用的類(lèi)庫(kù)。Lua不方便,不光是語(yǔ)言的問(wèn)題,更是復(fù)用基礎(chǔ)設(shè)施的問(wèn)題。另外,對(duì)于網(wǎng)關(guān)系統(tǒng)來(lái)說(shuō),性能不會(huì)差一個(gè)數(shù)量級(jí),問(wèn)題不大,多加2臺(tái)機(jī)器就可以“搞定”。
從測(cè)試的結(jié)果來(lái)看,如果后端API服務(wù)的延遲都較低(例如2ms級(jí)別),直連的吞吐量假如是100QPS,Kong可以達(dá)到60QPS,OpenResty是50QPS,Zuul 2和Spring CloudGateway大概是35QPS,如果服務(wù)本身的延遲(latency)大一點(diǎn),那么這些差距會(huì)逐步縮小。
目前來(lái)看Zuul 2的“坑”還是比較多的:
(1)剛出不久,不成熟,沒(méi)什么文檔,還沒(méi)有太多的實(shí)際應(yīng)用案例。
(2)高并發(fā)時(shí)出錯(cuò)率較高,1000并發(fā)時(shí)我們的測(cè)試場(chǎng)景有近50%的出錯(cuò)率。
簡(jiǎn)單使用或輕度定制業(yè)務(wù)網(wǎng)關(guān)系統(tǒng),目前建議使用Spring CloudGateway作為基礎(chǔ)骨架。
2. 各類(lèi)網(wǎng)關(guān)的Demo與測(cè)試
以上測(cè)試用到的模擬服務(wù)和網(wǎng)關(guān)Demo代碼,大部分可以在這里找到:
https://github.com/ kimmking/atlantis。
我們使用Vert.x實(shí)現(xiàn)了一個(gè)簡(jiǎn)單網(wǎng)關(guān),性能跟Zuul 2和Spring Cloud Gateway差不多。另外也簡(jiǎn)單模擬了一個(gè)Node.js做的網(wǎng)關(guān)Demo,加了keep-alive和pool,Demo的性能測(cè)試結(jié)果大概是直連的1/9,也就是Spring Cloud Gateway或Zuul 2的1/4左右。
1. 百億流量系統(tǒng)面對(duì)的業(yè)務(wù)現(xiàn)狀
百億流量系統(tǒng)面對(duì)的業(yè)務(wù)現(xiàn)狀如圖7-11所示。
圖7-11
我們目前面臨的現(xiàn)狀是日常十幾萬(wàn)的并發(fā)在線長(zhǎng)連接數(shù)(不算短連接),每天長(zhǎng)連接總數(shù)為3000萬(wàn)+,每天API的調(diào)用次數(shù)超過(guò)100億次,每天交易訂單數(shù)為1.5億個(gè)。
在這種情況下,API網(wǎng)關(guān)設(shè)計(jì)的一個(gè)重要目標(biāo)就是:如何借助API網(wǎng)關(guān)為各類(lèi)客戶提供精準(zhǔn)、專(zhuān)業(yè)、個(gè)性化的服務(wù),保障客戶實(shí)時(shí)地獲得業(yè)務(wù)系統(tǒng)的數(shù)據(jù)和業(yè)務(wù)能力。
2. 網(wǎng)關(guān)系統(tǒng)與其他系統(tǒng)的關(guān)系
某交易系統(tǒng)的API網(wǎng)關(guān)系統(tǒng)與其他系統(tǒng)的關(guān)系大致如圖7-12所示。
圖7-12
3. 網(wǎng)關(guān)系統(tǒng)典型的應(yīng)用場(chǎng)景
我們的API網(wǎng)關(guān)系統(tǒng)為Web端、移動(dòng)App端客戶提供服務(wù),也為大量API客戶提供API調(diào)用服務(wù),同時(shí)支持REST API和WebSocket協(xié)議。
作為實(shí)時(shí)交易系統(tǒng)的前置系統(tǒng),必須精準(zhǔn)及時(shí)為客戶提供最新的行情和交易信息。一旦出現(xiàn)數(shù)據(jù)的延遲或錯(cuò)誤,都會(huì)給客戶造成無(wú)法挽回的損失。
另外針對(duì)不同的客戶和渠道,網(wǎng)關(guān)系統(tǒng)需要提供不同的安全、驗(yàn)證、流控、緩存策略,同時(shí)可以隨時(shí)聚合不同視角的數(shù)據(jù)進(jìn)行預(yù)處理,保障系統(tǒng)的穩(wěn)定可靠和數(shù)據(jù)的實(shí)時(shí)精確。
4. 交易系統(tǒng)API的特點(diǎn)
作為一個(gè)全球性的交易系統(tǒng),我們的API特點(diǎn)總結(jié)如下。
訪問(wèn)非常集中:最核心的一組API占據(jù)了訪問(wèn)量的一半以上;
訪問(wèn)非常頻繁:QPS非常高,日均訪問(wèn)量非常大;
數(shù)據(jù)格式固定:交易系統(tǒng)處理的數(shù)據(jù)格式非常固定;
報(bào)文數(shù)據(jù)量小:每次請(qǐng)求傳輸?shù)臄?shù)據(jù)一般不超過(guò)10KB;
用戶全世界分布:客戶分布在全世界的各個(gè)國(guó)家;
分內(nèi)部調(diào)用和外部調(diào)用:除了API客戶直接調(diào)用的API,其他的API都是由內(nèi)部其他系統(tǒng)調(diào)用的;
7×24小時(shí)不間斷服務(wù):系統(tǒng)需要提供高可用、不間斷的服務(wù)能力,以滿足不同時(shí)區(qū)客戶的交易和自動(dòng)化策略交易;
外部用戶有一定技術(shù)能力:外部API客戶,一般是集成我們的API,實(shí)現(xiàn)自己的交易系統(tǒng)。
5. 交易系統(tǒng)API網(wǎng)關(guān)面臨的問(wèn)題
問(wèn)題1:流量不斷增加。
如何合理控制流量,如何應(yīng)對(duì)突發(fā)流量,如何大限度地保障系統(tǒng)穩(wěn)定,都是重要的問(wèn)題。特別是網(wǎng)關(guān)作為一個(gè)直接面對(duì)客戶的系統(tǒng),出現(xiàn)的任何問(wèn)題都會(huì)放大百倍。很多千奇百怪的從來(lái)沒(méi)人遇到的問(wèn)題隨時(shí)都可能出現(xiàn)。
問(wèn)題2:網(wǎng)關(guān)系統(tǒng)越來(lái)越復(fù)雜。
現(xiàn)有的業(yè)務(wù)網(wǎng)關(guān)經(jīng)過(guò)多年發(fā)展,里面有大量的業(yè)務(wù)嵌入,并且存在多個(gè)不同的業(yè)務(wù)網(wǎng)關(guān),相互之間沒(méi)有任何關(guān)系,也沒(méi)有沉淀出基礎(chǔ)設(shè)施。
同時(shí)技術(shù)債務(wù)太多,系統(tǒng)里硬編碼實(shí)現(xiàn)了全局性網(wǎng)關(guān)策略及很多業(yè)務(wù)規(guī)則,導(dǎo)致維護(hù)成本較大。
問(wèn)題3:API網(wǎng)關(guān)管理比較困難。
海量并發(fā)下API的監(jiān)控指標(biāo)設(shè)計(jì)和數(shù)據(jù)的收集也是一個(gè)不小的問(wèn)題。7×24小時(shí)運(yùn)行的技術(shù)支持也導(dǎo)致維護(hù)成本較高。
問(wèn)題4:選擇推送還是拉取。
使用短連接還是長(zhǎng)連接,REST API還是WebSocket?業(yè)務(wù)渠道較多(多個(gè)不同產(chǎn)品線的Web、App、API等形成十幾個(gè)不同的渠道),導(dǎo)致用戶的使用行為難以控制。
1. API網(wǎng)關(guān)1.0
我們的API網(wǎng)關(guān)1.0版本是多年前開(kāi)發(fā)的,是直接使用OpenResty定制的,全局的安全測(cè)試、流量的路由轉(zhuǎn)發(fā)策略、針對(duì)不同級(jí)別的限流等都是直接用Lua腳本實(shí)現(xiàn)。
這樣就導(dǎo)致在經(jīng)歷了業(yè)務(wù)飛速發(fā)展以后,系統(tǒng)里存在非常多的相同功能或不同功能的Lua腳本,每次上線或維護(hù)都需要找到受影響的其中幾個(gè)或幾十個(gè)Lua腳本,進(jìn)行策略調(diào)整,非常不方便,策略控制的粒度也不夠細(xì)。
2. API網(wǎng)關(guān)2.0
在區(qū)分了流量網(wǎng)關(guān)和業(yè)務(wù)網(wǎng)關(guān)以后,2017年開(kāi)始實(shí)現(xiàn)了流量網(wǎng)關(guān)和業(yè)務(wù)網(wǎng)關(guān)的分離,流量網(wǎng)關(guān)繼續(xù)使用OpenResty定制,只保留少量全局性、不經(jīng)常改動(dòng)的配置功能和對(duì)應(yīng)的Lua腳本。
業(yè)務(wù)網(wǎng)關(guān)使用Vert.x實(shí)現(xiàn)的Java系統(tǒng),部署在流量網(wǎng)關(guān)和后端業(yè)務(wù)服務(wù)系統(tǒng)之間,利用Vert.x的響應(yīng)式編程能力和異步非阻塞I/O能力、分布式部署的擴(kuò)展能力,初步解決了問(wèn)題1和問(wèn)題2,如圖7-13所示。
圖7-13
Vert.x是一個(gè)基于事件驅(qū)動(dòng)和異步非阻塞I/O、運(yùn)行于JVM上的框架,如圖7-14所示。在Vert.x里,Verticle是最基礎(chǔ)的開(kāi)發(fā)和部署單元,不同的Vert.x可以通過(guò)Event Bus傳遞數(shù)據(jù),進(jìn)而方便地實(shí)現(xiàn)高并發(fā)性能的網(wǎng)絡(luò)程序。關(guān)于Vert.x原理的分析可以參考阿里架構(gòu)師宿何的blog:
https://www.sczyh40.com/tags/Vert-x/。
圖7-14
Vert.x同時(shí)很好地支持了WebSocket協(xié)議,所以可以方便地實(shí)現(xiàn)支持REST API和WebSocket、完全異步的網(wǎng)關(guān)系統(tǒng),如圖7-15所示。
圖7-15
一個(gè)高性能的API網(wǎng)關(guān)系統(tǒng),緩存是必不可少的部分。無(wú)論分發(fā)冷熱數(shù)據(jù),降低對(duì)業(yè)務(wù)系統(tǒng)的壓力,還是作為中間數(shù)據(jù)源,為服務(wù)聚合提供高效可復(fù)用的業(yè)務(wù)數(shù)據(jù),緩存都發(fā)揮了巨大作用。
3. API網(wǎng)關(guān)的日常監(jiān)控
我們使用多種工具對(duì)API進(jìn)行監(jiān)控和管理,包括全鏈路訪問(wèn)跟蹤、連接數(shù)統(tǒng)計(jì)分析、全世界重要國(guó)家和城市的波測(cè)訪問(wèn)統(tǒng)計(jì)。網(wǎng)關(guān)技術(shù)團(tuán)隊(duì)每時(shí)每刻都關(guān)注著數(shù)據(jù)的變化趨勢(shì)。各個(gè)業(yè)務(wù)系統(tǒng)研發(fā)團(tuán)隊(duì)每天安排專(zhuān)人關(guān)注自己系統(tǒng)的API性能(吞吐量和延遲),推進(jìn)性能問(wèn)題解決和持續(xù)優(yōu)化。這就初步解決了問(wèn)題3。
4. 推薦外部客戶使用WebSocket和API SDK
由于外部客戶需要自己通過(guò)API網(wǎng)關(guān)調(diào)用API服務(wù)來(lái)集成業(yè)務(wù)服務(wù)能力到自己的系統(tǒng)。各個(gè)客戶的技術(shù)能力和系統(tǒng)處理能力有較大差異,使用行為也不同。對(duì)于不斷發(fā)展變動(dòng)的交易業(yè)務(wù)數(shù)據(jù),客戶調(diào)用API頻率太低會(huì)影響數(shù)據(jù)實(shí)時(shí)性,調(diào)用頻率太高則可能會(huì)浪費(fèi)雙方的系統(tǒng)資源。同時(shí)利用WebSocket的消息推送特點(diǎn),我們可以在網(wǎng)關(guān)系統(tǒng)控制客戶接收消息的頻率、單個(gè)用戶的連接數(shù)量等,隨時(shí)根據(jù)業(yè)務(wù)系統(tǒng)的情況動(dòng)態(tài)進(jìn)行策略調(diào)整。綜合考慮,WebSocket是一個(gè)比REST API更加實(shí)時(shí)可靠、更加易于管理的方式。另外對(duì)于習(xí)慣使用REST API的客戶,我們也通過(guò)將各種常見(jiàn)使用場(chǎng)景封裝成多種不同語(yǔ)言的API SDK(包括Java/C++/C#/Python),進(jìn)而統(tǒng)一用戶的API調(diào)用方式和行為。在研發(fā)、產(chǎn)品、運(yùn)營(yíng)各方的配合下,逐步協(xié)助客戶使用WebSocket協(xié)議和API SDK,基本解決了問(wèn)題4。
5. API網(wǎng)關(guān)的性能優(yōu)化
API網(wǎng)關(guān)系統(tǒng)作為API服務(wù)的統(tǒng)一接入點(diǎn),為了給用戶提供最優(yōu)質(zhì)的用戶體驗(yàn),必須長(zhǎng)期做性能優(yōu)化工作。不僅API網(wǎng)關(guān)自己做優(yōu)化,同時(shí)可以根據(jù)監(jiān)控情況,時(shí)刻發(fā)現(xiàn)各業(yè)務(wù)系統(tǒng)的API服務(wù)能力,以此為出發(fā)點(diǎn),推動(dòng)各個(gè)業(yè)務(wù)系統(tǒng)不斷優(yōu)化API性能。
舉一個(gè)具體的例子,某個(gè)網(wǎng)關(guān)系統(tǒng)連接經(jīng)常強(qiáng)烈抖動(dòng)(如圖7-16所示),嚴(yán)重影響系統(tǒng)的穩(wěn)定性、浪費(fèi)系統(tǒng)資源,經(jīng)過(guò)排除發(fā)現(xiàn):
(1)有爬蟲(chóng)IP不斷爬取我們的交易數(shù)據(jù),而且這些IP所在網(wǎng)段都沒(méi)有在平臺(tái)產(chǎn)生任何實(shí)際交易,最高單爬蟲(chóng)IP的每日新建連接近100萬(wàn)次,平均每秒十幾次。
(2)有部分API客戶的程序存在bug,而且處理速度有限,不斷地重復(fù)“斷開(kāi)并重新連接”,再?lài)L試重新對(duì)API數(shù)據(jù)進(jìn)行處理,嚴(yán)重影響了客戶的用戶體驗(yàn)。
針對(duì)如上分析,我們采取了如下處理方式:
(1)對(duì)于每天認(rèn)定的爬蟲(chóng)IP,加入黑名單,直接在流量網(wǎng)關(guān)限制其訪問(wèn)我們的API網(wǎng)關(guān)。
(2)對(duì)于存在bug的API客戶,協(xié)助對(duì)方進(jìn)行問(wèn)題定位和bug修復(fù),增強(qiáng)客戶使用信心。
(3)對(duì)于處理速度和技術(shù)能力有限的客戶,基于定制的WebSocket服務(wù),使用滑動(dòng)時(shí)間窗口算法,在業(yè)務(wù)數(shù)據(jù)變化非常大時(shí),對(duì)分發(fā)的消息進(jìn)行批量?jī)?yōu)化。
圖7-16
(4)對(duì)于未登錄和識(shí)別身份的API調(diào)用,流量網(wǎng)關(guān)實(shí)現(xiàn)全局的流控策略,增加緩存時(shí)間和限制調(diào)用次數(shù),保障系統(tǒng)穩(wěn)定。
(5)業(yè)務(wù)網(wǎng)關(guān)根據(jù)API服務(wù)的重要等級(jí)和客戶的分類(lèi),進(jìn)一步細(xì)化和實(shí)時(shí)控制網(wǎng)關(guān)策略,大限度地保障核心業(yè)務(wù)和客戶的使用。
從監(jiān)控圖表可以看到,優(yōu)化之后的效果非常明顯,系統(tǒng)穩(wěn)定,連接數(shù)平穩(wěn)。
本文節(jié)選自《高可用可伸縮微服務(wù)架構(gòu):基于Dubbo、Spring Cloud和Service Mesh》一書(shū),程超,梁桂釗,秦金衛(wèi),方志斌,張逸等著。
分享標(biāo)題:百億流量微服務(wù)網(wǎng)關(guān)的設(shè)計(jì)與實(shí)現(xiàn)-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://www.chinadenli.net/article40/dgiiho.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開(kāi)發(fā)、服務(wù)器托管、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、外貿(mào)建站、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容