0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

優(yōu)雅停機是什么?SpringBoot+Nacos+k8s實現(xiàn)優(yōu)雅停機

jf_ro2CN3Fa ? 來源:稀土掘金 ? 2024-02-20 10:00 ? 次閱讀

1 概念

優(yōu)雅停機是什么?網(wǎng)上說的優(yōu)雅下線、無損下線,都是一個意思。

優(yōu)雅停機,通常是指在設(shè)備、系統(tǒng)或應(yīng)用程序中止運作前,先執(zhí)行一定的流程或動作,以確保數(shù)據(jù)的安全、預(yù)防錯誤并保證系統(tǒng)的整體穩(wěn)定。

一般來說,優(yōu)雅停機可以參考以下步驟以實現(xiàn):

備份數(shù)據(jù) :立即將內(nèi)存中的所有未保存的修改、緩存等數(shù)據(jù)保存到數(shù)據(jù)庫或磁盤中。

停止接收新的請求

處理未完成的請求

通知其他依賴組件

等待所有要素安全退出后,關(guān)閉系統(tǒng)

在具體實施時,不同的設(shè)備、不同的系統(tǒng)、不同的應(yīng)用,所需要的優(yōu)雅停機步驟也不盡相同,甚至需要根據(jù)不同的場景來選擇不同的方法。

例如,在某些情況下,你可能需要讓用戶知道,系統(tǒng)即將關(guān)閉,并告訴他們應(yīng)當(dāng)保存所有的工作并退出系統(tǒng);而在另一些情況下,你可能需要設(shè)計一種策略,能夠讓系統(tǒng)在無用戶介入的情況下,自動保存所有的狀態(tài),并在下次啟動時恢復(fù)之。

但是,無論在哪種情況下,優(yōu)雅停機的目標都是保護數(shù)據(jù),避免錯誤,并盡量減少到訪用戶或使用者的不便。

上面的步驟,其實還缺了不少基礎(chǔ)的內(nèi)容,比如,停止請求外,還要停止接收定時任務(wù)、停止接收mq消息,等待他們的完成,這2項都是我們微服務(wù)中必不可缺的能力。

因此,我希望通過本文,能夠更清晰,更詳細的講解,在我已知的真實業(yè)務(wù)場景下,如何做優(yōu)雅停機。

文中,很多內(nèi)容不會講得太詳細,需要大家有一定的搜索能力或者經(jīng)驗!

2 用案例說話

隨著微服務(wù)的興起,運維方式由docker -> k8s 變化,優(yōu)雅停機涉及到的點就越來越多!下面,我們用一個案例,說明優(yōu)雅停機中的問題和問題解決方案。

案例前:k8s 停機流程

當(dāng)程序員執(zhí)行 kubectl delete pod 命令時,兩個過程開始:

網(wǎng)絡(luò)規(guī)則即將生效:

Kube-apiserver 收到 pod 刪除請求,并將 pod 的狀態(tài)更新為 Extinating at Etcd;

終結(jié)點控制器從終結(jié)點對象中刪除 Pod 的 IP;

Kuber-proxy 根據(jù) Endpoint 對象的更改更新 iptables 的規(guī)則,并且不再將流量路由到已刪除的 pod。

刪除容器:

Kube-apiserver 收到 pod 刪除請求,并將 pod 的狀態(tài)更新為 Extinating at Etcd;

Kubelet 清理節(jié)點處的容器相關(guān)資源,如存儲、網(wǎng)絡(luò);

添加 Prestop hook 鉤子,等待流量不再發(fā)給pod;

Kubelet 將SIGTERM發(fā)送到容器;

如果容器在默認的 30 秒內(nèi)沒有退出,Kubelet 將發(fā)送 SIGKILL 并強制其退出。

71ee3aec-cf90-11ee-a297-92fbcf53809c.jpg

k8s + springboot + nacos 案例

71f9a83c-cf90-11ee-a297-92fbcf53809c.jpg

PreStopHook 做了2件事情:

nacos反注冊

休眠35秒

通過信號量關(guān)閉springboot程序;

其中,k8s的 terminationGracePeriodSeconds(寬限期)設(shè)置為35s。

問題

springBoot程序關(guān)閉時間只有2s, 那么該程序就無法處理完一些線程任務(wù)、異步消息、定時任務(wù)等。為什么呢?

寬限期設(shè)置了35s,PreStop休眠了35s + 一個請求的時間,超過了寬限期,那么 kubelet 就會給與 pod 增加一次性2s的寬限時間。Pod 的生命周期,2s不管程序是否正常結(jié)束,都會被Kill -9。

為什么反注冊之后需要休眠35s?

這里涉及到nacos服務(wù)發(fā)現(xiàn)原理,nacos服務(wù)變更響應(yīng)時間:實時;ribbon 默認緩存刷新時間30s;因此,一開始是設(shè)置30s的,發(fā)現(xiàn)還有feign請求失敗的情況,所以設(shè)置成了35s以解決這個問題!

nacos服務(wù)變更響應(yīng)時間真的是實時嗎?

其實并不一定,nacos服務(wù)發(fā)現(xiàn)是通過http和udp實現(xiàn)的,udp是實時的,http最大等待時間是10s,但是,udp端口生產(chǎn)環(huán)境可能沒有開放!所以,案例中的nacos服務(wù)發(fā)現(xiàn)僅通過http定時輪詢實現(xiàn)。

案例優(yōu)化

上面的案例可以優(yōu)化的點

nacos 反注冊后休眠35s,是否可以減少;

terminationGracePeriodSeconds 設(shè)置多少合理?

優(yōu)化點1

反注冊后休眠的35s時候受到nacos服務(wù)發(fā)現(xiàn) + ribbon 緩存刷新時間影響,正常應(yīng)該是 服務(wù)發(fā)現(xiàn)時間 + 緩存刷新時間 40s才能在極端情況下保證服務(wù)停機時,不會再有feign 請求進入。

如果想要縮短這個時間

啟用udp,這個需要和運維同學(xué)商量,否則10s等待少不了;

監(jiān)聽nacos服務(wù)變更通知,發(fā)現(xiàn)服務(wù)下線后,及時刷新ribbon緩存;

/**
*訂閱nacos實例變更通知
*手動刷新ribbon服務(wù)實例緩存
*nacosclient1.4.6【1.4.1有重大缺陷,要注意】
*/
@Component
@Slf4j
publicclassNacosInstancesChangeEventListenerextendsSubscriber{

@Resource
privateSpringClientFactoryspringClientFactory;

@PostConstruct
publicvoidregisterToNotifyCenter(){
NotifyCenter.registerSubscriber(this);
}
@Override
publicvoidonEvent(InstancesChangeEventevent){
Stringservice=event.getServiceName();
//service:DEFAULT_GROUP@@demoribbonService:demo
StringribbonService=service.substring(service.indexOf("@@")+2);
log.info("####接收到微服務(wù)nacos實例變更事件:{}ribbonServiceName:{}",event.getServiceName(),ribbonService);
ILoadBalancerloadBalancer=springClientFactory.getLoadBalancer(ribbonService);
if(loadBalancer!=null){
((ZoneAwareLoadBalancer)loadBalancer).updateListOfServers();
log.info("刷新 ribbon 服務(wù)實例:{}緩存成功",ribbonService);
}
}

@Override
publicClasssubscribeType(){
returnInstancesChangeEvent.class;
}


/**
*nacos1.4.4~1.4.6需要加這個方法的實現(xiàn),2.1.2以后版本修復(fù)了該問題
*多注冊中心時,變更事件沒有隔離,因此需要實現(xiàn)該方法來判斷事件是否需要處理
*@seeISSUE#8428-NacosInstancesChangeEventScope
***/
@Override
publicbooleanscopeMatches(InstancesChangeEventevent){
returntrue;
}

}

優(yōu)化點2

terminationGracePeriodSeconds 的值應(yīng)該略大于 PreStop耗時 + springBoot 停機時間,springBoot 停機時間是由程序業(yè)務(wù)決定的(mq消息、定時任務(wù)、線程池任務(wù)、以及備份數(shù)據(jù)),網(wǎng)上的推薦做法是啟用springBoot的優(yōu)雅停機功能,并實現(xiàn)自定義的關(guān)閉邏輯。

springBoot優(yōu)雅停機的默認緩沖時間是30s,因此,terminationGracePeriodSeconds的時間個人建議10 + 30s即可。

經(jīng)過優(yōu)化后

720a365c-cf90-11ee-a297-92fbcf53809c.jpg

使用 actuator shutdown 方案

有些網(wǎng)貼推薦使用 actuator shutdown 進行優(yōu)雅停機,那么看下其流程圖:

7219a97a-cf90-11ee-a297-92fbcf53809c.jpg

其實,真正的情況并非如上圖所示,因為調(diào)用shutdown后,springBoot就會進入優(yōu)雅停機流程,但是這個流程沒有結(jié)束,然后就會被kill -15 中斷,如果線程池沒有做好配置,線程池任務(wù)沒有結(jié)束,服務(wù)就會關(guān)閉。

//沒有設(shè)置下面參數(shù),在kill-15時,線程池沒有執(zhí)行結(jié)束,會被強制關(guān)閉
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setAwaitTerminationSeconds(30);

3 再次優(yōu)化

mq 和 定時任務(wù)

上面的方案中,提到nacos反注冊時,其他服務(wù)監(jiān)聽反注冊事件,進行ribbon緩存刷新,那么,反注冊的服務(wù)(停機服務(wù))自身,是否可以也監(jiān)聽該事件呢?答案是可以的。

停機的服務(wù)監(jiān)聽nacos反注冊事件,判斷是自己反注冊了,表示準備關(guān)機,那么就可以停止對mq消息的監(jiān)聽,停止定時任務(wù),這樣就比在優(yōu)雅停機時,進行mq 和 定時任務(wù)的停止更完美。

724143fe-cf90-11ee-a297-92fbcf53809c.jpg

流量控制

如果沒有使用k8s進行pod節(jié)點的流量控制,那么大概率會使用 springCloud gateway作為服務(wù)網(wǎng)關(guān),因此,gateway 服務(wù)也應(yīng)該監(jiān)聽nacos的反注冊事件,從而及時刷新ribbon的緩存,關(guān)閉停機服務(wù)的流量。

4 小結(jié)

經(jīng)過大量的資料參考、學(xué)習(xí),最終得到的一份自己認為合格的優(yōu)雅停機方案,里面可能有較多的不專業(yè)表述,敬請諒解和指正,謝謝。

在本文的最后,還要說下,優(yōu)雅停機最大的挑戰(zhàn)并不是來源于這個優(yōu)雅停機流程,機械化的流程前人都幫忙躺過了,剩下的是業(yè)務(wù)服務(wù)自身的邏輯:

有沒有包含超過30s的業(yè)務(wù)邏輯,如執(zhí)行超過30s的請求,定時任務(wù)、線程池任務(wù)或mq消息;

服務(wù)關(guān)閉時,如何保存未完成的任務(wù)、數(shù)據(jù),實現(xiàn)自定義的關(guān)閉邏輯;

接口邏輯是否做了冪等;





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 控制器
    +關(guān)注

    關(guān)注

    112

    文章

    16028

    瀏覽量

    176635
  • UDP通信
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    1874
  • nacos
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    188

原文標題:SpringBoot + Nacos + k8s 優(yōu)雅停機

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM8可以設(shè)置類似停機模式下鬧鈴喚醒嗎?

    請問STM8可以設(shè)置類似停機模式下鬧鈴喚醒嗎,比如每天8點鐘從停機模式喚醒
    發(fā)表于 05-08 07:09

    stm8s003停機后,外部中斷有時候會無法退出停機狀態(tài),為什么?

    stm8s003,進入停機,外部中斷退出停機,但是經(jīng)常會觸發(fā)中斷之后卻沒退出停機狀態(tài),再觸發(fā)才行,這是什么問題。我用示波器看過外部中斷的波形,確實有觸發(fā)波形了,但是卻沒有退出
    發(fā)表于 05-11 08:29

    STM8S103K停機模式且關(guān)閉flash時有時候不能喚醒是怎么回事?

    STM8S103K停機模式且關(guān)閉flash 時有時候不能喚醒! 做一個產(chǎn)品,電池供電,有一個電源按鍵用來開關(guān)機,長按2秒就執(zhí)行。用的是PE5外部中斷來喚醒。 假如我設(shè)置:FLASH_CR1
    發(fā)表于 05-17 06:55

    神舟優(yōu)雅U10R上網(wǎng)本 參考價格:2499元

    。精巧散熱設(shè)計 動力強勁更環(huán)保  優(yōu)雅U10R采用先進的英特爾Atom N270處理器,它是目前PC業(yè)界最小的處理器(較一般筆記本電腦CPU縮小60%),采用45納米Hi-k金屬柵極技術(shù)生產(chǎn),僅
    發(fā)表于 07-01 22:30

    熱門低價3G上網(wǎng)本推薦 神舟優(yōu)雅U20Y 參考售價:2399元

    3G是第三代無線通訊技術(shù)的簡稱,這一代技術(shù)包括TD-SCDMA、WCDMA、CDMA2000和WiMax這四種,傳統(tǒng)意義上的3G標準是只前三種,也正是前三種可以真正擺脫線的束縛,實現(xiàn)無線廣域網(wǎng)?,F(xiàn)在
    發(fā)表于 07-02 09:03

    stm32停機

    大家好,請教一個問題:我用stm32f103c8作為主控通過功率驅(qū)動電路來控制一個有刷直流電機,當(dāng)電機速度增大(增大PWM占空比)到一定程度時,stm32就停機了,PWM停止沒有輸出,其他功能也停止
    發(fā)表于 12-19 08:49

    如何優(yōu)雅地完成倒計時定時器自適應(yīng)顯示呢

    如何實現(xiàn)倒計時的基本功能呢?如何優(yōu)雅地完成倒計時定時器自適應(yīng)顯示呢?
    發(fā)表于 10-27 07:15

    利用golang優(yōu)雅實現(xiàn)單實例分享

    1、利用golang優(yōu)雅實現(xiàn)單實例平時編寫代碼過程中,經(jīng)常會遇到對于全局角度只需運行一次的代碼,比如全局初始化操作,設(shè)計模式中的單例模式。針對單例模式,java中又出現(xiàn)了餓漢模式、懶漢模式,再配
    發(fā)表于 10-17 16:46

    怎么判斷STM8是否進入的停機模式?

    怎么判斷STM8是否進入的停機模式
    發(fā)表于 10-09 07:01

    光電控制自動停機

    光電控制自動停機
    發(fā)表于 10-13 11:30 ?409次閱讀

    關(guān)于SpringBoot如何優(yōu)雅的全局異常處理

    SpringBoot全局異常準備說明:如果想直接獲取工程那么可以直接跳到底部,通過鏈接下載工程代碼。 開發(fā)準備 環(huán)境要求JDK:1.8SpringBoot:1.5.17.RELEASE 首先還是
    的頭像 發(fā)表于 05-31 14:25 ?1595次閱讀
    關(guān)于<b class='flag-5'>SpringBoot</b>如何<b class='flag-5'>優(yōu)雅</b>的全局異常處理

    華為云微服務(wù)引擎0停機遷移Nacos?它是這樣做的

    華為云微服務(wù)引擎| 0停機遷移Nacos? “它”是這樣做的 遷移云環(huán)境****場景 ? 微服務(wù)規(guī)模小,使用微服務(wù)引擎CSE成本太高。 ? dubbo/Nacos微服務(wù)架構(gòu)改造
    的頭像 發(fā)表于 12-29 20:01 ?705次閱讀

    K8s+SpringBoot實現(xiàn)零宕機發(fā)布

    K8s + SpringBoot實現(xiàn)零宕機發(fā)布:健康檢查+滾動更新+優(yōu)雅停機+彈性伸縮+Prometheus監(jiān)控+配置分離(鏡像復(fù)用)。
    的頭像 發(fā)表于 01-31 16:31 ?871次閱讀

    冰箱不停機的故障維修

    發(fā)現(xiàn)冰箱不停機故障應(yīng)及時維修,因為冰箱不停機故障很容易造成壓縮機損壞燒毀。
    的頭像 發(fā)表于 02-07 09:44 ?4629次閱讀

    Tokio 模塊的優(yōu)雅停機機制

    在進行高并發(fā)、網(wǎng)絡(luò)編程時,優(yōu)雅停機是一個非常重要的問題。在 Rust 語言中,Tokio 是一個非常流行的異步編程框架,它提供了一些優(yōu)雅停機的機制,本文將圍繞 Tokio 模塊的
    的頭像 發(fā)表于 09-19 15:26 ?536次閱讀