最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

應(yīng)用在虛機和容器場景下如何優(yōu)雅上下線

2023-06-30 16:01 作者:旅游消費世界  | 我要投稿

一、微服務(wù)應(yīng)用上/下線發(fā)布過程中存在的問題

在應(yīng)用上下線發(fā)布過程中,如何做到流量的無損上/下線,是一個系統(tǒng)能保證SLA的關(guān)鍵。如果應(yīng)用上下線不平滑,就會出現(xiàn)短時間的服務(wù)調(diào)用報錯,比如連接被拒絕、請求超時、沒有實例和請求異常等問題。

1.1上線過程中的問題

在應(yīng)用上線發(fā)布過程中,由于過早暴露服務(wù),實例可能仍處在JVM JIT編譯或者使用的中間件還在加載,若此時大量流量進入,可能會瞬間壓垮新起的服務(wù)實例。我們在實際場景中,曾經(jīng)遇到provider服務(wù)啟動后,但是數(shù)據(jù)庫連接出現(xiàn)異常,未做好啟動前的資源準備,導(dǎo)致該provider服務(wù)在注冊中心暴露后DB異常還未修復(fù),無法正常提供被consumer調(diào)用的能力,導(dǎo)致大量請求異常返回。如下圖日志所示,應(yīng)用初始化時,DB連接失?。ㄔ摲?wù)對DB是弱依賴)。


1.2下線過程中的問題

在應(yīng)用下線過程中,服務(wù)消費者感知服務(wù)提供者下線有延遲,在一段時間內(nèi),被路由到已下線服務(wù)提供者實例的請求都拋連接被拒絕異常。其次服務(wù)實例在接收到SIGKILL信號時,會立即關(guān)閉,但是這時候可能在請求隊列中存在一部分請求還在處理,如果立即關(guān)閉這些請求都會損失掉。實際應(yīng)用中,我們在環(huán)境上部署了provider的唯一一個實例,該服務(wù)被consumer調(diào)用,然后再執(zhí)行kill -9 強殺應(yīng)用provider的唯一實例后,服務(wù)進程實際上已經(jīng)被終止,但是服務(wù)的注冊信息還會在注冊中心(該場景使用的是ServiceComb)保留一段時間,未及時清除,如下圖所示。若此時消費者服務(wù)consumer調(diào)到該實例會報連接拒絕錯誤。因為消費者consumer服務(wù)還能發(fā)現(xiàn)該實例,獲取其IP和端口嘗試去調(diào)用,但是該provider服務(wù)實例其實已經(jīng)被銷毀了。


二、如何處理應(yīng)用上/下線問題

那么有哪些優(yōu)化措施,可以減少應(yīng)用上/下線中流量的損失?

2.1處理應(yīng)用上線問題

應(yīng)用上線發(fā)布主要問題是:其中一個原因是注冊太早,過早的暴露了服務(wù);另一個原因是一些應(yīng)用初始化緩慢,若遇到大量流量,應(yīng)用容易宕機??梢圆扇∫韵聝?yōu)化措施:

1.延遲注冊:微服務(wù)應(yīng)用可以采用延遲注冊的方式,即在應(yīng)用啟動之后一定時間再進行注冊。這樣可以確保應(yīng)用完全就緒后再注冊,避免了服務(wù)未就緒就被外部訪問的情況。

2.健康檢查:微服務(wù)應(yīng)用可以實現(xiàn)健康檢查接口,通過該接口可以檢查服務(wù)是否就緒。注冊中心可以通過定期調(diào)用該接口來判斷服務(wù)是否可以對外提供服務(wù),從而避免了服務(wù)未就緒就被外部訪問的情況。

3.預(yù)熱:對新實例進行預(yù)熱,而不是突然將所有流量轉(zhuǎn)移到新實例上,從而避免新實例遇到大量流量,應(yīng)用容易宕機的情況。

4.啟動優(yōu)化:對于整個服務(wù)啟動的過程,可以進行一些優(yōu)化措施,比如減少不必要的依賴、調(diào)整啟動順序等,從而加快服務(wù)啟動速度。

2.2應(yīng)用合理的上線過程

合理的應(yīng)用上線大致分為這樣一個過程:當應(yīng)用啟動后,通過設(shè)置延遲注冊時間(服務(wù)對外暴露的時間)確保應(yīng)用多久后可提供服務(wù),其次可依賴平臺檢查服務(wù)的就緒狀態(tài)(比如K8S的就緒探針)確保服務(wù)對外提供服務(wù)為就緒狀態(tài),然后通過預(yù)熱對剛啟動應(yīng)用進行保護,確保流量慢慢進入剛啟動的應(yīng)用,最后流量逐漸增到正常情況。


2.3處理應(yīng)用下線問題

應(yīng)用下線過程最主要問題是:消費者應(yīng)用無法及時感知到注冊中心列表的刷新,導(dǎo)致可能還有新流量訪問下線應(yīng)用??梢圆扇∫韵聝?yōu)化措施:

1.減少注冊中心緩存時間:將注冊中心中服務(wù)列表的緩存時間縮短,可以使消費者應(yīng)用更快地獲取到服務(wù)列表的最新信息。這樣可以減少因服務(wù)列表緩存而導(dǎo)致的訪問下線應(yīng)用的流量。

2.實時性優(yōu)化:在服務(wù)消費者和注冊中心之間使用長連接、實時通知等機制,從而能夠?qū)崟r獲取注冊中心中服務(wù)列表的變化。

3.實現(xiàn)熔斷機制:在消費者應(yīng)用中實現(xiàn)熔斷機制,當某個服務(wù)實例出現(xiàn)故障或不可用時,可以快速切換到其他可用的服務(wù)實例。這樣可以避免將流量發(fā)送到已下線的應(yīng)用程序上,并確保消費者應(yīng)用的可用性。

2.4應(yīng)用合理的下線過程

合理的應(yīng)用下線大致分為這樣一個過程:當應(yīng)用接受到外部的關(guān)閉(停止服務(wù))請求后,不能在接收新的業(yè)務(wù)請求,但是會存在一些正在處理的業(yè)務(wù)請求,需等這些請求處理完后再銷毀應(yīng)用使用的資源,最后就可以通知主進程退出。


三、應(yīng)用下線注意點

針對應(yīng)用下線在虛機場景和容器場景需要關(guān)注一些注意點。

3.1虛機場景

當我們要關(guān)閉虛擬機應(yīng)用時,我們一般會使用ps -ef | grep xxx查找到進程ID,然后再執(zhí)行kill -9 PID操作。

kill 命令使用科普:

1.kill -9, 系統(tǒng)會發(fā)出SIGKILL(9)信號,由操作系統(tǒng)內(nèi)核完成殺進程操作,該信號不允許忽略和阻塞,應(yīng)用程序會立即終止(強制殺死)。

2.kill -15,默認使用信號,系統(tǒng)向應(yīng)用發(fā)送SIGTERM(15)信號,給目標進程一個清理善后工作的機會是一種優(yōu)雅終止進程的方式,告訴進程需要停止運行并開始清理資源。

因為kill -9 PID會強制殺死應(yīng)用,以合理的應(yīng)用下線流程看,應(yīng)需處理完相關(guān)舊業(yè)務(wù)請求,清理相關(guān)資源后再退出進程,所以當要關(guān)閉虛擬機應(yīng)用時,請執(zhí)行kill PID——以優(yōu)雅的方式停止運行。

3.2容器場景

Kubernetes目前是業(yè)界容器編排領(lǐng)域的事實標準,業(yè)界一般默認都是用K8S來管理容器。K8S提供了Pod優(yōu)雅退出機制,允許Pod在退出前完成一些清理工作。preStop會先執(zhí)行完,然后K8S才會給Pod發(fā)送TERM信號。在容器場景利用K8S提供的preStop機制,配合延遲下線API使用,這樣就能保證流量的無損下線。

...

spec:

containers:

- name: lifecycle-demo-container

image: nginx

lifecycle:

preStop:

exec:

command: ["/bin/sh","-c","to do xxx; do sleep 30; done"]

...

(1)為什么容器應(yīng)用(K8S環(huán)境)要配置preStop?首先要介紹一下Pod的終止過程。


參考:https://kubernetes.renkeju.com/chapter_4/4.5.5.pod_termination_process.html

1.用戶發(fā)送刪除 Pod 對象的命令。

2.API 服務(wù)器中的 Pod 對象會隨著時間的推移而更新,在寬限期內(nèi)(默認為30秒),Pod被視為“dead”。

3.將 Pod 標記為 “Terminating” 狀態(tài)。

4.(與第3步同時運行)kubelet 在監(jiān)控到 Pod 對象轉(zhuǎn)為 “Terminating” 狀態(tài)的同時啟動 Pod 關(guān)閉程序。

5.(與第3步同時運行)端點控制器監(jiān)控到 Pod 對象的關(guān)閉行為時將其從所有匹配到此端點的 Service 資源的端點列表中移除。

6.Pod 對象中的容器進程收到 TERM 信號。

7.如果當前當前 Pod 對象定義了 preStop 鉤子處理器,則在其標記為 “Terminating” 后即會以同步的方式啟動執(zhí)行;如若寬限期結(jié)束后,preStop 仍未執(zhí)行結(jié)束,則第2步會被重新執(zhí)行并額外獲取一個時長為2秒的小寬限期。

8.寬限期結(jié)束后,若存在任何一個仍在運行的進程,那么 Pod 對象即會收到 SIGKILL 信號。

9.kubelet 請求 API Server 將此 Pod 資源的寬限期設(shè)置為0從而完成刪除操作,它變得對用戶不在可見。

默認情況下,所有刪除操作的寬限期都是30秒,不過,kubectl delete 命令可以使用“--grace-period=”選項自定義其時長,若使用0值則表示直接強制刪除指定的資源,不過,此時需要同時為命令使用 “--force” 選項。

從上述Pod終止過程的時序圖可知,關(guān)閉Pod流程(關(guān)注紅色框),給Pod內(nèi)的進程發(fā)送TERM信號(即kill, kill -15),如果配置了preStop鉤子也會同時處理,最后寬限期結(jié)束后,若存在任何一個仍在運行的進程,那么Pod對象即會收到SIGKILL(kill-9)信號。

(2) 存在這樣一種情況Pod中的業(yè)務(wù)進程接受不到SIGTERM信號

存在這樣一種情況Pod中的業(yè)務(wù)進程接受不到SIGTERM信號(而且沒有配置preStop鉤子),等待一段時間業(yè)務(wù)進程直接被SIGKILL強制殺死了。

為什么業(yè)務(wù)進程接受不到SIGTERM信號?

通常都是因為容器啟動入口使用了 shell,比如使用了類似 /bin/sh -c my-app 或 /docker-entrypoint.sh 這樣的 ENTRYPOINT 或 CMD,這就可能就會導(dǎo)致容器內(nèi)的業(yè)務(wù)進程收不到SIGTERM信號,原因是:

1.容器主進程是shell,業(yè)務(wù)進程是在shell中啟動的,成為了shell進程的子進程。

2.shell 進程默認不會處理 SIGTERM 信號,自己不會退出,也不會將信號傳遞給子進程,導(dǎo)致業(yè)務(wù)進程不會觸發(fā)停止邏輯。

3.當?shù)鹊?K8S 優(yōu)雅停止超時時間 (terminationGracePeriodSeconds,默認30s),發(fā)送SIGKILL強制殺死shell及其子進程。

(3) 如何解決上述Pod中的業(yè)務(wù)進程接收不到SIGTERM信號問題

1.配置preStop鉤子(K8S場景),處理退出前完成一些清理工作,比如使用無損上下線插件的應(yīng)用服務(wù)需在停止前通知實例進行下線。

2.如果可以的話,盡量不使用 shell 啟動業(yè)務(wù)進程。

3.如果一定要通過 shell 啟動,比如在啟動前需要用 shell 進程一些判斷和處理,或者需要啟動多個進程,那么就需要在 shell 中傳遞下 SIGTERM 信號了。

參考:

https://imroc.cc/k8s/faq/why-cannot-receive-sigterm/

所以容器應(yīng)用(K8S環(huán)境)要配置preStop,在停止前通知實例進行下線,加了一層防護,保證Pod中的業(yè)務(wù)能優(yōu)雅的結(jié)束。

四、Sermant如何解決應(yīng)用上/下線問題

針對應(yīng)用上下線發(fā)布過程中的問題,Sermant插件提供預(yù)熱和延遲下線機制,為應(yīng)用提供無損上下線的能力。預(yù)熱是無損上線的核心機制,延遲下線是無損下線的核心機制,而且為了無損上線,還做了延遲注冊機制

4.1上線問題的解決方式


延遲注冊: 若服務(wù)還未完全初始化就已經(jīng)注冊到注冊中心提供給消費者調(diào)用,很有可能因資源為加載完成導(dǎo)致請求報錯。可以通過設(shè)置延遲注冊,讓服務(wù)充分初始化后再注冊到注冊中心對外提供服務(wù)。

預(yù)熱:是基于客戶端實現(xiàn)的,當流量進入時,Sermant會動態(tài)調(diào)整流量,根據(jù)服務(wù)的預(yù)熱配置,對流量進行動態(tài)分配。對于開啟服務(wù)預(yù)熱的實例,在剛啟動時,相對于其他已啟動的實例,分配的流量會更少,流量將以曲線方式隨時間推移增加直至與其他實例近乎持平。目的是采用少流量對服務(wù)實例進行初始化,防止服務(wù)崩潰。

4.2下線問題的解決方式


上圖描述了Sermant是如何解決服務(wù)下線問題的:

0. 微服務(wù)應(yīng)用consumerA、providerA、consumerB、providerB攜帶Sermant啟動,并將相關(guān)ip:port等信息注冊到注冊中心;

1.微服務(wù)應(yīng)用consumerA可以正常調(diào)用providerA和providerB;

2. 若要重啟providerA,providerA會標記自身將下線(通知注冊中心將下線),并開始統(tǒng)計請求確保當前請求已全部處理完成;

3. providerA會通知其上游應(yīng)用其自身的下線信息;

4. consumerA接受到providerA下線信息后,將其從緩存實例列表移除;

5. providerA在處理完當前的所有請求后,即可重啟。

總的來說,Sermant對于服務(wù)下線的機制概括為:

延遲下線:即對下線的實例提供保護,插件基于下線實時通知+刷新緩存的機制快速更新上游的實例緩存,同時基于流量統(tǒng)計的方式,確保即將下線的實例盡可能的將流量處理完成,最大程度避免流量丟失。提供了延遲下線API,方便在K8S環(huán)境中配置preStop。

延遲下線接口為:

http://127.0.0.1:16688/\$\$sermant\$\$/shutdown

流量統(tǒng)計: 為確保當前請求已全部處理完成,在服務(wù)下線時,Sermant會嘗試等待30s(可配置),定時統(tǒng)計和判斷當前實例請求是否均處理完成,處理完成后最終下線。

Sermant優(yōu)雅上下線能力的詳細介紹和使用見:

https://sermant.io/zh/document/plugin/graceful.html

五、總結(jié)

Sermant插件為微服務(wù)應(yīng)用提供無損上下線的能力,若要下線應(yīng)用,針對虛擬場景,請使用kill PID;針對容器場景(K8S環(huán)境),請配置preStop鉤子。

Sermant 作為專注于服務(wù)治理領(lǐng)域的字節(jié)碼增強框架,致力于提供高性能、可擴展、易接入、功能豐富的服務(wù)治理體驗,并會在每個版本中做好性能、功能、體驗的看護。

應(yīng)用在虛機和容器場景下如何優(yōu)雅上下線的評論 (共 條)

分享到微博請遵守國家法律
祁阳县| 乳源| 天门市| 个旧市| 黔西县| 新源县| 新宾| 潼关县| 昌吉市| 泸溪县| 灯塔市| 鹤庆县| 东城区| 台安县| 怀集县| 裕民县| 锡林郭勒盟| 滦平县| 漳浦县| 镇雄县| 永登县| 禹城市| 井冈山市| 大同县| 交城县| 卢氏县| 秦安县| 高邑县| 榆社县| 诸城市| 寿阳县| 商都县| 平泉县| 留坝县| 安宁市| 紫阳县| 叶城县| 麟游县| 江门市| 乌兰浩特市| 金门县|