亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

對于微服務來說,服務的優雅上下線是必要的。

就上線來說,如果組件或者容器沒有啟動成功,就不應該對外暴露服務,對于下線來說,如果機器已經停機了,就應該保證服務已下線,如此可避免上游流量進入不健康的機器。

優雅下線

基礎下線(Spring/SpringBoot/內置容器)

首先JVM本身是支持通過shutdownHook的方式優雅停機的。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

此方式支持在以下幾種場景下優雅停機:

  1. 程序正常退出
  2. 使用System.exit()
  3. 終端使用Ctrl+C
  4. 使用Kill pid干掉進程

那么如果你偏偏要kill -9 程序肯定是不知所措的。

而在Springboot中,其實已經幫你實現好了一個shutdownHook,支持響應Ctrl+c或者kill -15 TERM信號。

隨便啟動一個應用,然后Ctrl+c一下,觀察日志就可知, 它在 AnnotationConfigEmbeddedWebApplicationContext 這個類中打印出了疑似Closing...的日志,真正的實現邏輯在其父類 AbstractApplicationContext 中(這個其實是spring中的類,意味著什么呢,在spring中就支持了對優雅停機的擴展)。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

我們能對它做些什么呢,其實很明顯,在doClose方法中它發布了一個ContextClosedEvent的方法,不就是給我們擴展用的么。

于是我們可以寫個監聽器監聽ContextClosedEvent,在發生事件的時候做下線邏輯,對微服務來說即是從注冊中心中注銷掉服務。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

可能會有疑問的是,微服務中一般來說,注銷服務往往是優雅下線的第一步,接著才會執行停機操作,那么這個時候流量進來怎么辦呢?

個人會建議是,在注銷服務之后就可開啟請求擋板拒絕流量了,通過微服務框架本身的故障轉移功能去處理被拒絕的流量即可。另外,關注公眾號JAVA技術棧,在后臺回復:面試,可以獲取我整理的 Java、Spring Boot 系列面試題和答案,非常齊全。

Docker中的下線

好有人說了,我用docker部署服務,支不支持優雅下線。

那來看看docker的一些停止命令都會干些啥:

一般來說,正常人可能會用docker stop或者docker kill 命令去關閉容器(當然如果上一步注冊了USR2自定義信息,可能會通過docker exec kill -12去關閉)。

對于docker stop來說,它會發一個SIGTERM(kill -15 term信息)給容器的PID1進程,并且默認會等待10s,再發送一個SIGKILL(kill -9 信息)給PID1。

那么很明顯,docker stop允許程序有個默認10s的反應時間去做一下優雅停機的操作,程序只要能對kill -15 信號做些反應就好了,如上一步描述。那么這是比較良好的方式。

當然如果shutdownHook方法執行了個50s,那肯定不優雅了。可以通過docker stop -t 加上等待時間。

外置容器的shutdown腳本(Jetty)

如果非要用外置容器方式部署(個人認為浪費資源并提升復雜度)。那么能不能優雅停機呢。

可以當然也是可以的,這里有兩種方式:

首先RPC框架本身提供優雅上下線接口,以供調用來結束整個應用的生命周期,并且提供擴展點供開發者自定義服務下線自身的停機邏輯。同時調用該接口的操作會封裝成一個preStop操作固化在jetty或者其他容器的shutdown腳本中,保證在容器停止之前先調用下線接口結束掉整個應用的生命周期。shutdown腳本中執行類發起下線服務 -> 關閉端口 -> 檢查下線服務直至完成 -> 關閉容器的流程。

而更簡單的另一種方法是直接在腳本中加入kill -15命令。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

優雅上線

優雅上線相對來說可能會更加困難一些,因為沒有什么默認的實現方式,但是總之呢,一個原則就是確保端口存在之后才上線服務。

springboot內置容器優雅上線

這個就很簡單了,并且業界在應用層面的優雅上線均是在內置容器的前提下實現的,并且還可以配合一些列健康檢查做文章。Spring Boot 優雅關閉新姿勢,看看這篇。

參看sofa-boot的健康檢查的源碼,它會在程序啟動的時候先對springboot的組件做一些健康檢查,然后再對它自己搞得sofa的一些中間件做健康檢查,整個健康檢查的流程完畢之后(sofaboot 目前是沒法對自身應用層面做健康檢查的,它有寫相關接口,但是寫死了port is ready...)才會暴露服務或者說優雅上線,那么它健康檢查的時機是什么時候呢:

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

可以看到它是監聽了ContextRefreshedEvent這個事件。在內置容器模式中,內置容器模式的start方法是在refreshContext方法中,方法執行完成之后發布一個ContextRefreshedEvent事件,也就是說在監聽到這個事件的時候,內置容器必然是啟動成功了的。

但ContextRefreshedEvent這個事件,在一些特定場景中由于種種原因,ContextRefreshedEvent會被監聽到多次,沒有辦法保證當前是最后一次event,從而正確執行優雅上線邏輯。

在springboot中還有一個更加靠后的事件,叫做ApplicationReadyEvent,它的發布藏在了afterRefresh還要后面的那一句listeners.finished(context, null)中,完完全全可以保證內置容器 端口已經存在了,所以我們可以監聽這個事件去做優雅上線的邏輯,甚至可以把中間件相關的健康檢查集成在這里。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

外置容器(Jetty)優雅上線

目前大多數應用的部署模式不管是jetty部署模式還是docker部署模式(同樣使用jetty鏡像),本質上用的都是外置容器。那么這個情況就比較困難了,至少在應用層面無法觀察到外部容器的運行狀態,并且容器本身沒有提供什么hook給你實現。

那么和優雅上線一樣,需要RPC框架提供優雅上線接口來初始化整個應用的生命周期,并且提供擴展點給開發者供執行自定義的上線邏輯(上報版本探測信息等)。同樣將調用這個接口封裝成一個postStart操作,固化在jetty等外置容器的startup腳本中,保證應用在容器啟動之后在上線。容器執行類似啟動容器 -> 健康檢查 -> 上線服務邏輯 -> 健康上線服務直至完成 的流程。

別再用 kill -9了,這才是微服務上 下線的正確姿勢

 

分享到:
標簽:微服
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定