微服务的容错模式
http://www.360doc.com/content/18/0222/08/10346540_731371833.shtml
在使用了微服務(wù)架構(gòu)以后,整體的業(yè)務(wù)流程被拆分成小的微服務(wù),并組合在一起對外提供服務(wù),微服務(wù)之間使用輕量級的網(wǎng)絡(luò)協(xié)議通信,通常是RESTful風(fēng)格的遠(yuǎn)程調(diào)用。由于服務(wù)與服務(wù)的調(diào)用不再是進(jìn)程內(nèi)的調(diào)用,而是通過網(wǎng)絡(luò)進(jìn)行的遠(yuǎn)程調(diào)用,眾所周知,網(wǎng)絡(luò)通信是不穩(wěn)定、不可靠的,一個(gè)服務(wù)依賴的服務(wù)可能出錯、超時(shí)或者宕機(jī),如果沒有及時(shí)發(fā)現(xiàn)和隔離問題,或者在設(shè)計(jì)中沒有考慮如何應(yīng)對這樣的問題,那么很可能在短時(shí)間內(nèi)服務(wù)的線程池中的線程被用滿、資源耗盡,導(dǎo)致出現(xiàn)雪崩效應(yīng)。本節(jié)針對微服務(wù)架構(gòu)中可能遇到的這些問題,講解應(yīng)該采取哪些措施和方案來解決。
1. 艙壁隔離模式
這里用航船的設(shè)計(jì)比喻艙壁隔離模式,若一艘航船遇到了意外事故,其中一個(gè)船艙進(jìn)了水,則我們希望這個(gè)船艙和其他船艙是隔離的,希望其他船艙可以不進(jìn)水,不受影響。在微服務(wù)架構(gòu)中,這主要體現(xiàn)在如下兩個(gè)方面。
1)微服務(wù)容器分組
筆者所在的支付平臺應(yīng)用了微服務(wù),將微服務(wù)的每個(gè)節(jié)點(diǎn)的服務(wù)池分為三組:準(zhǔn)生產(chǎn)環(huán)境、灰度環(huán)境和生產(chǎn)環(huán)境。準(zhǔn)生產(chǎn)環(huán)境供內(nèi)側(cè)使用;灰度環(huán)境會跑一些普通商戶的流量;大部分生產(chǎn)流量和VIP商戶的流量則跑在生產(chǎn)環(huán)境中。這樣,在一次比較大的重構(gòu)過程中,我們就可以充分利用灰度環(huán)境的隔離性進(jìn)行預(yù)驗(yàn)證,用普通商戶的流量驗(yàn)證重構(gòu)沒有問題后,再上生產(chǎn)環(huán)境。
另外一個(gè)案例是一些社交平臺將名人的自媒體流量全部路由到服務(wù)的核心池子中,而將普通用戶的流量路由到另外一個(gè)服務(wù)池子中,有效隔離了普通用戶和重要用戶的負(fù)載。
其服務(wù)分組如圖1-27所示。
?
?
圖1-27?
2)線程池隔離
在微服務(wù)架構(gòu)實(shí)施的過程中,我們不一定將每個(gè)服務(wù)拆分到微小的力度,這取決于職能團(tuán)隊(duì)和財(cái)務(wù)的狀況,我們一般會將同一類功能劃分在一個(gè)微服務(wù)中,盡量避免微服務(wù)過細(xì)而導(dǎo)致成本增加,適可而止。
這樣就會導(dǎo)致多個(gè)功能混合部署在一個(gè)微服務(wù)實(shí)例中,這些微服務(wù)的不同功能通常使用同一個(gè)線程池,導(dǎo)致一個(gè)功能流量增加時(shí)耗盡線程池的線程,而阻塞其他功能的服務(wù)。
線程池隔離如圖1-28所示。
?
圖1-28
2. 熔斷模式
可以用家里的電路保險(xiǎn)開關(guān)來比喻熔斷模式,如果家里的用電量過大,則電路保險(xiǎn)開關(guān)就會自動跳閘,這時(shí)需要人工找到用電量過大的電器來解決問題,然后打開電路保險(xiǎn)開關(guān)。在這個(gè)過程中,電路保險(xiǎn)開關(guān)起到保護(hù)整個(gè)家庭電路系統(tǒng)的作用。
對于微服務(wù)系統(tǒng)也一樣,當(dāng)服務(wù)的輸入負(fù)載迅速增加時(shí),如果沒有有效的措施對負(fù)載進(jìn)行熔斷,則會使服務(wù)迅速被壓垮,服務(wù)被壓垮會導(dǎo)致依賴的服務(wù)都被壓垮,出現(xiàn)雪崩效應(yīng),因此,可通過模擬家庭的電路保險(xiǎn)開關(guān),在微服務(wù)架構(gòu)中實(shí)現(xiàn)熔斷模式。
微服務(wù)化的熔斷模式的狀態(tài)流轉(zhuǎn)如圖1-29所示。
?
?
圖1-29?
3. 限流模式
服務(wù)的容量和性能是有限的,在第3章中會介紹如何在架構(gòu)設(shè)計(jì)過程中評估服務(wù)的最大性能和容量,然而,即使我們在設(shè)計(jì)階段考慮到了性能壓力的問題,并從設(shè)計(jì)和部署上解決了這些問題,但是業(yè)務(wù)量是隨著時(shí)間的推移而增長的,突然上量對于一個(gè)飛速發(fā)展的平臺來說是很常見的事情。
針對服務(wù)突然上量,我們必須有限流機(jī)制,限流機(jī)制一般會控制訪問的并發(fā)量,例如每秒允許處理的并發(fā)用戶數(shù)及查詢量、請求量等。
有如下幾種主流的方法實(shí)現(xiàn)限流。
1)計(jì)數(shù)器
通過原子變量計(jì)算單位時(shí)間內(nèi)的訪問次數(shù),如果超出某個(gè)閾值,則拒絕后續(xù)的請求,等到下一個(gè)單位時(shí)間再重新計(jì)數(shù)。
在計(jì)數(shù)器的實(shí)現(xiàn)方法中通常定義了一個(gè)循環(huán)數(shù)組(見圖1-30),例如:定義5個(gè)元素的環(huán)形數(shù)組,計(jì)數(shù)周期為1s,可以記錄4s內(nèi)的訪問量,其中有1個(gè)元素為當(dāng)前時(shí)間點(diǎn)的標(biāo)志,通常來說每秒程序都會將前面3s的訪問量打印到日志,供統(tǒng)計(jì)分析。
?
圖1-30?
我們將時(shí)間的秒數(shù)除以數(shù)組元素的個(gè)數(shù)5,然后取模,映射到環(huán)形數(shù)組里的數(shù)據(jù)元素,假如當(dāng)前時(shí)間是1 000 000 002s,那么對應(yīng)當(dāng)前時(shí)間的環(huán)形數(shù)組里的第3個(gè)元素,下標(biāo)為2。
此時(shí)的數(shù)組元素的數(shù)據(jù)如圖1-31所示。
?
圖1-31?
在圖1-31中,當(dāng)前時(shí)間為1 000 000 002s,對應(yīng)的計(jì)數(shù)器在第3個(gè)元素,下標(biāo)為2,當(dāng)前請求是在這個(gè)時(shí)間周期內(nèi)的第1個(gè)訪問請求,程序首先需要對后一個(gè)元素即第4個(gè)元素,也就是下標(biāo)為3的元素清零;在1 000 000 002s內(nèi),任何一個(gè)請求如果發(fā)現(xiàn)下標(biāo)為3的元素不為0,則都會將原子變量3清零,并記錄清零的時(shí)間。
這時(shí)程序可以對第3個(gè)元素即下標(biāo)為2的元素,進(jìn)行累加并判斷是否達(dá)到閾值,如果達(dá)到閾值,則拒絕請求,否則請求通過;同時(shí),打印本次及之前3秒的數(shù)據(jù)訪問量,打印結(jié)果如下。
當(dāng)前:1次,前1s:302次,前2s:201次,前3s:518次
然而,如果當(dāng)前秒一直沒有請求量,下一秒的計(jì)數(shù)器始終不能清零,則下一秒的請求到達(dá)后要首先清零再使用,并更新清零時(shí)間。
在下一秒的請求到達(dá)后,若檢查到當(dāng)前秒對應(yīng)的原子變量計(jì)數(shù)器不為0,而且最后的清零時(shí)間不是上一秒,則先對當(dāng)前秒的計(jì)數(shù)器清零,再進(jìn)行累加操作,這避免發(fā)生上一秒無請求的場景,或者上一秒的請求由于線程調(diào)度延遲而沒有清零下一秒的場景,后面這種場景發(fā)生的概率較小。
另外一種實(shí)現(xiàn)計(jì)數(shù)器的簡單方法是單獨(dú)啟動一個(gè)線程,每隔一定的時(shí)間間隔執(zhí)行對下一秒的原子變量計(jì)數(shù)器清零操作,這個(gè)時(shí)間間隔必須小于計(jì)數(shù)時(shí)間間隔。
2)令牌筒
令牌筒是一個(gè)流行的實(shí)現(xiàn)限流的技術(shù)方案,它通過一個(gè)線程在單位時(shí)間內(nèi)生產(chǎn)固定數(shù)量的令牌,然后把令牌放入隊(duì)列,每次請求調(diào)用需要從桶中拿取一個(gè)令牌,拿到令牌后才有資格執(zhí)行請求調(diào)用,否則只能等待拿到令牌再執(zhí)行,或者直接丟棄。
令牌筒的結(jié)構(gòu)如圖1-32所示。
?
?
圖1-32?
3)信號量
限流類似于生活中的漏洞,無論倒入多少油,下面有漏管的流量是有限的,實(shí)際上我們在應(yīng)用層使用的信號量也可以實(shí)現(xiàn)限流。?
使用信號量的示例如下:
4. 失效轉(zhuǎn)移模式
若微服務(wù)架構(gòu)中發(fā)生了熔斷和限流,則該如何處理被拒絕的請求呢?解決這個(gè)問題的模式叫作失效轉(zhuǎn)移模式,通常分為下面幾種。
-
采用快速失敗的策略,直接返回使用方錯誤,讓使用方知道發(fā)生了問題并自行決定后續(xù)處理。
-
是否有備份服務(wù),如果有備份服務(wù),則迅速切換到備份服務(wù)。
-
失敗的服務(wù)有可能是某臺機(jī)器有問題,而不是所有機(jī)器有問題,例如OOM問題,在這種情況下適合使用failover策略,采用重試的方法來解決,但是這種方法要求服務(wù)提供者的服務(wù)實(shí)現(xiàn)了冪等性。
-
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/9276960.html
總結(jié)
- 上一篇: 基于 Spring Cloud 的服务治
- 下一篇: 微服务实践分享(8) 控制调用中心