大量新老項(xiàng)目接入,服務(wù)限流如何排除差異快速落地?
一、背景
1、場景
某一天有一個(gè)項(xiàng)目服務(wù)突然出現(xiàn)異常,我們定位到的原因是有大量的突發(fā)流量進(jìn)來,那么我們會(huì)先采取被動(dòng)的臨時(shí)手段去處理當(dāng)前故障,接著上線Nginx的限流功能進(jìn)行快速止損,防止二次故障。但是Nginx的限流功能是比較粗糙的,所以我們有一個(gè)更好的長期措施,即項(xiàng)目接入限流功能,并實(shí)現(xiàn)按維度進(jìn)行精細(xì)化的限流,化被動(dòng)解決為主動(dòng)防御、主動(dòng)治理。對(duì)于這一個(gè)項(xiàng)目來說,做到這一步應(yīng)該是比較好的效果。
那么我們能否更進(jìn)一步?更進(jìn)一步我們需要考慮經(jīng)驗(yàn)積累、通用性、整體效益這三個(gè)方面。
- 經(jīng)驗(yàn)積累:有什么經(jīng)驗(yàn)總結(jié)可以被其他項(xiàng)目借鑒?
- 通用性:解決方案其他項(xiàng)目可以直接使用嗎?
- 整體效益:可以降低團(tuán)隊(duì)的整體成本嗎?
2、問題與目標(biāo)
我們的方案設(shè)計(jì)需要考慮不同項(xiàng)目之間的差異性,因?yàn)槲覀冃枰尤氲捻?xiàng)目可能有十幾個(gè)甚至更多,不同項(xiàng)目的差異性會(huì)體現(xiàn)在開發(fā)語言、請(qǐng)求類型、生命周期、部署環(huán)境、鏈路節(jié)點(diǎn)等方面。
其中我們特別需要注意的是生命周期,有的項(xiàng)目可能是十幾年前就存在的老項(xiàng)目,有的可能是最近兩三年的較新的項(xiàng)目,還有的可能是以后會(huì)建立的全新項(xiàng)目,我們的方案需要能夠同時(shí)匹配這三種項(xiàng)目,以及需要抹平其他的幾種差異。
此外,我們的方案也有一些其他的期望目標(biāo),比如低成本、高效率、高質(zhì)量,以及專業(yè)性、穩(wěn)定性、可擴(kuò)展性、高性能。
- 低成本:接入所需的成本是比較低的,包括開發(fā)、運(yùn)維、硬件等成本。
- 高效率:能夠快速完成接入落地工作。
- 高質(zhì)量:提供了整套限流的解決方案,接入方使用前后都能夠得到有效的技術(shù)支持和指引。
其他幾點(diǎn)則比較好理解,那么擺在我們眼前的問題就是項(xiàng)目的數(shù)量多,差異性大,期望目標(biāo)和要求也多,那么我們應(yīng)該如何設(shè)計(jì)這個(gè)方案?
3、協(xié)作方式
在介紹具體的技術(shù)方案之前,我簡單講述一下我們的協(xié)作方式。
在公司內(nèi)部推廣一個(gè)技術(shù)落地,我們通常會(huì)采用單項(xiàng)目的方式進(jìn)行,即單獨(dú)某個(gè)項(xiàng)目了解需求、設(shè)計(jì)、開發(fā),在本項(xiàng)目落地之后再逐步推廣到其他項(xiàng)目,這種方式雖然沒有問題,但是存在幾個(gè)缺點(diǎn):
- 需求的全面性:不能充分兼顧到其他項(xiàng)目的需求,方案設(shè)計(jì)上可能會(huì)有缺漏,導(dǎo)致后期推廣困難,因?yàn)橹豢紤]到了本項(xiàng)目的需求和場景。
- 成本負(fù)擔(dān):成本由單一項(xiàng)目承擔(dān),可能會(huì)影響到項(xiàng)目組原本的工作,對(duì)項(xiàng)目本身也會(huì)有比較大的影響。
基于以上情況,我們?cè)O(shè)計(jì)了一個(gè)專業(yè)組機(jī)制,希望能夠讓專業(yè)的人做專業(yè)的事,工作流程如下:
首先從多個(gè)有需求的項(xiàng)目組里招募感興趣或者有經(jīng)驗(yàn)的成員加入專業(yè)組,比如圖示里從項(xiàng)目組1、項(xiàng)目組2和項(xiàng)目組3里各抽出一個(gè)人成立專業(yè)組,然后針對(duì)這幾個(gè)項(xiàng)目設(shè)計(jì)總體方案,以滿足他們的需求,在項(xiàng)目落地之后,再逐步推廣到其他項(xiàng)目。
與單項(xiàng)目推進(jìn)相比,專業(yè)組機(jī)制的優(yōu)點(diǎn)如下:
- 充分兼顧到了典型場景的需求。因?yàn)槲覀儠?huì)從原先的三個(gè)項(xiàng)目組里去對(duì)接需求,那么這三個(gè)項(xiàng)目組的場景是比較明確的。
- 成本由多個(gè)項(xiàng)目分?jǐn)?。每個(gè)項(xiàng)目只需要出1~2個(gè)人即可,對(duì)項(xiàng)目組原先的工作影響程度較低。
- 專業(yè)組的進(jìn)出機(jī)制可以充分發(fā)揮成員的技術(shù)積累優(yōu)勢(shì)和主觀能動(dòng)性。能夠進(jìn)專業(yè)組的成員一般是在專業(yè)問題上比較有技術(shù)積累的,或者是對(duì)該問題很感興趣,會(huì)主動(dòng)研究問題。
在解決現(xiàn)有功能上,專業(yè)組在整個(gè)過程中發(fā)揮了很大的作用。
二、技術(shù)方案
下面我們介紹具體的技術(shù)方案。
1、限流實(shí)現(xiàn)層
首先的問題是我們的限流應(yīng)該做在哪一層?一般來說我們可以在應(yīng)用層限流,也就是在API服務(wù)節(jié)點(diǎn)再增加一個(gè)web中間件,在請(qǐng)求進(jìn)入API服務(wù)時(shí)判斷請(qǐng)求是否被限流,這是比較常見的方式,對(duì)于單個(gè)項(xiàng)目而言成本也是最低的。
除了應(yīng)用層實(shí)現(xiàn)限流之外,還有接入層實(shí)現(xiàn)限流的做法。在原先的LB到API節(jié)點(diǎn)之間,我們可以增加一個(gè)網(wǎng)關(guān)層,將限流功能做在網(wǎng)關(guān)層。
兩種方法相比較,應(yīng)用層限流有以下缺陷:
- 異常流量依然落在API服務(wù)。如果有大量的突發(fā)流量進(jìn)來,還是會(huì)把壓力落在API服務(wù),那么效果相對(duì)而言是比較差的。
- 邏輯耦合,無法獨(dú)立變更限流功能。
- 職責(zé)不明確,增加服務(wù)復(fù)雜性。
- 多項(xiàng)目情況下難以復(fù)用,可行性低,無法達(dá)到我們的需求。比如我們前面提到的差異性,不同項(xiàng)目的開發(fā)語言、部署方式等不一樣,如果我們?cè)趹?yīng)用層實(shí)現(xiàn)限流,就需要針對(duì)每一個(gè)項(xiàng)目單獨(dú)適配,那么成本是比較高的。
基于以上情況我們選擇了接入層實(shí)現(xiàn)限流。在接入層實(shí)現(xiàn),我們就需要一個(gè)網(wǎng)關(guān)作為統(tǒng)一的記錄層。
2、Kong網(wǎng)關(guān)
按照官方的說法,Kong網(wǎng)關(guān)是一個(gè)輕量、快速、靈活的云原生API網(wǎng)關(guān),Kong是基于OpenResty和Nginx實(shí)現(xiàn)的。我們?cè)诮鉀Q這一個(gè)問題的情況下,為什么要選擇Kong?也是基于我們常見的高性能、高可用、靈活、易擴(kuò)展等方面。其中我們特別在意以下兩點(diǎn):
- 一是輕量靈活,在最輕量部署的情況下,僅需一個(gè)主進(jìn)程和一個(gè)yaml配置文件。
- 二是易擴(kuò)展,Kong的插件機(jī)制可以實(shí)現(xiàn)在請(qǐng)求生命周期的各階段執(zhí)行自定義邏輯,也就是我們可以做很多自己需要的工作。
3、Kong插件
Kong的插件機(jī)制可以支持多種語言,如Golang、Lua、Python、JS。我們選擇了Lua和Golang作為我們的開發(fā)插件。兩種之間的區(qū)別是Lua插件在Kong進(jìn)程中是直接執(zhí)行的,也就是它和Kong是同一個(gè)進(jìn)程,而每一個(gè)Go插件是一個(gè)單獨(dú)的插件,和Kong主進(jìn)程之間的通信需要通過IPC進(jìn)行。
Lua和Golang相比較,在團(tuán)隊(duì)技術(shù)棧匹配度、生態(tài)、工程化難度、開發(fā)維護(hù)成本上,Golang都占有比較明顯的優(yōu)勢(shì),而在性能方面Lua會(huì)更高。因?yàn)镚olang在插件每次執(zhí)行的時(shí)候都需要進(jìn)行IPC通信,在IPC通信次數(shù)較高的情況下,性能會(huì)受到較大影響。但是我們?cè)趯?shí)踐過程中發(fā)現(xiàn),在現(xiàn)有場景下,我們的IPC通信次數(shù)相對(duì)較少,對(duì)性能的影響也比較低。所以總體上我們是優(yōu)先使用Golang開發(fā)插件,如果Golang實(shí)現(xiàn)不了再退而求其次用Lua進(jìn)行開發(fā)。
4、插件模塊化
前面我們通過把Kong作為接入層解決了不同項(xiàng)目在環(huán)境上的差異性,接著我們可以使用插件機(jī)制解決不同項(xiàng)目在需求上的差異性。
我們可以將一個(gè)項(xiàng)目的限流需求分為業(yè)務(wù)需求模塊和限流功能模塊兩個(gè)部分。
- 業(yè)務(wù)需求模塊是比較頻繁迭代的,這一方面的需求包括解析用戶名等,根據(jù)路徑、IP、請(qǐng)求方法等不同,每個(gè)項(xiàng)目也會(huì)有不同的需求。
- 限流功能模塊相對(duì)而言比較穩(wěn)定,比如我們需要進(jìn)行短連接的頻率限流、并發(fā)數(shù)限流等。
在具體的限流算法的實(shí)現(xiàn)之上,還有一個(gè)策略的應(yīng)用,即對(duì)于同一個(gè)限流方法,比如令牌桶,我們可能會(huì)設(shè)計(jì)不同的策略進(jìn)行應(yīng)用。
基于以上模塊劃分,我們?cè)趯?shí)際開發(fā)時(shí)分了三層,從下到上依次是限流算法層、限流插件層、業(yè)務(wù)插件層。
1)限流算法層
限流算法層主要是SDK的形式,因?yàn)槲覀兊南蘖鲌鼍氨容^多,算法也不同,所以我們對(duì)于每一個(gè)不同的場景都會(huì)單獨(dú)開發(fā)SDK,比如短連接限制頻率的場景可能會(huì)有令牌桶或時(shí)間窗口等,短連接并發(fā)數(shù)、長連接也有具體的實(shí)現(xiàn)。
需要特別注意的是客戶端節(jié)流的場景,我們?cè)趯?shí)際應(yīng)用時(shí)發(fā)現(xiàn),該場景除了接入Kong服務(wù)端性能之外,客戶端請(qǐng)求時(shí)也需要進(jìn)行限流??蛻舳讼蘖髦傅氖强蛻舳酥鲃?dòng)發(fā)起請(qǐng)求調(diào)用第三方頻率時(shí),我們也希望能夠控制頻率,保護(hù)第三方服務(wù)。
限流算法的SDK是以代碼嵌入的形式嵌入到限流插件層。
2)限流插件層
限流插件層會(huì)調(diào)用SDK,針對(duì)不同的場景需要設(shè)置不同的策略,比如我們的令牌桶限制短連接頻率,一個(gè)插件可能會(huì)實(shí)現(xiàn)令牌預(yù)知功能,而另一個(gè)插件可能會(huì)做限流額度、動(dòng)態(tài)調(diào)控等,也就是已經(jīng)往業(yè)務(wù)層走了一步。
3)業(yè)務(wù)插件層
業(yè)務(wù)插件層會(huì)根據(jù)項(xiàng)目組不同的需求制定單獨(dú)的業(yè)務(wù)場景,比如不同的項(xiàng)目組可能會(huì)有不同的限流維度進(jìn)行解析,需要項(xiàng)目組自己適配等。
如配置監(jiān)聽,以及業(yè)務(wù)組的其他業(yè)務(wù)定制功能,也可以做在這一層。
我們的分層主要分為三層,實(shí)際Kong執(zhí)行會(huì)有兩個(gè)插件,分別是業(yè)務(wù)插件和限流插件,這里的插件指的是Kong本身自帶的執(zhí)行插件。
接下來以長輪詢場景為例,講述需要限制接入的客戶端連接數(shù)場景。
首先請(qǐng)求進(jìn)入Kong網(wǎng)關(guān)時(shí),在業(yè)務(wù)插件我們會(huì)解析它的限流維度,比如user、path、method、ip,然后把這些維度生成一個(gè)字符串限流KEY,它可能是一個(gè)比較長的字符串。
接著它會(huì)匹配特定的限流策略,如果匹配不到則會(huì)進(jìn)入兜底策略,把這些信息生成限流的協(xié)議數(shù)據(jù)。業(yè)務(wù)插件的配置會(huì)記錄請(qǐng)求的維度,比如path、method等,匹配到了限流策略之后,就會(huì)去生成它的限流協(xié)議,限流協(xié)議里會(huì)設(shè)置請(qǐng)求最大并發(fā)數(shù)、請(qǐng)求超時(shí)時(shí)間等。接著業(yè)務(wù)插件會(huì)把這些信息組裝成一個(gè)協(xié)議,協(xié)議的格式如圖右下角。
然后把這些數(shù)據(jù)通過Kong的Context機(jī)制傳遞到限流插件,限流插件則會(huì)解析該協(xié)議數(shù)據(jù),然后執(zhí)行限流邏輯判斷,來判斷這個(gè)請(qǐng)求應(yīng)該被限流還是透傳到上游服務(wù)。
5、分工
項(xiàng)目組的需求,如果已有的插件可滿足,則直接使用;如果不滿足,可定制自己的業(yè)務(wù)插件。定制插件時(shí)項(xiàng)目組只需要關(guān)注項(xiàng)目需要的業(yè)務(wù)邏輯即可,相關(guān)的生態(tài)已由專業(yè)組提供,專業(yè)組負(fù)責(zé)所有限流插件、部分通用業(yè)務(wù)插件的開發(fā),網(wǎng)關(guān)、插件公用功能開發(fā),搭建安全性、穩(wěn)定性保障,以及不同場景下的限流算法的設(shè)計(jì)實(shí)現(xiàn)等工作。插件開發(fā)完成后提交到插件庫,后續(xù)其他項(xiàng)目組若有相同的項(xiàng)目,也可以直接使用。
6、分發(fā)與使用
接下來我們簡單了解一下插件的分發(fā)與使用機(jī)制。
首先插件開發(fā)完成之后,我們會(huì)在GitLab上給它打一個(gè)tag,然后觸發(fā)一個(gè)CI流程。CI流程做的工作主要是編譯、寫入?yún)?shù)信息、壓縮打包,把插件打包成一個(gè)tag壓縮文件,將其上傳到文件服務(wù),再發(fā)布到git release界面,那么項(xiàng)目組使用時(shí)就可以在release界面看到我們可以使用的插件及其功能。
而項(xiàng)目組在具體使用的時(shí)候,需要Fork部署倉庫,然后設(shè)置需要使用的多個(gè)插件及版本。接著再去觸發(fā)CI流程,我們會(huì)把插件重新下載回來,并且進(jìn)行解析、解包等工作,然后把這些插件和它們的信息寫入到Kong里,將其構(gòu)建、推送成為一個(gè)完整的鏡像,有了鏡像之后,我們就可以在部署平臺(tái)上進(jìn)行部署,那么項(xiàng)目組就完成了Kong和插件的使用。
7、接入方式
接下來簡單介紹項(xiàng)目組實(shí)際的接入方式。前面我們提到項(xiàng)目組的差異比較多,因此我們分了5種情況:
1)如果是一個(gè)全新的項(xiàng)目,則直接接入。
2)現(xiàn)存項(xiàng)目,但是沒有網(wǎng)關(guān),那么主要考慮業(yè)務(wù)場景,整體評(píng)估之后再進(jìn)行接入。
3)現(xiàn)存項(xiàng)目,且已有Kong網(wǎng)關(guān),這種情況下直接安裝和使用我們的限流插件即可。因?yàn)槲覀冮_發(fā)的插件也是Kong的標(biāo)準(zhǔn)插件,項(xiàng)目組使用限流插件時(shí)只需要對(duì)接其限流協(xié)議。
4)現(xiàn)存項(xiàng)目,且已有其他網(wǎng)關(guān),那么就不能使用Kong網(wǎng)關(guān)了,直接對(duì)接限流算法的SDK即可。
5)客戶端限流的情況下不需要Kong網(wǎng)關(guān),也是直接對(duì)接客戶端限流的SDK即可。
8、整體架構(gòu)
該方案的整體結(jié)構(gòu)是比較簡單的,便于適配不同的項(xiàng)目。
總體而言就是在LB和API節(jié)點(diǎn)之間加了一個(gè)Kong網(wǎng)關(guān),網(wǎng)關(guān)方面首先我們會(huì)插入一個(gè)tracing插件,這個(gè)插件內(nèi)嵌了Open-Tracing的實(shí)現(xiàn),接著項(xiàng)目組根據(jù)自身需求選擇業(yè)務(wù)插件和限流插件。
業(yè)務(wù)插件有一個(gè)功能是動(dòng)態(tài)監(jiān)聽限流配置,需要外部的配置中心實(shí)現(xiàn)。動(dòng)態(tài)監(jiān)聽主要是考慮到當(dāng)有異常流量進(jìn)來時(shí),我們可能需要?jiǎng)討B(tài)調(diào)整額度,比如場景可能是原先給該項(xiàng)目定的額度已經(jīng)不能滿足其需求了,該項(xiàng)目最近的用戶量猛增,那么在這種情況下,我們不能限制它的流量,因此需要將額度調(diào)大,避免對(duì)業(yè)務(wù)造成不好的影響。
限流插件根據(jù)不同限流算法的實(shí)現(xiàn),我們也有不同的依賴,比如我們?cè)诖蟛糠智闆r下都會(huì)做分布式限流,我們選擇通過Redis加一個(gè)Lua腳本實(shí)現(xiàn)分布式限流,那么這種情況下依賴還需要增加一個(gè)Redis。也有少部分情況下它可能是作為一個(gè)本地限流,需要根據(jù)項(xiàng)目組的具體實(shí)現(xiàn)。
三、實(shí)施方案
實(shí)施方案指的是一個(gè)項(xiàng)目組從0接觸到整個(gè)方案完成上線的過程,前期包括需求、評(píng)估和開發(fā)這幾個(gè)步驟。
1、需求
在需求階段,項(xiàng)目組根據(jù)我們提供的模板提issue,里面會(huì)包含以下內(nèi)容:
- 限流場景、類型
- 限流維度、策略
- 項(xiàng)目組需要特化的業(yè)務(wù)需求
- 現(xiàn)有插件能否滿足項(xiàng)目組的需求
2、評(píng)估
接著進(jìn)行整體的評(píng)估工作,評(píng)估的方面包括:
- 開發(fā)、維護(hù)、硬件等成本
- 部署架構(gòu)
- 性能、鏈路的影響
3、開發(fā)(若需要)
如果我們現(xiàn)有的插件無法滿足項(xiàng)目組的需要,那么就需要進(jìn)行開發(fā)工作。對(duì)于開發(fā)工作,我們有一個(gè)比較詳細(xì)的指南,因此上手開發(fā)的成本比較低。項(xiàng)目組需要了解以下幾個(gè)方面:
- 本地環(huán)境部署:我們提供了一個(gè)docker-compose環(huán)境可以一鍵拉起本地的開發(fā)環(huán)境。
- 相關(guān)知識(shí)快速了解:包括Kong的一些概念等。
- 完善的開發(fā)文檔:包括具體插件如何寫之類的,簡單來說就是我們提供了一個(gè)手把手教會(huì)項(xiàng)目組進(jìn)行開發(fā)的文檔。
接下來是測(cè)試、部署與上線的環(huán)節(jié)。
4、測(cè)試
在測(cè)試環(huán)節(jié)我們的目的是需要保證接入Kong和插件之后的質(zhì)量。
- 首先需要保證我們的限流功能是符合預(yù)期的。
- 原來的API服務(wù)的功能回歸之后需要與之前保持一致。
鏡像流量和故障演練對(duì)于我們而言是比較重要的。
- 鏡像流量指的是把生產(chǎn)環(huán)境的流量導(dǎo)入到測(cè)試環(huán)境,可以提前驗(yàn)證限流之后我們的流量是否異常。也就是我們需要一個(gè)單獨(dú)的鏡像流量的環(huán)境,將生產(chǎn)環(huán)境的流量在該環(huán)境里提前進(jìn)行驗(yàn)證,因?yàn)槲覀冊(cè)黾恿艘粋€(gè)新的網(wǎng)關(guān),變更的影響面是比較廣的,而且可能還會(huì)遇到奇怪的問題。如果我們提前把生產(chǎn)環(huán)境的流量導(dǎo)入過來,就可以提前發(fā)現(xiàn)這些問題。
- 故障演練也是為了提前發(fā)現(xiàn)可能存在的問題和風(fēng)險(xiǎn)。
關(guān)于這兩點(diǎn),我們內(nèi)部有兩個(gè)最佳實(shí)踐說明,分別是《如何做好鏡像流量》和《如何做好從場景出發(fā)的故障演練》。
5、部署
接下來是部署環(huán)節(jié)。
- 我們基于內(nèi)部的一致性交付系統(tǒng)實(shí)現(xiàn)了模板部署,即不同的部署平臺(tái),比如物理機(jī)或公有云、私有云,都可以用一致性交付的平臺(tái)實(shí)現(xiàn)統(tǒng)一的部署,那么項(xiàng)目組在部署時(shí)可以不用考慮太多的細(xì)節(jié)問題。
- 其次我們?cè)诓渴鸬臅r(shí)候可以一鍵接入監(jiān)控、日志、告警、鏈路等功能。
- 我們部署時(shí)有一個(gè)完善的部署指南會(huì)介紹方方面面的問題,比如我們接入Kong網(wǎng)關(guān)之后,對(duì)原先的服務(wù)拆分問題是如何處理的。
6、上線
最后的步驟是上線,我們也提供了詳細(xì)的上線步驟,以及checklist和最重要的灰度、回滾的技術(shù)方案。
總體而言我們這幾個(gè)環(huán)節(jié)也達(dá)到了手把手指引、實(shí)現(xiàn)的整個(gè)過程。
四、小結(jié)
前面我們提到的目標(biāo)是低成本、高效率、高質(zhì)量這幾個(gè)方面。
1、低成本
1)開發(fā)成本:項(xiàng)目組對(duì)接時(shí)基本上是0成本,或者只有少量的開發(fā)工作。
2)維護(hù)成本:后續(xù)的維護(hù)、升級(jí)工作都是由專業(yè)組負(fù)責(zé)的。
3)硬件成本:主要的是Kong的集群部署,根據(jù)項(xiàng)目組本身的流量大小,可以部署不同的副本數(shù)。如果選擇了分布式限流,那么還需要部署一個(gè)Redis,我們一般建議部署一個(gè)新的Redis,但是為了節(jié)約成本也可以和原先項(xiàng)目已有的Redis共用。
2、高效率
1)接入時(shí)間:我們?cè)陧?xiàng)目實(shí)踐時(shí),最快的接入時(shí)間是三天,三天是在項(xiàng)目組沒有自己定制化的需求,不需要開發(fā)的情況下走完我們之前介紹的環(huán)節(jié),即評(píng)估、測(cè)試、部署、上線。
2)硬件配置:我們有一個(gè)推薦配置,也就是根據(jù)我們不同的流量進(jìn)行單獨(dú)測(cè)試,以及我們提供了比較完整的性能測(cè)試數(shù)據(jù)作為參考。
3)高效部署:網(wǎng)易內(nèi)部的平臺(tái)相對(duì)完善,借助于我們的CI自動(dòng)化、配置管理系統(tǒng)、容器云系統(tǒng)和一致性交付系統(tǒng)可以實(shí)現(xiàn)高效部署。
4)文檔建設(shè):文檔建設(shè)我們是比較完善的,從剛開始接觸限流這套方案到上線的整個(gè)過程中各個(gè)環(huán)節(jié),我們都有很詳細(xì)的文檔指引,遇到問題可以從文檔中尋找,也可以找專業(yè)組的同事了解。
3、高質(zhì)量
1)技術(shù)支持:由專業(yè)組的同事提供技術(shù)支撐。
2)多樣場景:我們的插件機(jī)制適配了多樣化的限流場景和業(yè)務(wù)需求。
3)經(jīng)驗(yàn)復(fù)用:在各個(gè)項(xiàng)目對(duì)接和使用過程中的經(jīng)驗(yàn)或優(yōu)化的問題,都可以總結(jié)復(fù)用,因?yàn)槲覀儾煌?xiàng)目使用的是同一套技術(shù)體系,便于積累經(jīng)驗(yàn)。
4)自定擴(kuò)展:我們雖然定制化了一些插件,以及一些Kong的部署過程,但是在實(shí)際開發(fā)時(shí)也考慮到了Kong原生態(tài)的兼容性,也就是項(xiàng)目組依然可以使用Kong原生態(tài)提供的豐富功能。
5)運(yùn)維體系:接入了整套運(yùn)維設(shè)施相關(guān)的功能體系,也就是前面我們提到的監(jiān)控、報(bào)警、日志等。
6)充分驗(yàn)證:我們的插件功能和性能得到了充分的測(cè)試,上線流程也比較完善,可以保證我們的可靠性。
通過以上環(huán)節(jié)可以保證服務(wù)限流方案的低成本、高效率和高質(zhì)量。
Q&A
Q1:這個(gè)限流方案在哪些類型的項(xiàng)目上具有通用性?
A1:這個(gè)問題其實(shí)回歸到了我們項(xiàng)目的差異性上,總體來說,我們對(duì)于不管是普通的http短連接的項(xiàng)目,或者是一些長輪詢的場景以及長連接的場景,我們都有單獨(dú)做適配。因?yàn)楸旧鞬ong對(duì)于這幾種請(qǐng)求都可以支持,也就是我們只需要針對(duì)這幾種場景開發(fā)對(duì)應(yīng)的插件即可。
Q2:Kong和插件對(duì)性能的影響大嗎?
A2:這一點(diǎn)我們?cè)趯?shí)際設(shè)計(jì)的時(shí)候也考慮過,經(jīng)過實(shí)踐發(fā)現(xiàn)對(duì)性能的影響是比較小的。性能一方面是對(duì)我們的請(qǐng)求耗時(shí)的影響,經(jīng)過我們的測(cè)試,耗時(shí)大概是在5毫秒左右,另外一方面是QPS,因?yàn)镵ong和插件本身是支持橫向擴(kuò)展的,以及Kong本身的性能也比較高,所以對(duì)QPS的影響是比較小的,我們?cè)跍y(cè)試時(shí)最高達(dá)到過五六萬QPS,因此基本上不需要過于擔(dān)心這個(gè)問題。
Q3:如何實(shí)現(xiàn)長輪詢連接數(shù)限制?
A3:長輪詢本質(zhì)是請(qǐng)求并發(fā)數(shù)的一個(gè)性質(zhì),只不過它是http請(qǐng)求,可能是一個(gè)掛起的狀態(tài),需要掛起比如一分鐘。這個(gè)場景的實(shí)現(xiàn)過程大概如下:Kong本身對(duì)插件機(jī)制可以保證在請(qǐng)求前和請(qǐng)求后,我們可以插入鉤子函數(shù)。在請(qǐng)求前我們的鉤子函數(shù)會(huì)在Redis的Zset里設(shè)置一個(gè)請(qǐng)求的狀態(tài),那么Zset的值就是該請(qǐng)求的唯一ID,比如它是一個(gè)雪花ID,然后分就是請(qǐng)求的過期時(shí)間,這個(gè)過期時(shí)間是當(dāng)前時(shí)間加上請(qǐng)求配置里的TTL(請(qǐng)求的超時(shí)時(shí)間),兩者加起來就是該請(qǐng)求實(shí)際失效的時(shí)間。在請(qǐng)求進(jìn)來時(shí),我們會(huì)在Zset里記錄請(qǐng)求的數(shù)據(jù),表示當(dāng)前的請(qǐng)求并發(fā)數(shù)已經(jīng)加一了。然后在執(zhí)行Redis Lua腳本的時(shí)候,它會(huì)先剔除那些已經(jīng)過期了的請(qǐng)求數(shù),在請(qǐng)求結(jié)束之后,會(huì)從Zset里移除該請(qǐng)求的數(shù)據(jù),也就是請(qǐng)求并發(fā)數(shù)減一,這是大致原理。
作者:肖晗網(wǎng)易互娛技術(shù)中心數(shù)據(jù)與平臺(tái)服務(wù)部高級(jí)開發(fā)工程師 網(wǎng)易互娛技術(shù)中心數(shù)據(jù)與平臺(tái)服務(wù)部高級(jí)開發(fā)工程師,具有多年服務(wù)端經(jīng)驗(yàn),現(xiàn)專注于CMDB、微服務(wù)、圖數(shù)據(jù)庫等方向。