新聞中心
絕?多數(shù)的軟件應(yīng)??產(chǎn)安全事故發(fā)?在應(yīng)?上下線發(fā)布階段,盡管通過(guò)遵守業(yè)界約定俗成的可灰度、可觀測(cè)和可滾回的安全?產(chǎn)三板斧,可以最?限度的規(guī)避發(fā)布過(guò)程中由于應(yīng)??身代碼問(wèn)題對(duì)?戶造成的影響。但對(duì)于?并發(fā)?流量情況下的短時(shí)間流量有損問(wèn)題卻仍然?法解決。因此,本文將圍繞發(fā)布過(guò)程中如何解決流量有損問(wèn)題實(shí)現(xiàn)應(yīng)?發(fā)布過(guò)程中的?損上下線效果相關(guān)內(nèi)容展開(kāi)?案介紹。

創(chuàng)新互聯(lián)建站主要從事成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)鳳翔,10余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢建站服務(wù):13518219792
無(wú)損上下線背景
據(jù)統(tǒng)計(jì),應(yīng)?的事故?多發(fā)?在應(yīng)?上下線過(guò)程中,有時(shí)是應(yīng)?本身代碼問(wèn)題導(dǎo)致。但有時(shí)我們也會(huì)發(fā)現(xiàn)盡管代碼本身沒(méi)有問(wèn)題,但在應(yīng)?上下線發(fā)布過(guò)程中仍然會(huì)出現(xiàn)短時(shí)間的服務(wù)調(diào)?報(bào)錯(cuò),?如調(diào)?時(shí)出現(xiàn)Connection refused和No instance等現(xiàn)象。相關(guān)問(wèn)題的原因有相關(guān)發(fā)布經(jīng)歷的同學(xué)或多或少可能有?定了解,?且?家發(fā)現(xiàn)該類(lèi)問(wèn)題?般在流量?峰時(shí)刻尤為明顯,半夜流量少的時(shí)候就?較少見(jiàn),于是很多?便選擇半夜三更進(jìn)?應(yīng)?發(fā)布希望以此來(lái)規(guī)避線上發(fā)布事故。本節(jié)將就這些問(wèn)題出現(xiàn)的背后真實(shí)原因以及業(yè)界對(duì)應(yīng)的設(shè)計(jì)?案展開(kāi)介紹。常見(jiàn)的流量有損現(xiàn)象出現(xiàn)的原因包括但不限于以下?種:
- 服務(wù)?法及時(shí)下線:服務(wù)消費(fèi)者感知注冊(cè)中?服務(wù)列表存在延時(shí),導(dǎo)致應(yīng)?特定實(shí)例下線后在?段時(shí)間內(nèi)服務(wù)消費(fèi)者仍然調(diào)?已下線實(shí)例造成請(qǐng)求報(bào)錯(cuò)。
- 初始化慢:應(yīng)?剛啟動(dòng)接收線上流量進(jìn)?資源初始化加載,由于流量太?,初始化過(guò)程慢,出現(xiàn)?量請(qǐng)求響應(yīng)超時(shí)、阻塞、資源耗盡從?造成剛啟動(dòng)應(yīng)?宕機(jī)。
- 注冊(cè)太早:服務(wù)存在異步資源加載問(wèn)題,當(dāng)服務(wù)還未初始化完全就被注冊(cè)到注冊(cè)中?,導(dǎo)致調(diào)?時(shí)資源未加載完畢出現(xiàn)請(qǐng)求響應(yīng)慢、調(diào)?超時(shí)報(bào)錯(cuò)等現(xiàn)象。
- 發(fā)布態(tài)與運(yùn)?態(tài)未對(duì)?:使?Kubernetes的滾動(dòng)發(fā)布功能進(jìn)?應(yīng)?發(fā)布,由于Kubernetes的滾動(dòng)發(fā)布?般關(guān)聯(lián)的就緒檢查機(jī)制,是通過(guò)檢查應(yīng)?特定端?是否啟動(dòng)作為應(yīng)?就緒的標(biāo)志來(lái)觸發(fā)下?批次的實(shí)例發(fā)布,但在微服務(wù)應(yīng)?中只有當(dāng)應(yīng)?完成了服務(wù)注冊(cè)才可對(duì)外提供服務(wù)調(diào)?。因此某些情況下會(huì)出現(xiàn)新應(yīng)?還未注冊(cè)到注冊(cè)中?,?應(yīng)?實(shí)例就被下線,導(dǎo)致?服務(wù)可?。
接下來(lái),將就具體的下線和上線過(guò)程中如何避免流量損耗問(wèn)題進(jìn)?分別介紹。
無(wú)損下線
由于微服務(wù)應(yīng)用自身調(diào)用特點(diǎn),在高并發(fā)下,服務(wù)提供端應(yīng)用實(shí)例的直接下線,會(huì)導(dǎo)致服務(wù)消費(fèi)端應(yīng)用實(shí)例無(wú)法實(shí)時(shí)感知下游實(shí)例的實(shí)時(shí)狀態(tài)因而出現(xiàn)繼續(xù)將請(qǐng)求轉(zhuǎn)發(fā)到已下線的實(shí)例從而出現(xiàn)請(qǐng)求報(bào)錯(cuò),流量有損。
圖1 Spring Cloud應(yīng)?消費(fèi)者?法及時(shí)感知提供者服務(wù)下線
例如對(duì)于Spring Cloud應(yīng)?如上圖1所示,當(dāng)應(yīng)?的兩個(gè)實(shí)例A’和A中的A下線時(shí),由于Spring Cloud框架為了在可?性和性能??做平衡,消費(fèi)者默認(rèn)是30s去注冊(cè)中?拉取最新的服務(wù)列表,因此A實(shí)例的下線不能被實(shí)時(shí)感知,流量較?時(shí),消費(fèi)者會(huì)繼續(xù)通過(guò)本地緩存調(diào)?已下線的A實(shí)例導(dǎo)致出現(xiàn)流量有損?;谏鲜霰尘埃瑯I(yè)界提出了相應(yīng)的?損下線(也叫優(yōu)雅下線)的技術(shù)?案來(lái)應(yīng)對(duì)上述問(wèn)題。本節(jié)將對(duì)業(yè)界主流的?些?損下線技術(shù)?案進(jìn)?介紹。
針對(duì)該類(lèi)問(wèn)題,業(yè)界一般的解決方式是通過(guò)將應(yīng)用更新流程劃分為手工摘流量、停應(yīng)用、更新重啟三個(gè)步驟。由人工操作實(shí)現(xiàn)客戶端避免調(diào)用已下線實(shí)例,這種方式簡(jiǎn)單而有效,但是限制較多:不僅需要借助流控能力來(lái)實(shí)現(xiàn)實(shí)時(shí)摘流量,還需要在停應(yīng)用前人工判斷來(lái)保證在途請(qǐng)求已經(jīng)處理完畢。這種需要人工介入的方式運(yùn)維復(fù)雜度較高,只適用于規(guī)模較小的應(yīng)用,無(wú)法解決當(dāng)前云原生架構(gòu)下,自動(dòng)化的彈性伸縮、滾動(dòng)升級(jí)等場(chǎng)景中的實(shí)例下線過(guò)程中的流量有損問(wèn)題。本節(jié)將對(duì)業(yè)界應(yīng)用于云原生場(chǎng)景中的一些無(wú)損下線技術(shù)方案進(jìn)行介紹。
1.主動(dòng)通知
一般注冊(cè)中心都提供了主動(dòng)注銷(xiāo)接口供微服務(wù)應(yīng)用正常關(guān)閉時(shí)調(diào)用,以便下線實(shí)例能及時(shí)更新其在注冊(cè)中心上的狀態(tài)。主動(dòng)注銷(xiāo)在部分基于事件感知注冊(cè)中心服務(wù)列表的微服務(wù)框架比如Dubbo中能及時(shí)讓上游服務(wù)消費(fèi)者感知到提供者下線避免后續(xù)調(diào)用已下線實(shí)例。但對(duì)于像Spring Cloud這類(lèi)微服務(wù)框架服務(wù)消費(fèi)者感知注冊(cè)中心實(shí)例變化是通過(guò)定時(shí)拉取服務(wù)列表的方式實(shí)現(xiàn)。盡管下線實(shí)例通過(guò)注冊(cè)中心主動(dòng)注銷(xiāo)接口更新了其自身在注冊(cè)中心上的應(yīng)用狀態(tài)信息但由于上游消費(fèi)者需要在下一次拉取注冊(cè)中心應(yīng)用列表時(shí)才能感知到,因此會(huì)出現(xiàn)消費(fèi)者感知注冊(cè)中心實(shí)例變化存在延時(shí)。在流量較大、并發(fā)較高的場(chǎng)景中,當(dāng)實(shí)例下線后,仍無(wú)法實(shí)現(xiàn)流量無(wú)損。既然無(wú)法通過(guò)注冊(cè)中心讓存量消費(fèi)者實(shí)例實(shí)時(shí)感知下游服務(wù)提供者的變化情況,業(yè)界提出了利用主動(dòng)通知解決該類(lèi)問(wèn)題。主動(dòng)通知過(guò)程如下圖2所示:
圖2 ?損下線?案
如圖2所示,服務(wù)提供者B中某個(gè)實(shí)例在下線時(shí)為避免主動(dòng)在注冊(cè)中心中注銷(xiāo)的服務(wù)實(shí)例狀態(tài)無(wú)法實(shí)時(shí)被上游消費(fèi)者A感知到,從而導(dǎo)致調(diào)用已下線實(shí)例的問(wèn)題。在接收到下線命令即將下線前,提供者B對(duì)于在等待下線階段內(nèi)收到的請(qǐng)求,在其返回值中都增加上特殊標(biāo)記讓服務(wù)消費(fèi)者接收到返回值并識(shí)別到相關(guān)標(biāo)志后主動(dòng)拉取一次注冊(cè)中心服務(wù)實(shí)例從而實(shí)時(shí)感知B實(shí)例最新?tīng)顟B(tài),從而達(dá)到服務(wù)提供者的下線狀態(tài)能夠被服務(wù)消費(fèi)者實(shí)時(shí)感知。
2.自適應(yīng)等待
在并發(fā)度不?的場(chǎng)景下,主動(dòng)通知?法可以解決絕?部分應(yīng)?下線流量有損問(wèn)題。但對(duì)于?并發(fā)?流量應(yīng)?下線場(chǎng)景,如果主動(dòng)通知完,可能仍然存在?些在途請(qǐng)求需要待下線應(yīng)?處理完才能下線否則這些流量就?法正常被響應(yīng)。為解決該類(lèi)在途請(qǐng)求問(wèn)題,可通過(guò)給待下線應(yīng)?在下線前通過(guò)?適應(yīng)等待機(jī)制在處理完所有在途請(qǐng)求后,再下線以實(shí)現(xiàn)流量?損。
圖3 ?適應(yīng)等待機(jī)制
如上圖3所示,?適應(yīng)等待機(jī)制是通過(guò)待下線應(yīng)?統(tǒng)計(jì)應(yīng)?中是否仍然存在未處理完的在途請(qǐng)求,來(lái)決定應(yīng)?下線的時(shí)機(jī),從?讓待下線應(yīng)?在下線前處理完所有剩余請(qǐng)求。
無(wú)損上線
延遲加載是軟件框架設(shè)計(jì)過(guò)程中最常?的?種策略,例如在Spring Cloud框架中Ribbon組件的拉取服務(wù)列表初始化默認(rèn)都是要等到服務(wù)的第?次調(diào)?時(shí)刻,例如下圖4是Spring Cloud應(yīng)?中第?次和第?次通過(guò)調(diào)?RestTemplate調(diào)?遠(yuǎn)程服務(wù)的耗時(shí)對(duì)比情況:
圖4 應(yīng)?啟動(dòng)資源初始化與正常運(yùn)?過(guò)程中耗時(shí)情況對(duì)?
由圖4結(jié)果可?,第?次調(diào)?由于進(jìn)?了?些資源初始化,耗時(shí)是正常情況的數(shù)倍之多。因此把新應(yīng)?發(fā)布到線上直接處理?流量極易出現(xiàn)?量請(qǐng)求響應(yīng)慢,資源阻塞,應(yīng)?實(shí)例宕機(jī)的現(xiàn)象。
業(yè)界針對(duì)上述應(yīng)??損上線場(chǎng)景提出如下包括延遲注冊(cè)、?流量服務(wù)預(yù)熱以及就緒檢查等?系列解決?案,詳細(xì)完整的?案如下圖5所示:
圖5 ?損上線整體?案
1.延遲注冊(cè)
對(duì)于初始化過(guò)程需要異步加載資源的復(fù)雜應(yīng)?啟動(dòng)過(guò)程,由于注冊(cè)通常與應(yīng)?初始化過(guò)程同步進(jìn)?,從?出現(xiàn)應(yīng)?還未完全初始化就已經(jīng)被注冊(cè)到注冊(cè)中?供外部消費(fèi)者調(diào)?,此時(shí)直接調(diào)?由于資源未加載完成可能會(huì)導(dǎo)致請(qǐng)求報(bào)錯(cuò)。通過(guò)設(shè)置延遲注冊(cè),可讓?xiě)?yīng)?在充分初始化后再注冊(cè)到注冊(cè)中?對(duì)外提供服務(wù)。例如開(kāi)源微服務(wù)治理框架Dubbo原?就提供延遲注冊(cè)功能[1]。
2.小流量服務(wù)預(yù)熱
在線上發(fā)布場(chǎng)景下,很多時(shí)候剛啟動(dòng)的冷系統(tǒng)直接處理?量請(qǐng)求,可能由于系統(tǒng)內(nèi)部資源初始化不徹底從?出現(xiàn)?量請(qǐng)求超時(shí)、阻塞、報(bào)錯(cuò)甚?導(dǎo)致剛發(fā)布應(yīng)?宕機(jī)等線上發(fā)布事故出現(xiàn)。為了避免該類(lèi)問(wèn)題業(yè)界針對(duì)不同框架類(lèi)型以及應(yīng)??身特點(diǎn)設(shè)計(jì)了不同的應(yīng)對(duì)舉措,?如針對(duì)類(lèi)加載慢問(wèn)題有編寫(xiě)腳本促使JVM進(jìn)?預(yù)熱、阿?巴巴集團(tuán)內(nèi)部HSF(High Speed Framework)使?的對(duì)接?分批發(fā)布、延遲注冊(cè)、通過(guò)mock腳本對(duì)應(yīng)?進(jìn)?模擬請(qǐng)求預(yù)熱以及?流量預(yù)熱等。本節(jié)將對(duì)其中適?范圍最?的?流量預(yù)熱?法進(jìn)?介紹。
相?于?般場(chǎng)景下,剛發(fā)布微服務(wù)應(yīng)?實(shí)例跟其他正常實(shí)例?樣?起平攤線上總QPS。?流量預(yù)熱?法通過(guò)在服務(wù)消費(fèi)端根據(jù)各個(gè)服務(wù)提供者實(shí)例的啟動(dòng)時(shí)間計(jì)算權(quán)重,結(jié)合負(fù)載均衡算法控制剛啟動(dòng)應(yīng)?流量隨啟動(dòng)時(shí)間逐漸遞增到正常?平的這樣?個(gè)過(guò)程幫助剛啟動(dòng)運(yùn)?進(jìn)?預(yù)熱,詳細(xì)QPS隨時(shí)間變化曲線如圖6所示:
圖6 應(yīng)??流量預(yù)熱過(guò)程QPS曲線
開(kāi)源Dubbo所實(shí)現(xiàn)的?流量服務(wù)預(yù)熱過(guò)程原理如下圖7所示:
圖7 應(yīng)??流量預(yù)熱過(guò)程原理圖
服務(wù)提供端在向注冊(cè)中?注冊(cè)服務(wù)的過(guò)程中,將?身的預(yù)熱時(shí)? WarmupTime、服務(wù)啟動(dòng)時(shí)間StartTime 通過(guò)元數(shù)據(jù)的形式注冊(cè)到注冊(cè)中?中,服務(wù)消費(fèi)端在注冊(cè)中?訂閱相關(guān)服務(wù)實(shí)例列表,調(diào)?過(guò)程中根據(jù) WarmupTime、StartTime 計(jì)算個(gè)實(shí)例所分批的調(diào)?權(quán)重。剛啟動(dòng)StartTime 距離調(diào)?時(shí)刻差值較?的實(shí)例權(quán)重下,從?實(shí)現(xiàn)對(duì)剛啟動(dòng)應(yīng)?分配更少流量實(shí)現(xiàn)對(duì)其進(jìn)??流量預(yù)熱。 開(kāi)源Dubbo所實(shí)現(xiàn)的?流量服務(wù)預(yù)熱模型計(jì)算如下公式所示:
模型中應(yīng)用QPS對(duì)應(yīng)的 f(x) 隨調(diào)用時(shí)刻 x 線性變化,x表示調(diào)用時(shí)刻的時(shí)間,startTime是應(yīng)用開(kāi)始時(shí)間,warmupTime是用戶配置的應(yīng)用預(yù)熱時(shí)長(zhǎng),k是常數(shù),一般表示各實(shí)例的默認(rèn)權(quán)重。
圖8 應(yīng)??流量預(yù)熱權(quán)重計(jì)算 通過(guò)?流量預(yù)熱?法,可以有效解決,?并發(fā)?流量下,資源初始化慢所導(dǎo)致的?量請(qǐng)求響應(yīng) 慢、請(qǐng)求阻塞,資源耗盡導(dǎo)致的剛啟動(dòng)應(yīng)?宕機(jī)事故。
3.微服務(wù)就緒檢查
在介紹微服務(wù)就緒檢查之間,先簡(jiǎn)單介紹?下相關(guān)的Kubernetes探針技術(shù)作為技術(shù)背景,以便更好的理解后?內(nèi)容:
Kubernetes探針技術(shù)
在云原?領(lǐng)域,Kubernetes為了確保應(yīng)? Pod 在對(duì)外提供服務(wù)之前應(yīng)?已經(jīng)完全啟動(dòng)就緒或者應(yīng)?Pod?時(shí)間運(yùn)?期間出現(xiàn)意外后能及時(shí)恢復(fù),提供了探針技術(shù)來(lái)動(dòng)態(tài)檢測(cè)應(yīng)?的運(yùn)?情況,為保證應(yīng)?的?損上線和?時(shí)間健康運(yùn)?提供了保障。
存活探針
Kubernetes 中提供的存活探測(cè)器來(lái)探測(cè)什么時(shí)候進(jìn)?容器重啟。例如,存活探測(cè)器可以捕捉到死鎖(應(yīng)?程序在運(yùn)?,但是?法繼續(xù)執(zhí)?后?的步驟)。在這樣的情況下重啟容器有助于讓?xiě)?yīng)?程序在有問(wèn)題的情況下更可?。
就緒探針
Kubernetes 中提供的就緒探測(cè)器可以知道容器什么時(shí)候準(zhǔn)備好了并可以開(kāi)始接受請(qǐng)求流量,當(dāng)?個(gè) Pod 內(nèi)的所有容器都準(zhǔn)備好了,才能把這個(gè) Pod 看作就緒了。這種信號(hào)的?個(gè)?途就是控制哪個(gè) Pod 作為 Service 的后端。在Pod 還沒(méi)有準(zhǔn)備好的時(shí)候,會(huì)從 Service 的負(fù)載均衡器中被剔除的。 啟動(dòng)探針 Kubernetes 中提供的啟動(dòng)探測(cè)器可以知道應(yīng)?程序容器什么時(shí)候啟動(dòng)了。如果配置了這類(lèi)探測(cè)器,就可以控制容器在啟動(dòng)成功后再進(jìn)?存活性和就緒檢查,確保這些存活、就緒探測(cè)器不會(huì)影響應(yīng)?程序的啟動(dòng)。這可以?于對(duì)慢啟動(dòng)容器進(jìn)?存活性檢測(cè),避免它們?cè)趩?dòng)運(yùn)?之前就被殺掉。
探針使??結(jié)
- 當(dāng)需要在容器已經(jīng)啟動(dòng)后再執(zhí)?存活探針或者就緒探針檢查,則可通過(guò)設(shè)定啟動(dòng)探針實(shí)現(xiàn)。
- 當(dāng)容器應(yīng)?在遇到異?;虿唤】档那闆r下會(huì)??崩潰,則不?定需要存活探針,Kubernetes 能根據(jù) Pod 的 restartPolicy 策略?動(dòng)執(zhí)?預(yù)設(shè)的操作。
- 當(dāng)容器在探測(cè)失敗時(shí)被Kill并重新啟動(dòng),則可通過(guò)指定?個(gè)存活探針,并指定restartPolicy 為Always 或 OnFailure。
- 當(dāng)希望容器僅在探測(cè)成功時(shí) Pod 才開(kāi)始接收外部請(qǐng)求流量,則可使?就緒探針。
更多Kubernetes探針技術(shù)使用示例參考[2]。
當(dāng)前容器+Kubernetes的應(yīng)?運(yùn)維部署?式已經(jīng)成為了業(yè)界的事實(shí)標(biāo)準(zhǔn),相關(guān)技術(shù)為微服務(wù)應(yīng)?運(yùn)維部署帶來(lái)巨?便利的同時(shí),在某些特殊的應(yīng)?部署場(chǎng)景中也有?些問(wèn)題需要解決。?如,使?Kubernetes的滾動(dòng)發(fā)布功能進(jìn)?應(yīng)?發(fā)布,由于Kubernetes的滾動(dòng)發(fā)布?般關(guān)聯(lián)的就緒檢查機(jī)制,是通過(guò)檢查應(yīng)?特定端?是否啟動(dòng)作為應(yīng)?就緒的標(biāo)志來(lái)觸發(fā)下?批次的實(shí)例發(fā)布,但在微服務(wù)應(yīng)?中只有當(dāng)應(yīng)?完成了服務(wù)注冊(cè)才可對(duì)外提供服務(wù)調(diào)?。因此某些情況下會(huì)出現(xiàn)新應(yīng)?還未注冊(cè)到注冊(cè)中?,?應(yīng)?實(shí)例就被設(shè)置下線,導(dǎo)致?服務(wù)可?。
針對(duì)這樣?類(lèi)微服務(wù)應(yīng)?的發(fā)布態(tài)與應(yīng)?運(yùn)?態(tài)?法對(duì)?的問(wèn)題導(dǎo)致的應(yīng)?上線事故,當(dāng)前業(yè)界也已經(jīng)有相關(guān)解決?案進(jìn)?應(yīng)對(duì)。?如可以通過(guò)就緒檢查關(guān)聯(lián)服務(wù)注冊(cè)的?法,通過(guò)字節(jié)碼技術(shù)植?應(yīng)?服務(wù)注冊(cè)邏輯前后,然后在應(yīng)?中開(kāi)啟?個(gè)探測(cè)應(yīng)?服務(wù)是否完成注冊(cè)的端?供Kubernetes的就緒探針進(jìn)?應(yīng)?就緒態(tài)探測(cè)進(jìn)?綁定?戶的發(fā)布態(tài)與運(yùn)?態(tài)實(shí)現(xiàn)微服務(wù)的就緒檢查,避免出現(xiàn)相關(guān)狀態(tài)不?致導(dǎo)致的應(yīng)?發(fā)布上線流量有損問(wèn)題。
參考資料
[1] Dubbo延遲注冊(cè):https://dubbo.apache.org/zh/docs/advanced/delay-publish/
[2]Kubernetes探針技術(shù)使?實(shí)例:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
名稱(chēng)欄目:解決微服務(wù)架構(gòu)下流量有損問(wèn)題的實(shí)踐和探索
文章地址:http://www.fisionsoft.com.cn/article/cdghced.html


咨詢
建站咨詢
