無損上下線常見問題
本文介紹MSE微服務(wù)治理無損上下線的常見問題。
原先操作面板上的高級(jí)功能去哪了?對(duì)已經(jīng)接入的應(yīng)用有什么影響?我還想開啟或關(guān)閉應(yīng)該怎么操作?
應(yīng)用新接入服務(wù)治理的情況下,無需關(guān)注本問題內(nèi)容。
在舊版的無損上下線控制臺(tái)交互中,提供了高級(jí)功能選項(xiàng)。而高級(jí)功能涉及比較多的微服務(wù)概念,所以新版交互從簡(jiǎn)化使用的角度考慮,在將其進(jìn)行了隱藏。舊版的高級(jí)功能包含兩個(gè)子功能:
通過就緒檢查前完成服務(wù)注冊(cè)。
新版中仍然提供并默認(rèn)開啟,如果您的應(yīng)用原先未開啟,當(dāng)您在控制臺(tái)無損上下線界面重新開啟無損上線后會(huì)自動(dòng)開啟。如果您的應(yīng)用原先已經(jīng)開啟了該功能,我們不推薦您關(guān)閉。該功能在默認(rèn)開啟的情況下,不會(huì)對(duì)應(yīng)用帶來負(fù)面影響。默認(rèn)開啟的情況下,可以規(guī)避發(fā)版時(shí)特定場(chǎng)景下流量跌零的風(fēng)險(xiǎn),具體可以參考為什么配置55199/health。
通過就緒檢查前完成服務(wù)預(yù)熱。
新版不再提供,該功能最初的設(shè)計(jì)目的是用來保證預(yù)熱效果達(dá)到預(yù)期狀態(tài),避免出現(xiàn)開啟預(yù)熱的服務(wù)QPS曲線出現(xiàn)陡升的情況。本質(zhì)上是通過推遲K8s就緒檢測(cè)通過的時(shí)間,來延長(zhǎng)整體的發(fā)版時(shí)間,保障新節(jié)點(diǎn)可以有足夠的時(shí)間進(jìn)行預(yù)熱,并且讓老節(jié)點(diǎn)在這個(gè)過程中繼續(xù)承擔(dān)一部分流量,不會(huì)被快速下掉。這樣就可以保證預(yù)熱的QPS曲線呈現(xiàn)出是一個(gè)緩慢升高的狀態(tài)。如果在發(fā)版過程中,新節(jié)點(diǎn)在預(yù)熱時(shí),老節(jié)點(diǎn)已經(jīng)全部下線,那么新節(jié)點(diǎn)就需要承受所有的線上流量,從而無法實(shí)現(xiàn)“小流量”的預(yù)熱。原先已經(jīng)開啟該功能的應(yīng)用不會(huì)受到影響,但是新應(yīng)用設(shè)置規(guī)則時(shí)無法再對(duì)該功能進(jìn)行開啟,如果您之前開啟了該功能,我們也不推薦您關(guān)閉。該功能在開啟的情況下,不會(huì)對(duì)應(yīng)用帶來負(fù)面影響。在新版交互中,想要服務(wù)小流量預(yù)熱達(dá)到預(yù)期效果,可參見小流量預(yù)熱的最佳實(shí)踐。
小流量預(yù)熱的原理是什么?為什么小流量預(yù)熱需要提供者、消費(fèi)者都接入服務(wù)治理?
當(dāng)消費(fèi)者對(duì)某個(gè)服務(wù)進(jìn)行調(diào)用時(shí),會(huì)對(duì)該服務(wù)的提供者進(jìn)行選擇。在提供者應(yīng)用開啟小流量預(yù)熱的情況下,服務(wù)治理對(duì)這里“選擇提供者”的過程進(jìn)行了增強(qiáng)。在消費(fèi)者選擇提供者時(shí),會(huì)計(jì)算每個(gè)提供者的權(quán)重大小(0%~100%),權(quán)重越大的提供者節(jié)點(diǎn),被選擇和調(diào)用的概率就會(huì)越高。開啟小流量預(yù)熱的提供者在剛啟動(dòng)時(shí),消費(fèi)者對(duì)其計(jì)算的權(quán)重很低,因此預(yù)熱的節(jié)點(diǎn)被調(diào)用的概率也會(huì)變低,隨著時(shí)間增加,這個(gè)權(quán)重計(jì)算結(jié)果會(huì)不斷增大,最終達(dá)到100%,達(dá)到100%時(shí),預(yù)熱流程就結(jié)束了,開始和正常節(jié)點(diǎn)一樣接收流量。提供者會(huì)在服務(wù)注冊(cè)的元數(shù)據(jù)中,帶上自身啟動(dòng)的時(shí)間,以供消費(fèi)者進(jìn)行權(quán)重計(jì)算。這個(gè)過程需要提供者、消費(fèi)者雙方都開啟服務(wù)治理才能實(shí)現(xiàn)。
小流量預(yù)熱的“開始”會(huì)在應(yīng)用收到第一筆請(qǐng)求后觸發(fā),當(dāng)預(yù)熱過程已經(jīng)達(dá)到配置的預(yù)熱時(shí)長(zhǎng)后(默認(rèn)120秒),小流量預(yù)熱結(jié)束。如果應(yīng)用一直沒有收到外部流量,則不會(huì)觸發(fā)預(yù)熱的開始。
小流量預(yù)熱觸發(fā)的前提是有外部流量進(jìn)來,這就要求服務(wù)已經(jīng)完成了注冊(cè)。如果您發(fā)現(xiàn)應(yīng)用還未進(jìn)行服務(wù)注冊(cè),卻已經(jīng)開始了小流量預(yù)熱(即您在控制臺(tái)觀察到預(yù)熱開始事件出現(xiàn)在服務(wù)注冊(cè)事件之前),您可以參考為什么應(yīng)用先出現(xiàn)預(yù)熱事件后出現(xiàn)服務(wù)注冊(cè)事件?來解決。
為什么我的預(yù)熱曲線不符合預(yù)期?該如何解決?
閱讀該問題之前,建議您先了解一下服務(wù)小流量預(yù)熱的原理。
正常情況下小流量預(yù)熱時(shí),應(yīng)用的QPS曲線圖如下:
但是有些時(shí)候由于不合理或不支持的使用場(chǎng)景,進(jìn)行小流量預(yù)熱的應(yīng)用,其QPS曲線圖形狀會(huì)不太符合預(yù)期(緩慢上升),下面是兩種常見的不符合預(yù)期的情況:
QPS 曲線中途出現(xiàn)陡升現(xiàn)象
這種現(xiàn)象一般發(fā)生在服務(wù)發(fā)布的場(chǎng)景,如果在服務(wù)發(fā)布時(shí),新節(jié)點(diǎn)的預(yù)熱還沒有達(dá)到指定時(shí)長(zhǎng),老節(jié)點(diǎn)就被下線了,那么消費(fèi)者端在選擇提供者時(shí),就無法實(shí)現(xiàn)控制新節(jié)點(diǎn)被“低概率”調(diào)用到了。所以會(huì)在 QPS 曲線圖中看到,某個(gè)新節(jié)點(diǎn)的 QPS 曲線在前半段時(shí)緩慢上線的態(tài)勢(shì),達(dá)到某個(gè)時(shí)間節(jié)點(diǎn)后,老節(jié)點(diǎn)被全部下線,QPS 曲線就出現(xiàn)陡升現(xiàn)象了。您可以參考小流量預(yù)熱的最佳實(shí)踐,來解決QPS曲線陡升的問題。
QPS 曲線未呈現(xiàn)緩升趨勢(shì)
出現(xiàn)這種現(xiàn)象,建議檢查對(duì)該應(yīng)用發(fā)起請(qǐng)求的消費(fèi)者應(yīng)用已經(jīng)接入服務(wù)治理,如果消費(fèi)者端沒接入,則考慮將消費(fèi)者應(yīng)用都接入服務(wù)治理,就可以解決該問題。如果您需要預(yù)熱的應(yīng)用,其流量來自外部(比如Java網(wǎng)關(guān)),這種場(chǎng)景下消費(fèi)者是沒有接入服務(wù)治理的,小流量預(yù)熱也無法支持這種場(chǎng)景。
小流量預(yù)熱的最佳實(shí)踐是什么?
在滾動(dòng)發(fā)布的情況下,經(jīng)常會(huì)出現(xiàn)預(yù)熱不充分的問題。您可以參考以下實(shí)踐,來保證服務(wù)預(yù)熱達(dá)到預(yù)期效果:
配置最小準(zhǔn)備時(shí)間(推薦):您可以為工作負(fù)載配置
.spec.minReadySeconds
來控制pod就緒后達(dá)到可用狀態(tài)時(shí)的時(shí)間間隔,并且設(shè)置該參數(shù)的值大于pod的小流量預(yù)熱時(shí)長(zhǎng),以使得K8s等待 pod 預(yù)熱完畢后再繼續(xù)滾動(dòng)發(fā)布。 如果您使用的是ACK,您可以直接在容器平臺(tái)上找到您的應(yīng)用,在 更多 > 升級(jí)策略 > 滾動(dòng)升級(jí) > 最小準(zhǔn)備時(shí)間(minReadySeconds) 中直接設(shè)置。(設(shè)置 minReadySeconds可以在發(fā)布時(shí),讓新啟動(dòng)的pod狀態(tài)達(dá)到ready并維持固定時(shí)長(zhǎng)之后,才會(huì)繼續(xù)發(fā)布)使用分批發(fā)布(推薦):您可以考慮使用OpenKruise等方式,實(shí)現(xiàn)工作負(fù)載的分批發(fā)布,并且控制每個(gè)批次發(fā)布時(shí)的時(shí)間間隔大于小流量預(yù)熱時(shí)長(zhǎng),保證批次內(nèi)的新節(jié)點(diǎn)預(yù)熱充分后,再繼續(xù)發(fā)布一下次批次的節(jié)點(diǎn)。
此外,延長(zhǎng)Readiness就緒檢測(cè)的初始探測(cè)時(shí)間(不推薦),也是一種方式,您可以增加工作負(fù)載Readiness 的首次探測(cè)延遲時(shí)長(zhǎng)(initialDelaySeconds),并且大于小流量預(yù)熱時(shí)長(zhǎng)、延遲注冊(cè)時(shí)長(zhǎng)、應(yīng)用啟動(dòng)時(shí)間三者之和。注意,應(yīng)用啟動(dòng)時(shí)間一般需要觀測(cè)實(shí)際日志輸出來得出,并且隨著業(yè)務(wù)發(fā)展,應(yīng)用的啟動(dòng)時(shí)間也會(huì)隨之變化;此外,延遲 Readiness 通過的時(shí)間,也會(huì)導(dǎo)致新啟動(dòng)的節(jié)點(diǎn)遲遲無法被加入到 K8s Service的Endpoint中,因此我們不推薦您使用這種方式來保證預(yù)熱效果達(dá)到最佳。
如果您按照最佳實(shí)踐進(jìn)行操作后,發(fā)現(xiàn)預(yù)熱QPS曲線仍然不符合預(yù)期,可以考慮應(yīng)用接收的流量,是否都來自于已經(jīng)接入服務(wù)治理的消費(fèi)者應(yīng)用,如果有消費(fèi)者沒有接入服務(wù)治理,或者存在來自于外部負(fù)載均衡的調(diào)用流量,那么應(yīng)用預(yù)熱時(shí)的QPS曲線圖也會(huì)不符合預(yù)期。
55199/health是做什么的?為什么不配置55199/health會(huì)有流量跌0的風(fēng)險(xiǎn)?
55199/health
是MSE微服務(wù)治理提供的一套內(nèi)置的、HTTP類型的就緒檢查端口,當(dāng)應(yīng)用的K8s就緒檢查配置成55199/health
時(shí),在新節(jié)點(diǎn)上線階段,如果該節(jié)點(diǎn)尚未完成服務(wù)注冊(cè),則就緒檢查返回500;如果該節(jié)點(diǎn)已經(jīng)完成服務(wù)注冊(cè),則就緒檢查返回 200。
按照 K8s 默認(rèn)的發(fā)布策略,新節(jié)點(diǎn)沒有就緒,老節(jié)點(diǎn)就不會(huì)下線。當(dāng)就緒檢查配置了55199/health
之后,新節(jié)點(diǎn)完成服務(wù)注冊(cè)之后,才會(huì)進(jìn)入就緒狀態(tài),即只有在新節(jié)點(diǎn)完成服務(wù)注冊(cè)的情況下,老節(jié)點(diǎn)才會(huì)下線。這樣就會(huì)保證注冊(cè)中心上該服務(wù)一直會(huì)有可用的節(jié)點(diǎn)。如果您不配置55199/health
,可能會(huì)在服務(wù)發(fā)布時(shí),新節(jié)點(diǎn)尚未注冊(cè),老節(jié)點(diǎn)就被下線,進(jìn)而導(dǎo)致注冊(cè)中心上該服務(wù)沒有可用節(jié)點(diǎn),進(jìn)而導(dǎo)致該服務(wù)的所有消費(fèi)者在調(diào)用時(shí)因?yàn)闆]有提供者而發(fā)生報(bào)錯(cuò),從而產(chǎn)生該服務(wù)的流量跌0。因此我們強(qiáng)烈建議您開啟無損上線,并為應(yīng)用配置55199/health
就緒檢測(cè)。
為什么應(yīng)用先出現(xiàn)預(yù)熱事件后出現(xiàn)服務(wù)注冊(cè)事件?如何解決?
在當(dāng)前版本下,服務(wù)收到了第一筆外部請(qǐng)求時(shí),就會(huì)開始預(yù)熱流程,并且上報(bào)預(yù)熱開始事件。而有些時(shí)候,應(yīng)用收到的第一筆請(qǐng)求,未必是微服務(wù)調(diào)用請(qǐng)求,因此這種請(qǐng)求也不會(huì)觸發(fā)業(yè)務(wù)邏輯的預(yù)熱。比如應(yīng)用的工作負(fù)載配置了K8s的Liveness探針,在新節(jié)點(diǎn)上線時(shí),即便還沒有進(jìn)行服務(wù)注冊(cè)操作,只要K8s對(duì)Liveness進(jìn)行了探測(cè),就會(huì)判定預(yù)熱已經(jīng)開始。
為了避免這種情況, 您可以在提供者應(yīng)用工作負(fù)載的環(huán)境變量中,配置如下參數(shù),來忽略這些請(qǐng)求對(duì)預(yù)熱邏輯的觸發(fā):
# 忽略路徑為 /xxx、/yyy/zz 的請(qǐng)求對(duì)預(yù)熱流程的觸發(fā)
profile_micro_service_record_warmup_ignored_path="/xxx,/yyy/zz"
該參數(shù)也支持 Jvm 啟動(dòng)參數(shù)的方式進(jìn)行配置。
該參數(shù)的值不支持正則匹配。
主動(dòng)通知是做什么的?什么時(shí)候需要開啟主動(dòng)通知?
主動(dòng)通知是無損下線功能模塊提供的一種進(jìn)階能力,該功能可以在SpringCloud提供者下線時(shí),讓提供者主動(dòng)發(fā)起一次網(wǎng)絡(luò)請(qǐng)求到服務(wù)消費(fèi)者,告知其自身已經(jīng)下線。消費(fèi)者收到通知后,不會(huì)再對(duì)該節(jié)點(diǎn)進(jìn)行調(diào)用。一般情況下,當(dāng)提供者消費(fèi)者都使用SpringCloud框架時(shí),消費(fèi)者本地會(huì)緩存提供者節(jié)點(diǎn)列表。在某些場(chǎng)景下,即便消費(fèi)者收到注冊(cè)中心的通知,也可能沒有及時(shí)刷新本地緩存,進(jìn)而導(dǎo)致消費(fèi)者對(duì)下線的節(jié)點(diǎn)仍然發(fā)起調(diào)用。主動(dòng)通知?jiǎng)t很好地解決了這個(gè)問題。
主動(dòng)通知功能默認(rèn)關(guān)閉,因?yàn)殚_啟服務(wù)治理之后,默認(rèn)的無損下線方案中,下線階段的提供者收到請(qǐng)求時(shí),會(huì)在響應(yīng)中加入一個(gè)特殊的header
,消費(fèi)者收到響應(yīng)時(shí)會(huì)識(shí)別該header
,并且不再調(diào)用該提供者節(jié)點(diǎn)。因此,只要在提供者下線時(shí),消費(fèi)者有流量到達(dá)下線的提供者,就會(huì)感知到該提供者已經(jīng)下線,并且會(huì)自動(dòng)將其“拉黑”。而如果在提供者下線的這段時(shí)間內(nèi)(一般30秒左右),消費(fèi)者沒有請(qǐng)求到達(dá)正在下線的提供者,消費(fèi)者就有可能未感知到該提供者節(jié)點(diǎn)已經(jīng)下線,有可能會(huì)在提供者剛好走完下線流程、即將停機(jī)時(shí),消費(fèi)者請(qǐng)求正好過來,此時(shí)就會(huì)出現(xiàn)請(qǐng)求報(bào)錯(cuò)的問題。這個(gè)時(shí)候,就需要開啟主動(dòng)通知。換句話說,如果消費(fèi)者的流量非常“稀疏”,就建議您為提供者開啟主動(dòng)通知的功能。
為什么已經(jīng)看到無損下線事件后,流量還是沒有快速降為0?
一般情況下,看到無損下線事件后,流量會(huì)在短時(shí)間內(nèi)快速降為0。如果沒有降為0,可能的原因和解決方案如下:
該應(yīng)用收到了非微服務(wù)方式的調(diào)用,比如收到來自外部負(fù)載均衡器的流量,或者存在本地腳本、定時(shí)任務(wù)等調(diào)用方式產(chǎn)生了流量。
目前無損上下線只支持治理內(nèi)部微服務(wù)調(diào)用的流量,上述場(chǎng)景并不在無損上下線功能支持的范圍之內(nèi)。建議您根據(jù)這些基礎(chǔ)設(shè)施、框架提供的優(yōu)雅下線特性來定制相應(yīng)的解決方案。
該應(yīng)用需要開啟主動(dòng)通知,但是沒有開啟。(您可以參考本文了解主動(dòng)通知)
建議您開啟主動(dòng)通知后再次觀測(cè)下線曲線是否符合預(yù)期。
該應(yīng)用使用的框架版本不在支持的范圍之內(nèi),服務(wù)治理無損上下線支持的框架可以參考:微服務(wù)治理支持的Java框架。
如果您發(fā)現(xiàn)應(yīng)用使用的框架版本不在支持版本之中,可以考慮對(duì)應(yīng)用的框架版本進(jìn)行升級(jí)。