淺析如何設(shè)計(jì)一個(gè)億級(jí)網(wǎng)關(guān)

1.背景

1.1 什么是API網(wǎng)關(guān)

API網(wǎng)關(guān)可以看做系統(tǒng)與外界聯(lián)通的入口牙捉,我們可以在網(wǎng)關(guān)進(jìn)行處理一些非業(yè)務(wù)邏輯的邏輯,比如權(quán)限驗(yàn)證材失,監(jiān)控痕鳍,緩存,請(qǐng)求路由等等龙巨。

1.2 為什么需要API網(wǎng)關(guān)

RPC協(xié)議轉(zhuǎn)成HTTP笼呆。

由于在內(nèi)部開發(fā)中我們都是以RPC協(xié)議(thrift or dubbo)去做開發(fā),暴露給內(nèi)部服務(wù)旨别,當(dāng)外部服務(wù)需要使用這個(gè)接口的時(shí)候往往需要將RPC協(xié)議轉(zhuǎn)換成HTTP協(xié)議诗赌。

請(qǐng)求路由

在我們的系統(tǒng)中由于同一個(gè)接口新老兩套系統(tǒng)都在使用,我們需要根據(jù)請(qǐng)求上下文將請(qǐng)求路由到對(duì)應(yīng)的接口秸弛。

統(tǒng)一鑒權(quán)

對(duì)于鑒權(quán)操作不涉及到業(yè)務(wù)邏輯铭若,那么可以在網(wǎng)關(guān)層進(jìn)行處理,不用下層到業(yè)務(wù)邏輯递览。

統(tǒng)一監(jiān)控

由于網(wǎng)關(guān)是外部服務(wù)的入口叼屠,所以我們可以在這里監(jiān)控我們想要的數(shù)據(jù),比如入?yún)⒊鰠⒔柿澹溌窌r(shí)間镜雨。

流量控制,熔斷降級(jí)

對(duì)于流量控制儿捧,熔斷降級(jí)非業(yè)務(wù)邏輯可以統(tǒng)一放到網(wǎng)關(guān)層荚坞。

有很多業(yè)務(wù)都會(huì)自己去實(shí)現(xiàn)一層網(wǎng)關(guān)層,用來(lái)接入自己的服務(wù)菲盾,但是對(duì)于整個(gè)公司來(lái)說(shuō)這還不夠颓影。

1.3 統(tǒng)一API網(wǎng)關(guān)

統(tǒng)一的API網(wǎng)關(guān)不僅有API網(wǎng)關(guān)的所有的特點(diǎn),還有下面幾個(gè)好處:

統(tǒng)一技術(shù)組件升級(jí)

在公司中如果有某個(gè)技術(shù)組件需要升級(jí)亿汞,那么是需要和每個(gè)業(yè)務(wù)線溝通瞭空,通常幾個(gè)月都搞不定揪阿。舉個(gè)例子如果對(duì)于入口的安全鑒權(quán)有重大安全隱患需要升級(jí)疗我,如果速度還是這么慢肯定是不行,那么有了統(tǒng)一的網(wǎng)關(guān)升級(jí)是很快的南捂。

統(tǒng)一服務(wù)接入

對(duì)于某個(gè)服務(wù)的接入也比較困難吴裤,比如公司已經(jīng)研發(fā)出了比較穩(wěn)定的服務(wù)組件,正在公司大力推廣溺健,這個(gè)周期肯定也特別漫長(zhǎng)麦牺,由于有了統(tǒng)一網(wǎng)關(guān),那么只需要統(tǒng)一網(wǎng)關(guān)統(tǒng)一接入。

節(jié)約資源

不同業(yè)務(wù)不同部門如果按照我們上面的做法應(yīng)該會(huì)都自己搞一個(gè)網(wǎng)關(guān)層剖膳,用來(lái)做這個(gè)事魏颓,可以想象如果一個(gè)公司有100個(gè)這種業(yè)務(wù),每個(gè)業(yè)務(wù)配備4臺(tái)機(jī)器吱晒,那么就需要400臺(tái)機(jī)器甸饱。并且每個(gè)業(yè)務(wù)的開發(fā)RD都需要去開發(fā)這個(gè)網(wǎng)關(guān)層,去隨時(shí)去維護(hù)仑濒,增加人力叹话。如果有了統(tǒng)一網(wǎng)關(guān)層,那么也許只需要50臺(tái)機(jī)器就可以做這100個(gè)業(yè)務(wù)的網(wǎng)關(guān)層的事墩瞳,并且業(yè)務(wù)RD不需要隨時(shí)關(guān)注開發(fā)驼壶,上線的步驟。

2.統(tǒng)一網(wǎng)關(guān)的設(shè)計(jì)

2.1 異步化請(qǐng)求

對(duì)于我們自己實(shí)現(xiàn)的網(wǎng)關(guān)層喉酌,由于只有我們自己使用热凹,對(duì)于吞吐量的要求并不高所以,我們一般同步請(qǐng)求調(diào)用即可瞭吃。

對(duì)于我們統(tǒng)一的網(wǎng)關(guān)層碌嘀,如何用少量的機(jī)器接入更多的服務(wù),這就需要我們的異步歪架,用來(lái)提高更多的吞吐量股冗。對(duì)于異步化一般有下面兩種策略:

Tomcat/Jetty+NIO+servlet3

這種策略使用的比較普遍,京東和蚪,有贊止状,Zuul,都選取的是這個(gè)策略攒霹,這種策略比較適合HTTP怯疤。在Servlet3中可以開啟異步。

Netty+NIO

Netty為高并發(fā)而生催束,目前唯品會(huì)的網(wǎng)關(guān)使用這個(gè)策略集峦,在唯品會(huì)的技術(shù)文章中在相同的情況下Netty是每秒30w+的吞吐量,Tomcat是13w+,可以看出是有一定的差距的抠刺,但是Netty需要自己處理HTTP協(xié)議塔淤,這一塊比較麻煩。

對(duì)于網(wǎng)關(guān)是HTTP請(qǐng)求場(chǎng)景比較多的情況可以采用Servlet速妖,畢竟有更加成熟的處理HTTP協(xié)議高蜂。如果更加重視吞吐量那么可以采用Netty。

2.1.1 全鏈路異步

對(duì)于來(lái)的請(qǐng)求我們已經(jīng)使用異步了罕容,為了達(dá)到全鏈路異步所以我們需要對(duì)去的請(qǐng)求也進(jìn)行異步處理备恤,對(duì)于去的請(qǐng)求我們可以利用我們r(jià)pc的異步支持進(jìn)行異步請(qǐng)求所以基本可以達(dá)到下圖:

由在web容器中開啟servlet異步稿饰,然后進(jìn)入到網(wǎng)關(guān)的業(yè)務(wù)線程池中進(jìn)行業(yè)務(wù)處理,然后進(jìn)行rpc的異步調(diào)用并注冊(cè)需要回調(diào)的業(yè)務(wù)露泊,最后在回調(diào)線程池中進(jìn)行回調(diào)處理喉镰。

2.2 鏈?zhǔn)教幚?/b>

在設(shè)計(jì)模式中有一個(gè)模式叫責(zé)任鏈模式,他的作用是避免請(qǐng)求發(fā)送者與接收者耦合在一起惭笑,讓多個(gè)對(duì)象都有可能接收請(qǐng)求梧喷,將這些對(duì)象連接成一條鏈,并且沿著這條鏈傳遞請(qǐng)求脖咐,直到有對(duì)象處理它為止铺敌。通過(guò)這種模式將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦了。在我們的各個(gè)框架中對(duì)此模式都有實(shí)現(xiàn)屁擅,比如servlet里面的filter偿凭,springmvc里面的Interceptor。

在Netflix Zuul中也應(yīng)用了這種模式派歌,如下圖所示:

這種模式在網(wǎng)關(guān)的設(shè)計(jì)中我們可以借鑒到自己的網(wǎng)關(guān)設(shè)計(jì):

preFilters:前置過(guò)濾器弯囊,用來(lái)處理一些公共的業(yè)務(wù),比如統(tǒng)一鑒權(quán)胶果,統(tǒng)一限流匾嘱,熔斷降級(jí),緩存處理等早抠,并且提供業(yè)務(wù)方擴(kuò)展霎烙。

routingFilters: 用來(lái)處理一些泛化調(diào)用,主要是做協(xié)議的轉(zhuǎn)換蕊连,請(qǐng)求的路由工作悬垃。

postFilters: 后置過(guò)濾器,主要用來(lái)做結(jié)果的處理甘苍,日志打點(diǎn)尝蠕,記錄時(shí)間等等。

errorFilters: 錯(cuò)誤過(guò)濾器载庭,用來(lái)處理調(diào)用異常的情況看彼。

這種設(shè)計(jì)在有贊的網(wǎng)關(guān)也有應(yīng)用。

2.3 業(yè)務(wù)隔離

上面在全鏈路異步的情況下不同業(yè)務(wù)之間的影響很小囚聚,但是如果在提供的自定義FiIlter中進(jìn)行了某些同步調(diào)用靖榕,一旦超時(shí)頻繁那么就會(huì)對(duì)其他業(yè)務(wù)產(chǎn)生影響。所以我們需要采用隔離之術(shù)靡挥,降低業(yè)務(wù)之間的互相影響序矩。

2.3.1 信號(hào)量隔離

信號(hào)量隔離只是限制了總的并發(fā)數(shù)鸯绿,服務(wù)還是主線程進(jìn)行同步調(diào)用跋破。這個(gè)隔離如果遠(yuǎn)程調(diào)用超時(shí)依然會(huì)影響主線程簸淀,從而會(huì)影響其他業(yè)務(wù)。因此毒返,如果只是想限制某個(gè)服務(wù)的總并發(fā)調(diào)用量或者調(diào)用的服務(wù)不涉及遠(yuǎn)程調(diào)用的話租幕,可以使用輕量級(jí)的信號(hào)量來(lái)實(shí)現(xiàn)。有贊的網(wǎng)關(guān)由于沒(méi)有自定義filter所以選取的是信號(hào)量隔離拧簸。

2.3.2 線程池隔離

最簡(jiǎn)單的就是不同業(yè)務(wù)之間通過(guò)不同的線程池進(jìn)行隔離劲绪,就算業(yè)務(wù)接口出現(xiàn)了問(wèn)題由于線程池已經(jīng)進(jìn)行了隔離那么也不會(huì)影響其他業(yè)務(wù)。在京東的網(wǎng)關(guān)實(shí)現(xiàn)之中就是采用的線程池隔離盆赤,比較重要的業(yè)務(wù)比如商品或者訂單 都是單獨(dú)的通過(guò)線程池去處理贾富。但是由于是統(tǒng)一網(wǎng)關(guān)平臺(tái),如果業(yè)務(wù)線眾多牺六,大家都覺(jué)得自己的業(yè)務(wù)比較重要需要單獨(dú)的線程池隔離颤枪,如果使用的是Java語(yǔ)言開發(fā)的話那么,在Java中線程是比較重的資源比較受限淑际,如果需要隔離的線程池過(guò)多不是很適用畏纲。如果使用一些其他語(yǔ)言比如Golang進(jìn)行開發(fā)網(wǎng)關(guān)的話,線程是比較輕的資源春缕,所以比較適合使用線程池隔離盗胀。

2.3.3 集群隔離

如果有某些業(yè)務(wù)就需要使用隔離但是統(tǒng)一網(wǎng)關(guān)又沒(méi)有線程池隔離那么應(yīng)該怎么辦呢?那么可以使用集群隔離锄贼,如果你的某些業(yè)務(wù)真的很重要那么可以為這一系列業(yè)務(wù)單獨(dú)申請(qǐng)一個(gè)集群或者多個(gè)集群票灰,通過(guò)機(jī)器之間進(jìn)行隔離。

2.4 請(qǐng)求限流

流量控制可以采用很多開源的實(shí)現(xiàn)宅荤,比如阿里最近開源的Sentinel和比較成熟的Hystrix米间。

一般限流分為集群限流和單機(jī)限流:

利用統(tǒng)一存儲(chǔ)保存當(dāng)前流量的情況,一般可以采用Redis膘侮,這個(gè)一般會(huì)有一些性能損耗屈糊。

單機(jī)限流:限流每臺(tái)機(jī)器我們可以直接利用Guava的令牌桶去做,由于沒(méi)有遠(yuǎn)程調(diào)用性能消耗較小琼了。

2.5 熔斷降級(jí)

這一塊也可以參照開源的實(shí)現(xiàn)Sentinel和Hystrix逻锐,這里不是重點(diǎn)就不多提了。

2.6 泛化調(diào)用

泛化調(diào)用指的是一些通信協(xié)議的轉(zhuǎn)換雕薪,比如將HTTP轉(zhuǎn)換成Thrift昧诱。在一些開源的網(wǎng)關(guān)中比如Zuul是沒(méi)有實(shí)現(xiàn)的,因?yàn)楦鱾€(gè)公司的內(nèi)部服務(wù)通信協(xié)議都不同所袁。比如在唯品會(huì)中支持HTTP1,HTTP2,以及二進(jìn)制的協(xié)議盏档,然后轉(zhuǎn)化成內(nèi)部的協(xié)議,淘寶的支持HTTPS,HTTP1,HTTP2這些協(xié)議都可以轉(zhuǎn)換成燥爷,HTTP,HSF,Dubbo等協(xié)議蜈亩。

2.6.1泛化調(diào)用

如何去實(shí)現(xiàn)泛化調(diào)用呢懦窘?由于協(xié)議很難自動(dòng)轉(zhuǎn)換,那么其實(shí)每個(gè)協(xié)議對(duì)應(yīng)的接口需要提供一種映射稚配。簡(jiǎn)單來(lái)說(shuō)就是把兩個(gè)協(xié)議都能轉(zhuǎn)換成共同語(yǔ)言畅涂,從而互相轉(zhuǎn)換。

一般來(lái)說(shuō)共同語(yǔ)言有三種方式指定:

json:json數(shù)據(jù)格式比較簡(jiǎn)單,解析速度快道川,較輕量級(jí)午衰。在Dubbo的生態(tài)中有一個(gè)HTTP轉(zhuǎn)Dubbo的項(xiàng)目是用JsonRpc做的,將HTTP轉(zhuǎn)化成JsonRpc再轉(zhuǎn)化成Dubbo冒萄。

比如可以將一個(gè) www.baidu.com/id = 1 GET 可以映射為json:

代碼塊

{

“method”: "getBaidu"

"param" : {

"id" : 1

}

}

xml:xml數(shù)據(jù)比較重臊岸,解析比較困難,這里不過(guò)多討論尊流。

自定義描述語(yǔ)言:一般來(lái)說(shuō)這個(gè)成本比較高需要自己定義語(yǔ)言來(lái)進(jìn)行描述并進(jìn)行解析扇单,但是其擴(kuò)展性,自定義個(gè)性化性都是最高奠旺。例:spring自定義了一套自己的SPEL表達(dá)式語(yǔ)言

對(duì)于泛化調(diào)用如果要自己設(shè)計(jì)的話JSON基本可以滿足蜘澜,如果對(duì)于個(gè)性化的需要特別多的話倒是可以自己定義一套語(yǔ)言。

2.7 管理平臺(tái)

上面介紹的都是如何實(shí)現(xiàn)一個(gè)網(wǎng)關(guān)的技術(shù)關(guān)鍵响疚。這里需要介紹網(wǎng)關(guān)的一個(gè)業(yè)務(wù)關(guān)鍵淳地。有了網(wǎng)關(guān)之后怀伦,需要一個(gè)管理平臺(tái)如何去對(duì)我們上面所描述的技術(shù)關(guān)鍵進(jìn)行配置,包括但不限于下面這些配置:

限流

熔斷

緩存

日志

自定義filter

泛化調(diào)用

3.總結(jié)

最后一個(gè)合理的標(biāo)準(zhǔn)網(wǎng)關(guān)應(yīng)該按照如下去實(shí)現(xiàn):

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玻墅,一起剝皮案震驚了整個(gè)濱河市吞歼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌践盼,老刑警劉巖鸦采,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咕幻,居然都是意外死亡渔伯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門肄程,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锣吼,“玉大人,你說(shuō)我怎么就攤上這事蓝厌⌒” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵拓提,是天一觀的道長(zhǎng)读恃。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么寺惫? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任疹吃,我火速辦了婚禮,結(jié)果婚禮上肌蜻,老公的妹妹穿的比我還像新娘。我一直安慰自己必尼,他們只是感情好蒋搜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著判莉,像睡著了一般豆挽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上券盅,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天帮哈,我揣著相機(jī)與錄音,去河邊找鬼锰镀。 笑死娘侍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泳炉。 我是一名探鬼主播憾筏,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼花鹅!你這毒婦竟也來(lái)了氧腰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刨肃,失蹤者是張志新(化名)和其女友劉穎古拴,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體真友,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黄痪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盔然。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片满力。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖轻纪,靈堂內(nèi)的尸體忽然破棺而出油额,到底是詐尸還是另有隱情,我是刑警寧澤刻帚,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布潦嘶,位于F島的核電站,受9級(jí)特大地震影響崇众,放射性物質(zhì)發(fā)生泄漏掂僵。R本人自食惡果不足惜航厚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锰蓬。 院中可真熱鬧幔睬,春花似錦、人聲如沸芹扭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舱卡。三九已至辅肾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間轮锥,已是汗流浹背矫钓。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舍杜,地道東北人新娜。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像既绩,于是被迫代替她去往敵國(guó)和親杯活。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容