架構(gòu)師如何選型分布式業(yè)務(wù)網(wǎng)關(guān)
在日常工作中,不同的場(chǎng)合下,我們可能都會(huì)聽說網(wǎng)關(guān)的概念,當(dāng)然通常是指業(yè)務(wù)網(wǎng)關(guān)(API網(wǎng)關(guān)),負(fù)責(zé)API的輸入和輸出。有了業(yè)務(wù)網(wǎng)關(guān)之后,各個(gè)API服務(wù)提供者可以專注于自己的業(yè)務(wù)邏輯處理,而API網(wǎng)關(guān)更專注于安全、流量、路由等問題。從功能層次我們又會(huì)聯(lián)想到一個(gè)概念——代理。網(wǎng)關(guān)與代理的區(qū)別:代理本質(zhì)是數(shù)據(jù)的透?jìng)?,協(xié)議不會(huì)發(fā)生變化;網(wǎng)關(guān)在數(shù)據(jù)透?jìng)鞯谋尘跋?,還會(huì)涉及協(xié)議的轉(zhuǎn)換,比如從HTTP到Dubbo。
那么作為一名架構(gòu)師,我們?cè)撊绾芜x型“業(yè)務(wù)網(wǎng)關(guān)”呢?我們自己先要學(xué)會(huì)做技術(shù)選型,自己預(yù)期有一個(gè)技術(shù)成本的預(yù)判,比如我推薦使用Spring Cloud Alibaba+Spring Gateway,就是我自己作為一個(gè)架構(gòu)師的技術(shù)預(yù)判。
Zuul
Zuul是Netflix開源的微服務(wù)網(wǎng)關(guān),可以和Eureka、Ribbon、Hystrix等組件配合使用,Spring Cloud對(duì)Zuul進(jìn)行了整合與增強(qiáng),Zuul總共有兩個(gè)大的版本:Zuul1.0和Zuul2.0,目前最新的版本為v2.2.0,Zuul1.0和Zuul2.0版本之間功能差異性非常大。
Netflix的Zuul包含如下功能:
- 身份認(rèn)證與安全: 識(shí)別每個(gè)資源的驗(yàn)證要求,并拒絕那些與要求不符的請(qǐng)求;
- 審查與監(jiān)控:在邊緣位置追蹤有意義的數(shù)據(jù)和統(tǒng)計(jì)結(jié)果;
- 動(dòng)態(tài)路由: 動(dòng)態(tài)地將請(qǐng)求路由到不同的后端集群;
- 壓力測(cè)試 : 逐漸增加指向集群的流量,以了解性能;
- 負(fù)載分配: 為每一種負(fù)載類型分配對(duì)應(yīng)容量 ,并棄用超出限定值的請(qǐng)求 ;
- 靜態(tài)響應(yīng)處理:在邊緣位置直接建立部分響應(yīng),從而避免其轉(zhuǎn)發(fā)到內(nèi)部集群;
- 多區(qū)域彈性: 跨越AWS Region進(jìn)行請(qǐng)求路由,旨在實(shí)現(xiàn)ELB(Elastic Load Balancing)使用的多樣化和 以及讓系統(tǒng)的邊緣更貼近系統(tǒng)的使用者。
以上介紹來(lái)自Zuul官方文檔,但其實(shí)開源版本的Zuul以上功能一個(gè)都沒有——開源的Zuul只是幾個(gè)Jar包而已,以上能力指的應(yīng)該是Netflix官方自用的Zuul的能力;Netflix自用的Zuul能力是比較強(qiáng)大的,可使用Groovy編寫過濾器,并且可動(dòng)態(tài)加載/卸載、修改規(guī)則,而且使用Cassandra作為數(shù)據(jù)庫(kù),然而開源版本這些一個(gè)都沒有;Spring Cloud中,Zuul絕大部分功能都是Spring Cloud團(tuán)隊(duì)為Zuul開發(fā)的;所以Zuul 2.x的開源進(jìn)度延后一年,Spring Cloud團(tuán)隊(duì)開發(fā)了自己的SCG,并宣布Spring Cloud不打算支持Zuul 2.x,你還覺得意外嗎?看到這里,很多人可能沒有動(dòng)力學(xué)習(xí)Zuul了,個(gè)人認(rèn)為還是可以了解一下的,后面講到SCG時(shí),你會(huì)發(fā)現(xiàn)很多設(shè)計(jì)理念是相通的。
既然說到了Spring Cloud對(duì)Zuul的封裝,那么我們來(lái)簡(jiǎn)單的分析下Spring Cloud與Zuul的關(guān)系。Spring Cloud通過Spring Cloud Netflix 1.X來(lái)封裝Zuul1.0,1.X的最后一個(gè)版本是v1.4.7.RELEASE,對(duì)應(yīng)的Zuul版本是1.3.1。Spring Cloud Netflix從3.X開始就沒有封裝Zuul網(wǎng)關(guān),包括Zuul1.0和Zuul2.0,也就是說開發(fā)者想要通過Spring Cloud來(lái)復(fù)用Zuul,只能使用Zuul1.0,暫時(shí)不能復(fù)用Zuul2.0。
Zuul目前在github上的star數(shù)為10.2k,fork數(shù)為2k,也就是說還是有很多開源愛好者會(huì)基于Zuul來(lái)定制化業(yè)務(wù)網(wǎng)關(guān)。
除了開源的Spring Cloud定制化Zuul,開源微服務(wù)框架jhipster也參與了定制,并集成到它的生態(tài)中。Jhipster主要包含generator-jhipster和jhipster-registry,前者star數(shù)微17.7k,fork數(shù)為3.5k,后者star數(shù)為604,fork為607。
Zuul1.0整體架構(gòu)設(shè)計(jì)如圖所示。

Zuul2.0整體架構(gòu)設(shè)計(jì)如圖所示。

Spring Cloud Gateway
SCG是基于Spring Framework 5.0和Spring Boot 2.0構(gòu)建的API網(wǎng)關(guān),提供路由等功能。其旨在提供一種簡(jiǎn)單而有效的方法路由到API,并為它們提供跨領(lǐng)域的關(guān)注點(diǎn),例如:安全性、監(jiān)視/指標(biāo)和彈性。
主要特性:
- J ava8
- Spring Framework5
- Spring Boot2
- 動(dòng)態(tài)路由
- Spring Handler Mapping 內(nèi)置的路由匹配
- HTTP 請(qǐng)求的路由匹配(路徑、方法、 Hea der 、主機(jī)等)
- 過濾器限定范圍以匹配路由
- 過濾器可以修改下游 HTTP 請(qǐng)求和 HTTP 響應(yīng)(添加、刪除 Header 、添加 / 刪除參數(shù)、重寫路徑、設(shè)置路徑等)
- API或配置驅(qū)動(dòng)
- 支持Spring Cloud Discovery Client配置路由
SCG的專業(yè)術(shù)語(yǔ)包括:
- 路由:它是基本構(gòu)建模塊,主要包含ID、URI、斷言集合以及過濾器集合,如果能夠匹配斷言就會(huì)執(zhí)行路由。
- 斷言: 主要是指Java8的函數(shù)式斷言,輸入類型是Spring Framework的ServerWebExchange,基于斷言可以匹配基于headers或者parameters的http請(qǐng)求。
- 過濾器: 它是通過特殊的工廠方法構(gòu)造的基于Spring Framework GatewayFilter的實(shí)現(xiàn),通過過濾器開發(fā)者可以在http請(qǐng)求下行之前修改請(qǐng)求響應(yīng)參數(shù),在請(qǐng)求響應(yīng)返回之后可以修改響應(yīng)的結(jié)果。
SCG整體架構(gòu)設(shè)計(jì)如圖所示。

自研網(wǎng)關(guān)
一個(gè)API網(wǎng)關(guān)的基本功能包括統(tǒng)一接入、協(xié)議適配、流量管控與容錯(cuò),以及安全防護(hù),這個(gè)四大基本功能構(gòu)成了網(wǎng)關(guān)的核心能力。網(wǎng)關(guān)首要的功能是負(fù)責(zé)統(tǒng)一接入,然后將請(qǐng)求的協(xié)議轉(zhuǎn)換成內(nèi)部的接口協(xié)議,在調(diào)用的過程中還要限流、降級(jí)和熔斷等容錯(cuò)的方式來(lái)保護(hù)網(wǎng)關(guān)的整體穩(wěn)定,同時(shí)網(wǎng)關(guān)還要做到基本的安全防護(hù)(防刷控制),以及黑白名單(比如IP地址白名單)等基本的安全措施,主要包括:統(tǒng)一標(biāo)準(zhǔn)接入,具備高性能、高并發(fā)和高可靠性,具備負(fù)載均衡的能力;

除了基本的四個(gè)功能,網(wǎng)關(guān)運(yùn)行良好的環(huán)境還包括注冊(cè)中心(比如通過Nacos讀取已經(jīng)發(fā)布的API接口的動(dòng)態(tài)配置)。為了實(shí)現(xiàn)高性能,將數(shù)據(jù)全部異構(gòu)到緩存(比如Redis)中,同時(shí)還可以配合本機(jī)緩存來(lái)進(jìn)一步的提高網(wǎng)關(guān)系統(tǒng)的性能。為了提高網(wǎng)關(guān)的吞吐率,可以使用NIO+Servlet3異步的方式,還可以利用Servlet3的異步特性將請(qǐng)求線程與業(yè)務(wù)處理線程分開,為后續(xù)的線程池隔離做好基本的支撐。訪問日志的存儲(chǔ)我們可以放到Hbase或者ES中,如果要作為開放網(wǎng)關(guān)使用,那么需要一個(gè)支持OAuth2.0協(xié)議的授權(quán)中心,同時(shí)還可以引入Nginx+Lua的方式,將一些基本的校驗(yàn)判斷前置到應(yīng)用系統(tǒng)之上,這樣可以更加輕量級(jí)的處理網(wǎng)關(guān)接入的問題。

主要包括接入層,開發(fā)者可以通過Nginx和Lua腳本,解決限流、黑白名單、路由、負(fù)載均衡、長(zhǎng)短連接以及容災(zāi)切換的問題。網(wǎng)關(guān)需要保證服務(wù)的穩(wěn)定性,需要接入注冊(cè)中心,因?yàn)楸緯荢pring Cloud Alibaba的布道書籍,所以強(qiáng)烈推薦使用Nacos作為注冊(cè)中心和配置中心。統(tǒng)一的鑒權(quán)中心,主要是統(tǒng)一解決網(wǎng)關(guān)為各個(gè)API服務(wù)的鑒權(quán)問題,當(dāng)然可以按照服務(wù)維度做隔離,自定義鑒權(quán)規(guī)則。統(tǒng)一用戶中心主要是解決用戶登錄問題,確保微服務(wù)調(diào)用的安全性。
自研網(wǎng)關(guān)還需要有泛化功能,使用者在調(diào)用提供者的接口的時(shí)候,不再需要API提供者的客戶端JAR包,因此也就沒有了POJO,通過泛化的方式進(jìn)行遠(yuǎn)程調(diào)用。一般情況下我們要通過RPC調(diào)用接口提供方的服務(wù),首先在系統(tǒng)中嵌入接口提供者的JAR包,然后使用JAR包里面的類和方法。對(duì)于一個(gè)網(wǎng)關(guān)系統(tǒng)來(lái)說,如果要調(diào)用N個(gè)接口,就需要N個(gè)JAR包,這樣的網(wǎng)關(guān)是很難維護(hù)的,當(dāng)然Dubbo RPC是支持泛化的。
網(wǎng)關(guān)要具備時(shí)間校驗(yàn)、方法校驗(yàn)、版本校驗(yàn)和簽名校驗(yàn)等功能,當(dāng)然網(wǎng)關(guān)還需要具備服務(wù)降級(jí)、日志記錄以及監(jiān)控與告警功能。
對(duì)比以上三種網(wǎng)關(guān)
網(wǎng)關(guān) | 限流 | 鑒權(quán) | 監(jiān)控 | 易用性 | 可維護(hù)性 | 成熟度 |
SCG | 可以通過IP,用戶,集群限流,提供了相應(yīng)的接口進(jìn)行擴(kuò)展 | 普通鑒權(quán)auth2.0 | Gateway Metrics Filter | 簡(jiǎn)單易用 | Spring系列可擴(kuò)展強(qiáng),易配置和可維護(hù)性好 | Spring社區(qū)成熟,但Gateway資源少。 |
Zuul2 | 可以通過配置文件配置集群限流和單服務(wù)器限流,也可以通過filter實(shí)現(xiàn)限流擴(kuò)展 | filter中實(shí)現(xiàn) | Filter中實(shí)現(xiàn) | 參考資料比較少 | 可維護(hù)性差 | 開源不就資源少。 |
Zuul1 | 同上 | 同上 | 同上 | 同上 | 同上 | 同上 |
自研網(wǎng)關(guān) | 需要開發(fā) | 需要開發(fā) | 需要開發(fā) | 需要開發(fā) | 可維護(hù)性極高 | 需要開發(fā) |
總結(jié)
推薦使用Spring Cloud Alibaba+Spring Cloud Gateway,可以更加高效的利用Spring Cloud ALibaba的服務(wù)治理能力去融合網(wǎng)關(guān)API的治理,從而提升業(yè)務(wù)服務(wù)API的系統(tǒng)穩(wěn)定性。





























