新聞中心
一、管理和監(jiān)控
1.1、大使模式:創(chuàng)建代表消費(fèi)者服務(wù)或應(yīng)用程序發(fā)送網(wǎng)絡(luò)請(qǐng)求的幫助服務(wù)
進(jìn)程外的代理服務(wù)(很多框架層面的事情可以以軟件框架的形式寄宿在進(jìn)程內(nèi),也可以以獨(dú)立的代理形式做一個(gè)網(wǎng)絡(luò)中間件)。這里的大使模式意思就是這么一個(gè)網(wǎng)絡(luò)代理進(jìn)程,用于和遠(yuǎn)端的服務(wù)進(jìn)行通訊,完成下面的工作:
服務(wù)路由
服務(wù)熔斷
服務(wù)跟蹤
服務(wù)監(jiān)控
服務(wù)授權(quán)
數(shù)據(jù)加密
日志記錄
由于是獨(dú)立進(jìn)程的網(wǎng)絡(luò)服務(wù),所以這個(gè)模式適合于我們有多語(yǔ)言多框架都需要干同樣的事情,那么我們的框架中客戶端部分的很多工作可以移出來(lái)放到大使服務(wù)中去。當(dāng)然了,多一層網(wǎng)絡(luò)調(diào)用多一層開銷,大使服務(wù)的部署也要考慮到性能不一定可以集中部署,這些都是要考慮的問(wèn)題。
1.2、反腐模式:在現(xiàn)代應(yīng)用程序和遺留系統(tǒng)之間實(shí)現(xiàn)裝飾或適配器層
使用一層防腐層來(lái)作為新老系統(tǒng)通訊的中間人。這樣新系統(tǒng)可以完全使用新的通訊方式和架構(gòu)方式,老的系統(tǒng)又不用進(jìn)行特別改造可以暫時(shí)保留,等老系統(tǒng)不用之后可以廢棄這個(gè)反腐層。這種模式適合新老系統(tǒng)遷移的過(guò)渡方案,不屬于永久使用的架構(gòu)設(shè)計(jì)模式。
1.3、外部配置存儲(chǔ):將應(yīng)用程序部署包中的配置信息移動(dòng)到中心化的位置
這個(gè)模式說(shuō)的就是可以有一個(gè)外部的配置服務(wù)來(lái)保存配置信息。不管是處于管理運(yùn)維的角度還是方便安全的角度,具有配置共享配置外存特點(diǎn)的獨(dú)立配置服務(wù)對(duì)于大型的網(wǎng)站來(lái)說(shuō)必不可少。實(shí)現(xiàn)的話有很多開源項(xiàng)目提供了配置服務(wù)。
1.4、網(wǎng)關(guān)聚合模式:使用網(wǎng)關(guān)將多個(gè)單獨(dú)的請(qǐng)求聚合到一個(gè)請(qǐng)求中
應(yīng)用程序如果需要和多個(gè)服務(wù)交互的話,在中間構(gòu)建起一個(gè)聚合網(wǎng)關(guān)層,網(wǎng)關(guān)并發(fā)發(fā)出多個(gè)請(qǐng)求給后面的服務(wù),然后匯總數(shù)據(jù)給到應(yīng)用程序。這種模式有幾個(gè)好處:
允許并發(fā)調(diào)用多個(gè)服務(wù)提高性能,允許只返回部分?jǐn)?shù)據(jù)
網(wǎng)關(guān)里可以做一些彈性設(shè)計(jì)方案(熔斷、重試、限流)
網(wǎng)關(guān)里可以做一些緩存方案
對(duì)于外網(wǎng)通訊的時(shí)候,可以讓網(wǎng)關(guān)作為一個(gè)網(wǎng)絡(luò)中間層
當(dāng)然,使用這種模式需要考慮到網(wǎng)關(guān)的負(fù)載、高可用、高性能(異步IO)等等。
其實(shí)這種模式不僅僅用于純后端服務(wù)之間的通訊,很多面向前端的API請(qǐng)求都會(huì)做一個(gè)聚合層,這樣前端可以只發(fā)一個(gè)請(qǐng)求的情況下任意向后端一次性索取多個(gè)API的返回,減少網(wǎng)絡(luò)請(qǐng)求次數(shù)提高性能。
實(shí)現(xiàn)上最簡(jiǎn)單的方式可以使用OpenResty或Nginx實(shí)現(xiàn)。
1.5、網(wǎng)關(guān)卸壓模式:把共享或特定的服務(wù)功能放到網(wǎng)關(guān)代理
名字有點(diǎn)難以理解。就是用一個(gè)代理網(wǎng)關(guān)層做一些和業(yè)務(wù)無(wú)關(guān)的又麻煩的點(diǎn),比如SSL,實(shí)現(xiàn)上用Nginx實(shí)現(xiàn)就很簡(jiǎn)單。我們經(jīng)常會(huì)對(duì)外啟用HTTPS服務(wù),然后對(duì)內(nèi)服務(wù)實(shí)際提供的是HTTP接口,通過(guò)網(wǎng)關(guān)做一下協(xié)議轉(zhuǎn)換。
1.6、網(wǎng)關(guān)路由模式:使用單個(gè)端點(diǎn)將請(qǐng)求路由到多個(gè)服務(wù)
這也是很常見(jiàn)的作法,我們對(duì)外的接口可能是/cart、/order、/search這樣的API,在其背后其實(shí)是不同的服務(wù),通過(guò)網(wǎng)關(guān)層進(jìn)行轉(zhuǎn)發(fā),不僅僅可以做后端服務(wù)的負(fù)載均衡和故障轉(zhuǎn)移,在后端服務(wù)變更切換對(duì)外API路徑(比如版本升級(jí))的時(shí)候我們也可以進(jìn)行靈活的路由,確保了對(duì)外接口的一致性??梢允褂肗ginx來(lái)實(shí)現(xiàn),相信大部分公司都是由Nginx這樣的網(wǎng)關(guān)來(lái)對(duì)外的,不會(huì)把域名直接解析到底層服務(wù)上對(duì)外。
1.7、健康端點(diǎn)監(jiān)控模式:在應(yīng)用程序中執(zhí)行功能檢查,外部工具可以定期通過(guò)暴露的端點(diǎn)訪問(wèn)
這個(gè)模式其實(shí)是挺重要的一點(diǎn),有幾個(gè)點(diǎn)需要注意:
需要暴露哪些信息?不僅僅是服務(wù)本身或框架本身是否啟動(dòng)成功,盡可能暴露出服務(wù)依賴的外部存儲(chǔ)或系統(tǒng)是否可用,原因是網(wǎng)絡(luò)通訊是復(fù)雜的,從外部看到某個(gè)服務(wù)可用不代表我們的網(wǎng)站就可以成功連接,如果底層的數(shù)據(jù)庫(kù)都無(wú)法連接,即使這個(gè)網(wǎng)站本身啟動(dòng)成功,那么我們應(yīng)該認(rèn)為這個(gè)服務(wù)是不健康的。外部存儲(chǔ)即使對(duì)于A節(jié)點(diǎn)是可以連通對(duì)于B節(jié)點(diǎn)不能連通也是有可能的,可能是因?yàn)榫W(wǎng)絡(luò)問(wèn)題或權(quán)限問(wèn)題,還可能因?yàn)樨?fù)載問(wèn)題,有的時(shí)候?qū)τ陂L(zhǎng)連接的請(qǐng)求A節(jié)點(diǎn)因?yàn)槭冀K連著存儲(chǔ)不會(huì)有問(wèn)題,新的B節(jié)點(diǎn)要求連接的時(shí)候因?yàn)槌鲎畲筮B接限制無(wú)法連接。如果有可能的話還暴露一些服務(wù)內(nèi)部各種線程池、連接池和隊(duì)列的信息吧(對(duì)象數(shù),隊(duì)列長(zhǎng)度等),這些指標(biāo)很關(guān)鍵,但是因?yàn)樵诔绦騼?nèi)部所以外圍很難感知到,有了一些關(guān)鍵指標(biāo)的外露對(duì)于排查性能問(wèn)題會(huì)方便很多。
不只是網(wǎng)站,服務(wù)也應(yīng)該暴露出健康信息,一來(lái)我們可以在外部收集這些信息進(jìn)行監(jiān)控匯總,二來(lái)我們的負(fù)載均衡器或發(fā)布系統(tǒng)需要有一個(gè)方式來(lái)判斷服務(wù)是否可用,不可用的時(shí)候進(jìn)行重啟或故障轉(zhuǎn)移。
對(duì)外的服務(wù)注意health端口的授權(quán),這里可能會(huì)有一些敏感信息,不宜讓匿名用戶看到。
實(shí)現(xiàn)上,我們應(yīng)當(dāng)把health端口作為插件形式集成到系統(tǒng),配置一下即可啟用,用不著每一個(gè)系統(tǒng)都自己開發(fā)一套。如果使用SpringBoot的話可以直接使用Actuator模塊實(shí)現(xiàn)。
1.8、絞殺者模式:通過(guò)使用新的應(yīng)用程序和服務(wù)逐漸替換特定功能部件來(lái)逐步遷移舊系統(tǒng)
名字挺嚇人,這個(gè)模式說(shuō)的是如何做遷移。通過(guò)建立一個(gè)門面來(lái)作為后端新老服務(wù)的路由,慢慢把服務(wù)替換為新服務(wù),最后當(dāng)所有的服務(wù)都是新服務(wù)后刪除這個(gè)門面即可。這樣對(duì)于消費(fèi)者感知不到這個(gè)遷移的過(guò)程。在上一篇文章中我們提到的換引擎的方式其實(shí)說(shuō)的是保留原有的門面,也是通過(guò)這個(gè)門面做底層引擎的替換。其實(shí)我覺(jué)得對(duì)于減少外圍影響這種模式是完全可以理所當(dāng)然想到的,真正難的過(guò)程還是之前說(shuō)的數(shù)據(jù)遷移和底層服務(wù)實(shí)現(xiàn)的過(guò)程。
二、性能和可擴(kuò)展性
2.1、緩存輔助模式:按需將數(shù)據(jù)從數(shù)據(jù)存儲(chǔ)加載到緩存中
這個(gè)模式說(shuō)的不是廣義上的緩存使用,而是其中的一種使用方式。我們對(duì)于緩存的使用一般有這么幾種方式:
查緩存,不存在查庫(kù),然后更新緩存
直接維護(hù)一大塊“全量”數(shù)據(jù),盡量和數(shù)據(jù)庫(kù)同步
這個(gè)模式說(shuō)的是后一種方式,對(duì)于數(shù)據(jù)變動(dòng)不大,這種模式是性能最好的,幾乎實(shí)現(xiàn)了100%的命中率,而且如果數(shù)據(jù)量不大可以容納進(jìn)進(jìn)程的話不需要跨進(jìn)程通訊。往細(xì)致一點(diǎn)去想,這里還有一層性能優(yōu)化的點(diǎn),因?yàn)槲覀冊(cè)趦?nèi)存中維護(hù)了一套復(fù)雜的全量數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),內(nèi)存中對(duì)象的引用只是指針引用,內(nèi)存中的數(shù)據(jù)搜索可以很快,對(duì)于數(shù)據(jù)量不大但是關(guān)系復(fù)雜的數(shù)據(jù),這個(gè)搜索效率可以是數(shù)據(jù)庫(kù)的幾百倍。實(shí)現(xiàn)上一般會(huì)在應(yīng)用程序啟動(dòng)的時(shí)候把數(shù)據(jù)完全加入內(nèi)存,在后續(xù)通過(guò)一些策略進(jìn)行數(shù)據(jù)更新:
定時(shí)更新同步數(shù)據(jù),不同數(shù)據(jù)可以有不同的更新頻率由后臺(tái)線程來(lái)更新
數(shù)據(jù)具有不同的過(guò)期時(shí)間,過(guò)期后由請(qǐng)求觸發(fā)主動(dòng)更新或回調(diào)方式被動(dòng)更新
數(shù)據(jù)修改后同步修改緩存和數(shù)據(jù)庫(kù)中的數(shù)據(jù)
2.2、命令和查詢責(zé)任分離模式:通過(guò)使用單獨(dú)的接口來(lái)分離讀取數(shù)據(jù)和更新數(shù)據(jù)的操作
英文縮寫是CQRS,看到這個(gè)關(guān)鍵字你可能會(huì)覺(jué)得有點(diǎn)熟悉了。CQRS原來(lái)說(shuō)的是我們可以有兩套數(shù)據(jù)模型分別用于讀和寫。好處是,我們可以讓讀和寫具有完全不同的數(shù)據(jù)結(jié)構(gòu),減少相互的干擾,減少權(quán)限控制的復(fù)雜度。這里說(shuō)的不一定是指架構(gòu)層面我們可以這么做,也指在程序內(nèi)部,我們可以有兩套命令模型來(lái)處理讀寫這兩個(gè)事情,分別進(jìn)行優(yōu)化和定制。
現(xiàn)在一般的做法是類似于上圖的做法,為讀寫配置兩套獨(dú)立的數(shù)據(jù)源,并且和事件溯源的方式結(jié)合起來(lái)做。我們來(lái)說(shuō)說(shuō)讀寫兩套模型在存儲(chǔ)上分離這個(gè)事情,在《相輔相成的存儲(chǔ)五件套》一文中我們的架構(gòu)圖其實(shí)就有這方面的意思。對(duì)于讀寫這兩個(gè)事情,我們完全可以不用一套數(shù)據(jù)源,為讀建立專門的物化視圖,可以針對(duì)讀進(jìn)行優(yōu)化,避免在讀的時(shí)候做很多Join的工作,可以把性能做到極致。事件溯源+CQRS+物化視圖三者一般會(huì)結(jié)合起來(lái)使用。
2.3、事件溯源模式:使用僅追加存儲(chǔ)去記錄描述對(duì)域中的數(shù)據(jù)采取的操作的完整系列事件
事件溯源(ES)是一種有趣的模式,說(shuō)的是我們記錄的不是數(shù)據(jù)的當(dāng)前狀態(tài)而是疊加的數(shù)據(jù)變化序列(是不是想到了區(qū)塊鏈的數(shù)據(jù)記錄方式)。傳統(tǒng)的CRUD方式因?yàn)橛懈逻@個(gè)操作,所以會(huì)產(chǎn)生性能并發(fā)方面的局限性,而且我們還需要配備額外的日志來(lái)做審計(jì),否則就產(chǎn)生了信息丟失。而事件溯源模式記錄的是事件而不是當(dāng)前狀態(tài),所以有下面的特點(diǎn):
事件不可變,只是追加新的事件,沒(méi)有沖突,性能高
以事件驅(qū)動(dòng)做外部處理,耦合低
保留第一手原始信息,信息沒(méi)有損耗
其實(shí)有一些業(yè)務(wù)場(chǎng)景下這種模式會(huì)比CRUD存儲(chǔ)更適合:
業(yè)務(wù)更看重?cái)?shù)據(jù)的意圖和目的而不是當(dāng)前的狀態(tài),注重審計(jì)、回滾、歷史方面的功能
希望避免數(shù)據(jù)更新的沖突,希望數(shù)據(jù)的產(chǎn)生能有較高性能,又能接受數(shù)據(jù)狀態(tài)的最終一致性
整個(gè)系統(tǒng)中本身就是以事件在驅(qū)動(dòng)的(我們可以想一下在真實(shí)的世界中,物體和物體之間相互影響,通過(guò)事件來(lái)影響,每個(gè)物體觀察到其它物體發(fā)出的事件來(lái)做出自己的反映,這是最自然的,而不是觀察到別的物體屬性的變化來(lái)調(diào)整自己的屬性)
反過(guò)來(lái)說(shuō),業(yè)務(wù)邏輯很簡(jiǎn)單的系統(tǒng),需要強(qiáng)一致性的系統(tǒng),數(shù)據(jù)很少更新的系統(tǒng)不適合這種模式。不知你所了解到的采用ES模式的業(yè)務(wù)場(chǎng)景有哪些?大家一起交流一下。
2.4、物化視圖模式:針對(duì)所需的查詢操作,當(dāng)數(shù)據(jù)沒(méi)有理想地格式化時(shí),在一個(gè)或多個(gè)數(shù)據(jù)存儲(chǔ)中的數(shù)據(jù)上生成預(yù)填充視圖
我們?cè)谑褂脭?shù)據(jù)存儲(chǔ)的時(shí)候往往會(huì)更多考慮存儲(chǔ)而不是讀取。我們使用各種數(shù)據(jù)庫(kù)范式來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù),在讀取數(shù)據(jù)的時(shí)候我們需要做大量的關(guān)聯(lián)查詢以輸出符合需要的查詢結(jié)果。這個(gè)時(shí)候性能往往會(huì)成為瓶頸,物化視圖是一種空間換時(shí)間的做法。與其在查詢的時(shí)候做關(guān)聯(lián),倒不如提前保存一份面向于查詢和輸出的數(shù)據(jù)格式。因此,物化視圖適合下面的場(chǎng)景:
經(jīng)過(guò)復(fù)雜的計(jì)算才能查詢出數(shù)據(jù)
背后存儲(chǔ)可能會(huì)有不穩(wěn)定的情況
需要連接多個(gè)不同類型的存儲(chǔ)才能查詢到結(jié)果
但是因?yàn)樾枰紤]到物化視圖計(jì)算保存的開銷,所以也不太適合于數(shù)據(jù)變化太頻繁的情況,因?yàn)閿?shù)據(jù)加工需要時(shí)間,所以不適合需要數(shù)據(jù)強(qiáng)一致性的場(chǎng)景。
實(shí)現(xiàn)上一般是基于消息監(jiān)聽做額外維護(hù)一套物化視圖的數(shù)據(jù)源和主流程解耦。惠普的Vertica是一款高性能的列式分析數(shù)據(jù)庫(kù),它的一個(gè)特性就是物化視圖,通過(guò)事先提供SQL語(yǔ)句直接緩存面向于統(tǒng)計(jì)的查詢結(jié)果,極大程度提高了性能,也是空間換時(shí)間的思想。
2.5、基于隊(duì)列的負(fù)載均衡模式:使用一個(gè)隊(duì)列作為任務(wù)和服務(wù)之間的緩沖區(qū),平滑間歇性重負(fù)載
消息隊(duì)列我們太熟悉了,之前我們也反復(fù)提高過(guò)好多次,甚至我說(shuō)這是架構(gòu)三馬車之一。這個(gè)模式在這里強(qiáng)調(diào)的是削峰的優(yōu)勢(shì)。這里我還想提幾點(diǎn):
引入消息隊(duì)列不會(huì)提高處理能力,而是會(huì)降低性能,只是我們把耦合解開了允許每一個(gè)部件單獨(dú)有自己的彈性,對(duì)于不能負(fù)荷的部分在隊(duì)列中進(jìn)行緩沖,緩沖不是存儲(chǔ)不意味無(wú)限制
隊(duì)列看的是處理速度和入隊(duì)速度的比例,一般而言,我們需要預(yù)先做評(píng)估確保處理TPS超過(guò)2倍的最高峰的入隊(duì)TPS,確保留出一半的富裕,這樣在業(yè)務(wù)邏輯有修改的時(shí)候處理TPS哪怕下降了30%,還能抗住壓力
2.6、優(yōu)先級(jí)隊(duì)列模式:確定發(fā)送到服務(wù)的請(qǐng)求的優(yōu)先級(jí),使得具有較高優(yōu)先級(jí)的請(qǐng)求更快地被接收和處理
區(qū)別于FIFO結(jié)構(gòu)的隊(duì)列,優(yōu)先級(jí)隊(duì)列允許消息標(biāo)識(shí)處理優(yōu)先級(jí)。這里實(shí)現(xiàn)上如上面兩個(gè)圖有兩種方式:
消息優(yōu)先級(jí)方式。在隊(duì)列中進(jìn)行實(shí)時(shí)位置重排,永遠(yuǎn)優(yōu)先處理級(jí)別較高的消息。
不同的處理池方式。我們可以針對(duì)不同的處理級(jí)別配備專門的處理池來(lái)處理這些消息,高級(jí)別的消息具有更多的處理資源,更好的硬件來(lái)處理,這樣勢(shì)必會(huì)有較高的處理能力。
在方案選擇和實(shí)現(xiàn)上要考慮消息優(yōu)先級(jí)是否需要絕對(duì)按照優(yōu)先級(jí)來(lái)處理,還是說(shuō)相對(duì)優(yōu)先處理即可,如果需要絕對(duì)優(yōu)先那么除了消息位置重排還需要有搶占處理。還有,如果我們采用第二種多池的方式來(lái)處理的話可能會(huì)發(fā)生低級(jí)別的消息處理時(shí)間比高級(jí)別的消息更快的可能性(如果兩者處理業(yè)務(wù)邏輯是完全不同的話)。
實(shí)現(xiàn)上的話RabbitMQ 3.5以上版本支持了消息優(yōu)先級(jí),實(shí)現(xiàn)的是第一種方式,在消息有緩沖的堆積的時(shí)候進(jìn)行消息重排,消費(fèi)端可以先看到先處理優(yōu)先級(jí)高的消息,這種方式在消費(fèi)速度大于產(chǎn)出速度的場(chǎng)景下是無(wú)法實(shí)現(xiàn)高級(jí)別消息優(yōu)先處理的。
補(bǔ)充一點(diǎn),對(duì)于隊(duì)列中的消息,還有一種需要特別考慮的就是一直停留在隊(duì)列的消息應(yīng)當(dāng)視為低優(yōu)先級(jí)或是死信消息來(lái)處理,最好是有單獨(dú)的消費(fèi)者來(lái)處理,避免此類消息影響了整個(gè)隊(duì)列的處理,見(jiàn)過(guò)很多個(gè)事故是由于隊(duì)列中被廢棄消息卡死導(dǎo)致徹底喪失處理能力的。
2.7、限流模式:控制應(yīng)用程序,個(gè)人租戶或整個(gè)服務(wù)的實(shí)例消耗的資源
在做壓力測(cè)試的時(shí)候我們會(huì)發(fā)現(xiàn),隨著壓力的上升系統(tǒng)的吞吐慢慢變大而且這個(gè)時(shí)候響應(yīng)時(shí)間可以基本保持可控(1秒內(nèi)),當(dāng)壓力突破一個(gè)邊界后,響應(yīng)時(shí)間一下子會(huì)不可控,隨之系統(tǒng)的吞吐就會(huì)下降,最后會(huì)徹底崩潰。任何系統(tǒng)對(duì)于壓力的負(fù)荷是有邊界的,超過(guò)這個(gè)邊界之后系統(tǒng)的SLA肯定無(wú)法滿足標(biāo)準(zhǔn),導(dǎo)致大家都無(wú)法好好用這個(gè)服務(wù)。因?yàn)橄到y(tǒng)的擴(kuò)展往往不是秒級(jí)可以做到的,所以這個(gè)時(shí)候最快的手段就是限流,只有限流了才能保護(hù)現(xiàn)在的系統(tǒng)不至于突破這個(gè)邊界徹底崩潰。對(duì)于業(yè)務(wù)量超大的系統(tǒng)搞活動(dòng),對(duì)關(guān)鍵服務(wù)甚至入口層面做限流是必然的,別無(wú)它法,淘寶雙11凌晨0點(diǎn)那一刻也能看到一定比例的下單被限流了。
常見(jiàn)的限流算法有這么幾種:
計(jì)數(shù)器算法。最簡(jiǎn)單的算法,資源使用加一,釋放減一,達(dá)到一定的計(jì)數(shù)拒絕服務(wù)。
令牌桶算法。按照固定速率往桶里加令牌,桶里最多存放n個(gè)令牌,填滿丟棄。處理的時(shí)候需要獲取令牌,獲取不到則拒絕請(qǐng)求。
漏桶算法。一個(gè)固定容量的漏洞,按照一定的速度流出水滴(任務(wù))。可以以任意速度流入水滴(任務(wù)),滿了則溢出丟棄。
令牌桶算法限制的是平均流入速度,允許一定程度的突發(fā)請(qǐng)求,漏桶算法限制的是常量的流出速率用于平滑流入的速度。實(shí)現(xiàn)上,常用的一些開源類庫(kù)都會(huì)有相關(guān)的實(shí)現(xiàn),比如google的Guava提供的RateLimiter就是令牌桶算法。
限流模式有下面的一些注意事項(xiàng):
限流需要快速執(zhí)行,任何一個(gè)超出流量控制的請(qǐng)求不允許放行,否則沒(méi)有意義。
限流需要提前執(zhí)行,最好在系統(tǒng)能力達(dá)到80%的時(shí)候進(jìn)行限流,越晚限流風(fēng)險(xiǎn)越大。
可以返回特定的限流控制錯(cuò)誤代碼給客戶端,讓用戶知道這不是錯(cuò)誤是限流,可以稍后再試。
因?yàn)槲覀兊南到y(tǒng)很多地方都會(huì)做限流,在監(jiān)控圖上我們最好對(duì)這類限流的曲線有敏感,限流后的曲線是一下子失去了增長(zhǎng)的梯度變?yōu)榱似椒€(wěn)的狀態(tài),如果監(jiān)控圖看的時(shí)間范圍過(guò)小的話會(huì)誤判這是一個(gè)正常的請(qǐng)求量。
限流可以在邊緣節(jié)點(diǎn)做。我們來(lái)考慮秒殺的場(chǎng)景,如果一秒有100萬(wàn)個(gè)請(qǐng)求,這100萬(wàn)個(gè)請(qǐng)求全部打到我們的應(yīng)用服務(wù)器沒(méi)有意義,我們可以在邊緣節(jié)點(diǎn)(CDN)甚至客戶端上做簡(jiǎn)單的邊緣計(jì)算,讓這100萬(wàn)個(gè)請(qǐng)求采用命中注定的方式直接隨機(jī)放棄其中的99.9%留下1000個(gè)請(qǐng)求,最終可以進(jìn)入我們的業(yè)務(wù)服務(wù),這樣TPS在1000一般是沒(méi)有問(wèn)題的。所以很多時(shí)候我們參與秒殺,系統(tǒng)會(huì)在極短的時(shí)間內(nèi)毫無(wú)思考告知你活動(dòng)已結(jié)束,說(shuō)明你已經(jīng)是被選中的命中注定的無(wú)法進(jìn)入后端系統(tǒng)來(lái)參與秒殺的那些人。
三、數(shù)據(jù)管理模式
3.1、分片模式:將數(shù)據(jù)存儲(chǔ)區(qū)劃分為一組水平分區(qū)或分片
一直有一個(gè)說(shuō)法就是不到?jīng)]路可走的時(shí)候不要考慮數(shù)據(jù)庫(kù)分片。有的時(shí)候業(yè)務(wù)量大到單個(gè)業(yè)務(wù)表在經(jīng)過(guò)緩存+隊(duì)列削峰等措施之后的平均的TPS超過(guò)1萬(wàn),單表實(shí)在是扛不住,還是只能考慮分片手段。
分片前:
需要根據(jù)數(shù)據(jù)分布、壓力情況、業(yè)務(wù)邏輯確定分片的方式,按照條件還是范圍還是哈希等等(三個(gè)圖展示了三種策略)。
需要進(jìn)行業(yè)務(wù)代碼改造,改掉所有不允許的SQL。
需要確定用HardCode方式還是框架方式還是中間件方式做數(shù)據(jù)路由。
分片后:
需要有運(yùn)維工具可以對(duì)這么多套分片的數(shù)據(jù)進(jìn)行統(tǒng)一的加索引等操作。
最好有數(shù)據(jù)倉(cāng)庫(kù)可以匯總所有數(shù)據(jù),使得adhoc查詢可以更方便。
最好有輔助工具可以用來(lái)幫助定位數(shù)據(jù)會(huì)在哪個(gè)分片中。
3.2、靜態(tài)內(nèi)容托管模式:將靜態(tài)內(nèi)容部署到基于云的存儲(chǔ)服務(wù),可以將它們直接傳遞給客戶端
相信互聯(lián)網(wǎng)公司90%+肯定都使用了這個(gè)模式。把靜態(tài)資源從動(dòng)態(tài)網(wǎng)站中剝離由Nginx等高性能服務(wù)器來(lái)處理靜態(tài)資源,然后使用三方CDN對(duì)靜態(tài)資源進(jìn)行加速,不但減輕了動(dòng)態(tài)網(wǎng)站的負(fù)載而且數(shù)據(jù)在邊緣節(jié)點(diǎn)加速讓用戶的訪問(wèn)跟快,使用單獨(dú)的一個(gè)或多個(gè)子域名做靜態(tài)資源還能提高下載資源的并行度提高網(wǎng)頁(yè)加載的速度。
使用CDN來(lái)進(jìn)行資源加速一般有主動(dòng)數(shù)據(jù)傳送到CDN存儲(chǔ)和在CDN配置回源站拉取兩種方式,文件類一般使用主動(dòng)推送數(shù)據(jù),靜態(tài)資源類一般使用回源方式。在使用CDN的時(shí)候考慮下面的問(wèn)題:
CDN以什么方式來(lái)認(rèn)定同一個(gè)文件的,CDN提供了什么工具來(lái)刷新邊緣節(jié)點(diǎn)的緩存?根據(jù)不同的策略做相應(yīng)的緩存刷新方案。
源站對(duì)于相同的文件需要有一致性(最好版本變化后文件名變化),不能今天是這個(gè)版本明天是另一個(gè)版本,這樣很可能導(dǎo)致邊緣節(jié)點(diǎn)緩存了不同版本的文件,導(dǎo)致各種怪問(wèn)題。
使用了CDN后不同地區(qū)的用戶訪問(wèn)的都是CDN節(jié)點(diǎn)上的數(shù)據(jù),一旦出現(xiàn)問(wèn)題排查比較困難,考慮引入前端的錯(cuò)誤處理框架來(lái)記錄前端出現(xiàn)腳本錯(cuò)誤時(shí)的調(diào)用棧,方便定位問(wèn)題。
3.3、索引表模式:為查詢經(jīng)常引用的數(shù)據(jù)存儲(chǔ)區(qū)中的字段創(chuàng)建索引
雖然我們的關(guān)系型數(shù)據(jù)庫(kù)大多支持主鍵之外的非聚集索引,但是在某些情況下直接對(duì)大表做很多索引性能并不好。
做了Sharding后我們確實(shí)沒(méi)有辦法以分片鍵之外的維度來(lái)查詢數(shù)據(jù)。
希望以空間換時(shí)間,直接把某個(gè)維度的復(fù)合查詢作為主鍵單獨(dú)保存一份數(shù)據(jù)。
不過(guò)需要考慮一點(diǎn)索引只有在數(shù)據(jù)區(qū)分度高的情況下才能發(fā)揮價(jià)值,如果90%以上的數(shù)據(jù)都是相同的值,那么走索引進(jìn)行查詢性能會(huì)比全表掃還要差一點(diǎn)。
四、設(shè)計(jì)和實(shí)現(xiàn)模式
4.1、前端專用的后端模式:通過(guò)使用單獨(dú)的接口來(lái)分離讀取數(shù)據(jù)和更新數(shù)據(jù)的操作
這里說(shuō)的是不同的前端配以不同的專用后端。比如PC網(wǎng)站和APP的后端是兩套程序。這種模式是否適合其實(shí)還是看兩端的后端提供的數(shù)據(jù)差異有多大,我們總是希望可以盡量統(tǒng)一一套后端,業(yè)務(wù)邏輯不用重復(fù)寫,但是我們要考慮到PC網(wǎng)站和APP的差異性:
APP系統(tǒng)的接口交互一般會(huì)簽名驗(yàn)證,有的時(shí)候還會(huì)加密
PC系統(tǒng)的流程一般和APP系統(tǒng)不一樣
PC一個(gè)頁(yè)面能顯示的內(nèi)容會(huì)比APP一個(gè)界面顯示的更多
安全性設(shè)計(jì)上PC和APP不一樣,APP很少有圖形驗(yàn)證碼
考慮到這些差異,我們是在一個(gè)工程內(nèi)根據(jù)來(lái)源做適配,還是獨(dú)立兩套工程來(lái)做獨(dú)立的后端取決于差異度有多大了。
4.2、計(jì)算資源整合模式:將多個(gè)任務(wù)或操作整合到單個(gè)計(jì)算單元中
這個(gè)模式從資源節(jié)省的角度來(lái)說(shuō)我們的計(jì)算單元任務(wù)可以進(jìn)行一些合并,減少因?yàn)橘Y源限制導(dǎo)致不必要的開銷。
4.3、選舉模式:通過(guò)選舉一個(gè)實(shí)例作為負(fù)責(zé)管理其它實(shí)例的負(fù)責(zé)人,來(lái)協(xié)調(diào)分布式應(yīng)用程序中的協(xié)作任務(wù)實(shí)例集合執(zhí)行的操作
對(duì)于分布式服務(wù),我們趨向于把服務(wù)設(shè)計(jì)為無(wú)狀態(tài)可以任意擴(kuò)展的,但是在某些業(yè)務(wù)場(chǎng)景下我們不得不在服務(wù)中選舉出一個(gè)Leader(Primary節(jié)點(diǎn),Master節(jié)點(diǎn))來(lái)做一些不適合重復(fù)做的協(xié)調(diào)管理工作。這個(gè)時(shí)候我們需要有算法來(lái)做選舉。
最常見(jiàn)的實(shí)現(xiàn)方式是使用Zookeeper來(lái)實(shí)現(xiàn),我們知道ZK的znode有Sequence和NonSequence兩種,前者多個(gè)客戶端只有一個(gè)可創(chuàng)建成功同名節(jié)點(diǎn),后者創(chuàng)建后會(huì)自動(dòng)加上序列號(hào)命名多個(gè)客戶端可以創(chuàng)建多個(gè)同名節(jié)點(diǎn),利用這個(gè)特性有兩種常見(jiàn)實(shí)現(xiàn)方式:
非公平實(shí)現(xiàn)。多個(gè)客戶端同時(shí)創(chuàng)建EPHEMERAL+NONSEQUENCE節(jié)點(diǎn)。只有一個(gè)可以創(chuàng)建成功,創(chuàng)建成功的就是Leader,其它的Follower需要注冊(cè)watch,一旦Leader放棄節(jié)點(diǎn)(注意,EPHEMERAL意味著Leader待機(jī)后Session結(jié)束節(jié)點(diǎn)被刪除),再一次重復(fù)之前的過(guò)程注冊(cè)節(jié)點(diǎn)搶占成為L(zhǎng)eader。這個(gè)模式實(shí)現(xiàn)簡(jiǎn)單,問(wèn)題是在節(jié)點(diǎn)數(shù)量過(guò)多的時(shí)候一旦發(fā)生重新競(jìng)選,這個(gè)時(shí)候可能會(huì)有性能問(wèn)題。
公平實(shí)現(xiàn)。多個(gè)客戶端同時(shí)創(chuàng)建EPHEMERAL+SEQUENCE節(jié)點(diǎn)。客戶端都可以創(chuàng)建成功節(jié)點(diǎn),客戶端如果判斷自己是最小的節(jié)點(diǎn)則為L(zhǎng)eader否則為Follower。每一個(gè)Follower都去watch序號(hào)比自己小的節(jié)點(diǎn)(大家都看前一位)。一旦有Leader節(jié)點(diǎn)因?yàn)殄礄C(jī)被刪除(還是EPHEMERAL特性),收到通知的節(jié)點(diǎn)會(huì)看自己是不是最小的序號(hào),如果是的話成為L(zhǎng)eader。節(jié)點(diǎn)宕機(jī)后,原先watch宕機(jī)節(jié)點(diǎn)的客戶端重新watch比自己序號(hào)小的有效節(jié)點(diǎn)。這個(gè)模式實(shí)現(xiàn)復(fù)雜,但是由于watch的都只是一個(gè)節(jié)點(diǎn)所以不會(huì)發(fā)生像非公平實(shí)現(xiàn)的性能問(wèn)題,而且競(jìng)選根據(jù)節(jié)點(diǎn)序號(hào)來(lái)而不是搶占式所以顯得Leader的選舉公平有序。
4.4、管道和過(guò)濾器模式:將需要執(zhí)行復(fù)雜處理的任務(wù)分解成可以重復(fù)使用的一系列單獨(dú)的元素
在軟件設(shè)計(jì)模式中過(guò)濾器構(gòu)成的管道這種模式很常見(jiàn)(圖上的業(yè)務(wù)邏輯就是Handler,之前的那些Task就是Filter,模式上可以是Filter+Handler也可以是Filter+Handler+Filter也可以是Handler+Filter),不管是Spring MVC框架也好,Netty這種網(wǎng)絡(luò)框架也好都提供了這樣的設(shè)計(jì)。每一個(gè)過(guò)濾器單獨(dú)完成一個(gè)功能,可以獨(dú)立插拔隨意組合配置成一套管道,不但數(shù)據(jù)處理的整個(gè)過(guò)程清晰可見(jiàn)還增加了靈活性。
對(duì)于架構(gòu)上也可以有這樣的模式,在數(shù)據(jù)源進(jìn)入到業(yè)務(wù)邏輯處理之前(或之后,或前后),我們可以配置一系列的數(shù)據(jù)過(guò)濾器完成各種數(shù)據(jù)轉(zhuǎn)化和處理的任務(wù)。Task和Task之間可以是同步調(diào)用,也可以使用MQ做一定的可伸縮性設(shè)計(jì)。還可以把過(guò)濾器的配置信息保存在配置系統(tǒng)中甚至根據(jù)上下文動(dòng)態(tài)構(gòu)建出管道,實(shí)現(xiàn)更靈活的前置或后置流程處理。
五、消息模式
5.1、競(jìng)爭(zhēng)消費(fèi)者模式:使用多個(gè)并發(fā)消費(fèi)者來(lái)處理在同一消息通道上接收的消息
這里說(shuō)的是消息隊(duì)列的消息消費(fèi)者是一組對(duì)等的消費(fèi)者,通過(guò)競(jìng)爭(zhēng)方式來(lái)拉取數(shù)據(jù)執(zhí)行。之前提到過(guò)這是MQ的最常見(jiàn)的一種模式,一般而言我們會(huì)部署多個(gè)消費(fèi)節(jié)點(diǎn)進(jìn)行負(fù)載均衡,在負(fù)載較大的時(shí)候可以方便得增加消費(fèi)者進(jìn)行消費(fèi)能力擴(kuò)容。不過(guò)對(duì)于這種模式消費(fèi)者應(yīng)當(dāng)是對(duì)等的無(wú)狀態(tài)的,在某個(gè)消費(fèi)者在消費(fèi)失敗的時(shí)候消息重新回到隊(duì)列隨后可能會(huì)被另一個(gè)消費(fèi)者進(jìn)行處理。
5.2、重試模式:在應(yīng)用程序嘗試連接到服務(wù)或網(wǎng)絡(luò)資源遇到預(yù)期的臨時(shí)故障時(shí),讓程序通過(guò)透明地重試以前失敗的操作來(lái)處理
重試適用于瞬態(tài)故障,之后會(huì)提到斷路器模式,兩種模式可以結(jié)合使用。首先說(shuō)說(shuō)重試的幾個(gè)發(fā)起人:
讓用戶自己發(fā)起,遇到錯(cuò)誤的時(shí)候及時(shí)返回錯(cuò)誤信息,讓用戶自己稍后重試整個(gè)業(yè)務(wù)功能。這種方式不容易產(chǎn)生瞬時(shí)的壓力,但是體驗(yàn)較差。
在中間件自動(dòng)發(fā)起,比如在RPC調(diào)用的時(shí)候遇到服務(wù)超時(shí)自動(dòng)進(jìn)行一定次數(shù)的重試,這樣可以在外部沒(méi)有感知的情況下有一定概率消除錯(cuò)誤。這個(gè)方式要求服務(wù)是支持重試的。
由業(yè)務(wù)邏輯手動(dòng)發(fā)起,不同的業(yè)務(wù)邏輯根據(jù)需求在代碼中去寫重試的邏輯(當(dāng)然也可以通過(guò)類似Spring-Retry這種組件來(lái)做)。實(shí)現(xiàn)繁瑣但是不容易出錯(cuò)。
由補(bǔ)償邏輯發(fā)起進(jìn)行同步轉(zhuǎn)異步操作,非重要邏輯同步行則行,不行不在主流程重試,由單獨(dú)的異步流程進(jìn)行重試補(bǔ)償。
重試也要考慮幾種策略:
次數(shù)。最多重試幾次。
異常。遇到什么樣的異常(黑白名單)應(yīng)該去重試。
等待。考慮每次重試是相同的間隔呢還是有一個(gè)延遲的遞增,隨著重試次數(shù)增加而增加延時(shí)時(shí)間。
5.3、調(diào)度、代理、主管模式:在一組分布式服務(wù)和其它遠(yuǎn)程資源之間協(xié)調(diào)一組操作
這個(gè)模式說(shuō)的是三者的角色:
調(diào)度負(fù)責(zé)安排任務(wù),在執(zhí)行每個(gè)步驟的時(shí)候維護(hù)任務(wù)的狀態(tài),具體業(yè)務(wù)邏輯由代理負(fù)責(zé)。
代理負(fù)責(zé)和遠(yuǎn)程的服務(wù)和資源進(jìn)行通訊,實(shí)現(xiàn)錯(cuò)誤處理和重試。
管理者負(fù)責(zé)監(jiān)視任務(wù)的執(zhí)行狀態(tài),作為調(diào)度的補(bǔ)充,在合適的時(shí)候要求調(diào)度進(jìn)行補(bǔ)償。
三個(gè)角色相互配合完成復(fù)雜的,具有較多遠(yuǎn)程服務(wù)參與的任務(wù),確保任務(wù)的最終有效執(zhí)行。在之前架構(gòu)三馬車一文中說(shuō)到定時(shí)任務(wù)的時(shí)候提到過(guò)一種任務(wù)驅(qū)動(dòng)表的模式,說(shuō)到了一些驅(qū)動(dòng)表的實(shí)現(xiàn)細(xì)節(jié),其實(shí)整體和這個(gè)模式是類似的思想。當(dāng)我們的一個(gè)復(fù)雜邏輯有多個(gè)步驟構(gòu)成,每一步都依賴外部服務(wù),這個(gè)時(shí)候我們可以選擇全程MQ+補(bǔ)償方式(樂(lè)觀方式),也可以選擇全程任務(wù)驅(qū)動(dòng)的被動(dòng)模式(悲觀方式),具體選擇取決于更看重可靠性還是及時(shí)性。
六、彈性模式
6.1、艙壁模式:將應(yīng)用程序的元素隔離到池中,如果其中一個(gè)失敗,其它的將繼續(xù)運(yùn)行
資源隔離有好幾個(gè)層次,可以在進(jìn)程內(nèi)部做線程池或隊(duì)列的隔離,在微服務(wù)的服務(wù)劃分上考慮隔離出單獨(dú)的物理服務(wù),或是在服務(wù)器層面通過(guò)虛擬化技術(shù)或Docker技術(shù)進(jìn)行資源隔離。隔離了就不會(huì)相互影響,但是會(huì)有成本、性能、管理便利性方面的開銷。實(shí)現(xiàn)能夠根據(jù)需求分析出可能的資源相互影響的點(diǎn),提前規(guī)劃隔離往往可以避免很多問(wèn)題的發(fā)生。之前有遇到過(guò)幾個(gè)事故是這樣的:
程序內(nèi)部大量使用了Java8的ParallelStream特性進(jìn)行并行處理,由于默認(rèn)共享了相同的線程池,某一個(gè)業(yè)務(wù)的執(zhí)行占滿了線程影響了其它業(yè)務(wù)的正常進(jìn)行。
消息隊(duì)列因?yàn)闆](méi)有對(duì)執(zhí)行過(guò)多次失敗的死信消息和正常的新消息進(jìn)行隔離,導(dǎo)致一些業(yè)務(wù)下線后無(wú)法處理的死消息占滿了整個(gè)隊(duì)列,正常消息無(wú)法消費(fèi)。
某個(gè)服務(wù)提供了類似文件上傳的重量級(jí)操作,也提供了數(shù)據(jù)查詢的輕量級(jí)操作,在上傳業(yè)務(wù)大的時(shí)候服務(wù)的線程都被IO所占滿,導(dǎo)致其它查詢操作無(wú)法進(jìn)行。
6.2、斷路器模式:連接到遠(yuǎn)程服務(wù)或資源時(shí), 處理可能需要花費(fèi)時(shí)間來(lái)修復(fù)的故障
分布式應(yīng)用環(huán)節(jié)多網(wǎng)絡(luò)環(huán)境復(fù)雜,如果遇到依賴服務(wù)調(diào)用失敗的情況我們或許可以進(jìn)行重試期待服務(wù)馬上可以恢復(fù),但是在某些時(shí)候依賴的服務(wù)是徹底掛了而不是網(wǎng)絡(luò)故障無(wú)法及時(shí)恢復(fù),如果不考慮進(jìn)行熔斷的,可能服務(wù)調(diào)用方會(huì)被服務(wù)提供方拖死。這個(gè)時(shí)候可以引入斷路器機(jī)制,如圖所示斷路器一般采用三態(tài)實(shí)現(xiàn),瞬間恢復(fù)可能會(huì)讓底層服務(wù)壓力過(guò)大:
關(guān)閉:出現(xiàn)錯(cuò)誤的時(shí)候增加計(jì)數(shù)器
打開:計(jì)數(shù)器到達(dá)閾值打開斷路器,直接返回錯(cuò)誤
半開:超時(shí)后允許一定的請(qǐng)求通過(guò),成功率達(dá)到閾值關(guān)閉斷路器,操作還是失敗的話還是進(jìn)入打開狀態(tài)
實(shí)現(xiàn)模式的時(shí)候考慮下面注意點(diǎn):
考慮熔斷后怎么來(lái)處理,熔斷后我們肯定拿不到實(shí)際的處理結(jié)果,這個(gè)時(shí)候考慮是功能降級(jí)還是采用后備的數(shù)據(jù)提供方來(lái)提供數(shù)據(jù)
緊急的時(shí)候需要人工介入,最好在外部提供手動(dòng)的方式可以干預(yù)斷路器的三態(tài)
不同的業(yè)務(wù)考慮不同的斷路器打開閾值,每一個(gè)錯(cuò)誤還能有不同的權(quán)重,比如對(duì)于下游程序返回了太多請(qǐng)求的錯(cuò)誤,每次錯(cuò)誤可以+2提高權(quán)重盡可能早斷路
斷路器應(yīng)當(dāng)記錄熔斷時(shí)的請(qǐng)求原始信息,在之后必要的時(shí)候可以進(jìn)行重放或數(shù)據(jù)修復(fù)工作
注意設(shè)置好外部服務(wù)的超時(shí),如果客戶端超時(shí)比服務(wù)端短,很可能進(jìn)行錯(cuò)誤的熔斷
實(shí)現(xiàn)上我們可以看一下Netflix的Hystrix進(jìn)行進(jìn)一步了解。
6.3、事務(wù)補(bǔ)償模式:撤消通過(guò)一系列步驟執(zhí)行的工作,它們一起定義最終一致的操作
這個(gè)模式說(shuō)的是失敗時(shí)必須進(jìn)行撤銷的操作,可以由一組補(bǔ)償程序來(lái)做相應(yīng)的補(bǔ)償。在這里我想說(shuō)的更廣一點(diǎn),在服務(wù)調(diào)用的時(shí)候,調(diào)用失敗有幾種可能:
請(qǐng)求客戶端發(fā)出但是沒(méi)到服務(wù)端,業(yè)務(wù)邏輯沒(méi)有執(zhí)行
請(qǐng)求客戶端發(fā)出服務(wù)端收到也處理成功了,業(yè)務(wù)邏輯執(zhí)行了客戶端沒(méi)收到結(jié)果
請(qǐng)求客戶端發(fā)出服務(wù)端收到但處理失敗了,客戶端沒(méi)收到結(jié)果
所以在出現(xiàn)服務(wù)調(diào)用失敗或超時(shí)的時(shí)候,服務(wù)端執(zhí)行究竟有沒(méi)有成功客戶端是不明確的(只有客戶端收到了明確的服務(wù)端返回的業(yè)務(wù)錯(cuò)誤才真正代表執(zhí)行失?。@個(gè)時(shí)候需要有補(bǔ)償邏輯來(lái)同步服務(wù)端的執(zhí)行狀態(tài)。如果這樣的補(bǔ)償不可避免而且需要補(bǔ)償?shù)姆?wù)特別多,這樣的邏輯逐一來(lái)寫是一件很煩的事情,我們可以把這個(gè)工作封裝成一個(gè)補(bǔ)償中間件來(lái)處理:
所有關(guān)鍵服務(wù)調(diào)用標(biāo)記為需要自動(dòng)補(bǔ)償
補(bǔ)償中間件在數(shù)據(jù)庫(kù)記錄服務(wù)的調(diào)用狀態(tài)
關(guān)鍵服務(wù)的提供者提供統(tǒng)一狀態(tài)查詢接口,消費(fèi)者提供統(tǒng)一的補(bǔ)償回調(diào)接口(來(lái)處理成功和失敗的情況)
補(bǔ)償中間件根據(jù)數(shù)據(jù)庫(kù)的記錄調(diào)用服務(wù)提供方的狀態(tài)查詢和服務(wù)消費(fèi)方的補(bǔ)償回調(diào)接口進(jìn)行補(bǔ)償
這樣,我們?cè)诜?wù)調(diào)用的時(shí)候就不需要考慮補(bǔ)償邏輯的實(shí)現(xiàn),只要實(shí)現(xiàn)這個(gè)標(biāo)準(zhǔn)即可。
七、安全模式
7.1、代客密鑰模式:使用向客戶端提供對(duì)特定資源或服務(wù)的有限直接訪問(wèn)權(quán)限的令牌或密鑰
這個(gè)模式說(shuō)的是,在訪問(wèn)敏感資源的時(shí)候,我們可以不必讓應(yīng)用程序在其中作為一個(gè)代理轉(zhuǎn)一層做權(quán)限控制,而是生成一個(gè)密鑰,讓用戶直接拿著密鑰到資源池?fù)Q數(shù)據(jù)。
一些CDN在提供資源上傳下載服務(wù)的時(shí)候一般都會(huì)提供類似的安全策略,需要實(shí)現(xiàn)生成Token才能去使用下載和上傳服務(wù),避免了CDN數(shù)據(jù)被非法利用作為圖床的可能。
實(shí)現(xiàn)上比較簡(jiǎn)單,應(yīng)用程序和資源提供方約定好Token的生成算法,對(duì)資源+請(qǐng)求資源的時(shí)間+密鑰聯(lián)合在一起做簽名,資源提供方如果校驗(yàn)到簽名不正確或Token過(guò)期或資源不匹配都將拒絕服務(wù)。
7.2、聯(lián)合身份模式:將認(rèn)證委托給外部身份提供者
這個(gè)模式說(shuō)的是將身份驗(yàn)證委托給專門的程序或模塊來(lái)做。使用專門的模塊來(lái)統(tǒng)一負(fù)責(zé)登錄授權(quán)不僅僅可以提供單點(diǎn)登錄的功能,而且服務(wù)實(shí)現(xiàn)上更簡(jiǎn)單不需要每次都考慮登錄那套東西。實(shí)現(xiàn)上可以看一下Spring Security實(shí)現(xiàn)的OAuth 2.0。
總結(jié)一下,對(duì)于其中的很多模式,我們可以發(fā)現(xiàn)其實(shí)在之前的一些介紹或多或少有一些涉及。這里提到的30種模式有些體現(xiàn)的是一些設(shè)計(jì)細(xì)節(jié),有些體現(xiàn)的是一種設(shè)計(jì)理念,它們大多時(shí)候是組合使用的,適合的就是最好的,大家可以細(xì)細(xì)品味一下每種模式的適合場(chǎng)景,在合適的時(shí)候可以想到它或許會(huì)有一種豁然開朗的感覺(jué)。
本文標(biāo)題:商丘互聯(lián)網(wǎng)公司常用架構(gòu)模式梳理
本文鏈接http://njylbyy.cn/xinwenzhongxin/1039.html
- 商丘阿里國(guó)際站代運(yùn)營(yíng):沒(méi)有詢盤怎么辦
- 商丘阿里國(guó)際站代運(yùn)營(yíng):如何提升點(diǎn)擊率
- 商丘阿里國(guó)際站代運(yùn)營(yíng):阿里國(guó)際站沒(méi)效果怎么辦?
- 商丘外貿(mào)推廣:Facebook賬號(hào)怎么注冊(cè)
- 商丘外貿(mào)推廣:Facebook營(yíng)銷如何開展
- 商丘建跨境獨(dú)立站公司哪家好
- 商丘外貿(mào)建站公司哪家好
- 商丘阿里國(guó)際站代運(yùn)營(yíng):常見(jiàn)運(yùn)營(yíng)誤區(qū)有哪些
- 商丘阿里國(guó)際站代運(yùn)營(yíng):這些運(yùn)營(yíng)錯(cuò)誤千萬(wàn)不要犯!
- 商丘外貿(mào)建站推廣為什么要重視新聞板塊
- 商丘外貿(mào)推廣如何進(jìn)行新聞撰寫
- 商丘阿里國(guó)際站代運(yùn)營(yíng):現(xiàn)在阿里國(guó)際站還能做嗎?
- 商丘阿里國(guó)際站代運(yùn)營(yíng)提醒:國(guó)際站開通前這些準(zhǔn)備要做好
- 商丘外貿(mào)推廣為什么離不開外貿(mào)建站
- 商丘外貿(mào)建站有什么作用
- 商丘阿里國(guó)際站代運(yùn)營(yíng):這些細(xì)節(jié)不可忽視
- 商丘阿里國(guó)際站代運(yùn)營(yíng):這些基礎(chǔ)工作要做好
- 商丘外貿(mào)建站如何做更具有吸引力
- 商丘外貿(mào)建站怎么樣做有利于推廣
- 商丘阿里國(guó)際站代運(yùn)營(yíng):運(yùn)營(yíng)這幾個(gè)誤區(qū)你中了幾個(gè)