日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring boot 2.3优雅下线,距离生产还有多远?

發(fā)布時(shí)間:2024/8/23 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring boot 2.3优雅下线,距离生产还有多远? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡介:?對于任何一個(gè)線上應(yīng)用,如何在服務(wù)更新部署過程中保證業(yè)務(wù)無感知是開發(fā)者必須要解決的問題,即從應(yīng)用停止到重啟恢復(fù)服務(wù)這個(gè)階段不能影響正常的業(yè)務(wù)請求,這使得無損下線成為應(yīng)用生命周期中必不可少的一個(gè)環(huán)節(jié)。

前言

在生產(chǎn)環(huán)境中,隨著云原生架構(gòu)的發(fā)展,自動(dòng)的彈性伸縮、滾動(dòng)升級、分批發(fā)布等云原生能力讓用戶享受到了資源、成本、穩(wěn)定性的最優(yōu)解。但是在應(yīng)用的縮容、發(fā)布等過程中,由于實(shí)例下線處理得不夠優(yōu)雅,將會導(dǎo)致短暫的服務(wù)不可用,短時(shí)間內(nèi)業(yè)務(wù)監(jiān)控會出現(xiàn)大量 io 異常報(bào)錯(cuò);如果業(yè)務(wù)沒做好事務(wù),那么還會引起數(shù)據(jù)不一致的問題,那么需要緊急手動(dòng)訂正錯(cuò)誤數(shù)據(jù);甚至每次發(fā)布,您需要發(fā)告示停機(jī)發(fā)布,否則您的用戶會出現(xiàn)一段時(shí)間服務(wù)不可用。沒處理好服務(wù)實(shí)例下線,無論發(fā)生上述哪種情況,都會對您業(yè)務(wù)的連續(xù)性造成困擾。

對于任何一個(gè)線上應(yīng)用,如何在服務(wù)更新部署過程中保證業(yè)務(wù)無感知是開發(fā)者必須要解決的問題,即從應(yīng)用停止到重啟恢復(fù)服務(wù)這個(gè)階段不能影響正常的業(yè)務(wù)請求,這使得無損下線成為應(yīng)用生命周期中必不可少的一個(gè)環(huán)節(jié)。

同時(shí)在多次 Dubbo Meetup 中,平滑上下線一直都是位居微服務(wù)開發(fā)痛點(diǎn)前 Top 3。

下面我們來了解一下 Spring Boot 2.3 中提供的新特性 Graceful Shutdown,來分析一下它對我們生產(chǎn)穩(wěn)定性帶來什么樣的幫助。

Spring Boot graceful shutdown

Graceful shutdown

Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and Servlet-based web applications. When enabled using server.shutdown=graceful, upon shutdown, the web server will no longer permit new requests and will wait for a grace period for active requests to complete. The grace period can be configured using spring.lifecycle.timeout-per-shutdown-phase. Please see the reference documentation for further details.

Spring Boot 2.3.0.RELEASE引入了Graceful Shutdown的功能。其中應(yīng)用在等待下線期間對待新請求的方式,取決于我們所使用的 Server 類型。根據(jù)官方文檔Tomcat、Jetty 和 Reactor Netty將會在網(wǎng)絡(luò)層面停止接收新的請求。Undertow 會繼續(xù)接收新的請求,但立即會以 HTTP 503(服務(wù)不可用)來響應(yīng)。

配置與使用

在Spring Boot 2.3.0中,優(yōu)雅停機(jī)的使用非常簡單,可以通過在應(yīng)用程序配置文件中設(shè)置兩個(gè)屬性來進(jìn)行。
1、 server.shutdown 屬性可以支持的值有兩種

  • immediate 這是默認(rèn)值,配置后服務(wù)器立即關(guān)閉,無優(yōu)雅停機(jī)邏輯。
  • graceful 開啟優(yōu)雅停機(jī)功能,并遵守 spring.lifecycle.timeout-per-shutdown-phase 屬性中給出的超時(shí)來作為服務(wù)端等待的最大時(shí)間。
    2、spring.lifecycle.timeout-per-shutdown-phase 服務(wù)端等待最大超時(shí)時(shí)間,采用java.time.Duration格式的值,默認(rèn)30s。
  • 例如:Properties 文件

    1、#To enable graceful shutdown

    2、server.shutdown=graceful
    3、#To configure the timeout period
    4、spring.lifecycle.timeout-per-shutdown-phase=20s

    當(dāng)我們使用了如上配置開啟了優(yōu)雅停機(jī)功能,當(dāng)我們通過SIGTERM信號關(guān)閉 Spring Boot 應(yīng)用時(shí)
    1、 此時(shí)如果應(yīng)用中沒有正在進(jìn)行的請求,應(yīng)用程序?qū)苯雨P(guān)閉,而無需等待超時(shí)時(shí)間結(jié)束后才關(guān)閉。
    2、此時(shí)如果應(yīng)用中有正在處理的請求,則應(yīng)用程序?qū)⒌却瑫r(shí)時(shí)間結(jié)束后才會關(guān)閉。如果應(yīng)用在超時(shí)時(shí)間之后仍然有未處理完的請求,應(yīng)用程序?qū)伋霎惓2⒗^續(xù)強(qiáng)制關(guān)閉。

    源碼實(shí)現(xiàn)分析

    我們以 Tomcat 為例看一下是SpringBoot 2.3如何實(shí)現(xiàn)graceful shutdown的

    這里注意下,Tomcat 9.0.33或更高版本,才具備graceful shutdown功能。

    我們看一下 SpringBoot 的 TomcatWebServer 的實(shí)現(xiàn),先看其中構(gòu)造函數(shù)

    1、org.springframework.boot.web.embedded.tomcat.TomcatWebServer

    2、public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
    3、 Assert.notNull(tomcat, "Tomcat Server must not be null");
    4、 this.tomcat = tomcat;
    5、 this.autoStart = autoStart;
    6、 this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
    7、 initialize();
    8、}

    可以看到當(dāng)我們配置 server.shutdown=graceful 時(shí),其中 gracefulShutdown 成員就不為null,而是被置為 GracefulShutdown 實(shí)例。
    當(dāng)我們關(guān)閉SpringBoot的應(yīng)用容器時(shí),會觸發(fā)其生命周期的 stop 方法,我們看到其中會執(zhí)行webServer的shutDownGracefully方法

    因?yàn)槲覀兣渲?了server.shutdown=graceful ,所以 gracefulShutdown 成員并不為null,而是會觸發(fā) gracefulShutdown 的 shutDownGracefully 方法

    我們看一下shutDownGracefully 方法是如何做到graceful shutdown的

    來看一下doShutdown的邏輯
    org.springframework.boot.web.embedded.tomcat.GracefulShutdown#doShutdown
    private void doShutdown(GracefulShutdownCallback callback) {

    List<Connector> connectors = getConnectors(); connectors.forEach(this::close); try {for (Container host : this.tomcat.getEngine().findChildren()) {for (Container context : host.findChildren()) {while (isActive(context)) {if (this.aborted) {logger.info("Graceful shutdown aborted with one or more requests still active");callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE);return;}Thread.sleep(50);}}}} catch (InterruptedException ex) {Thread.currentThread().interrupt(); } logger.info("Graceful shutdown complete"); callback.shutdownComplete(GracefulShutdownResult.IDLE);

    }

    先是關(guān)閉掉所有的連接,在網(wǎng)絡(luò)層停止接受請求,然后再等待所有請求處理完畢。
    其中關(guān)于 spring.lifecycle.timeout-per-shutdown-phase 配置,是通過等待配置的時(shí)間后,再執(zhí)行TomcatWebServer的stop方法,將其aborted成員置為true,實(shí)現(xiàn)如果應(yīng)用在寬限期之后仍然有待處理的請求,應(yīng)用程序?qū)伋霎惓2⒗^續(xù)強(qiáng)制關(guān)閉,而不是一直等待下去。
    @Override
    public void stop() throws WebServerException {

    synchronized (this.monitor) {boolean wasStarted = this.started;try {this.started = false;try {if (this.gracefulShutdown != null) {this.gracefulShutdown.abort();}stopTomcat();this.tomcat.destroy();}catch (LifecycleException ex) {// swallow and continue}}catch (Exception ex) {throw new WebServerException("Unable to stop embedded Tomcat", ex);}finally {if (wasStarted) {containerCounter.decrementAndGet();}} }

    }

    void abort() {

    this.aborted = true;

    }

    在微服務(wù)場景下問題似乎依舊存在...
    總結(jié)一下一個(gè) Spring Cloud 應(yīng)用正常分批發(fā)布的流程
    1、服務(wù)發(fā)布前,消費(fèi)者根據(jù)負(fù)載均衡規(guī)則調(diào)用服務(wù)提供者,業(yè)務(wù)正常。
    2、服務(wù)提供者 B 需要發(fā)布新版本,先對其中的一個(gè)節(jié)點(diǎn)進(jìn)行操作,先是正常停止 Java 進(jìn)程。
    3、服務(wù)停止過程中,首先去注冊中心注銷服務(wù),然后等待服務(wù)端線程處理完成,再停止服務(wù)。
    4、注冊中心則將通知消費(fèi)者,其中的一個(gè)服務(wù)提供者節(jié)點(diǎn)已下線。這個(gè)過程包含推送和輪詢兩種方式,推送可以認(rèn)為是準(zhǔn)實(shí)時(shí)的,輪詢的耗時(shí)由服務(wù)消費(fèi)者輪詢間隔決定,最差的情況下需要 1 分鐘。
    5、服務(wù)消費(fèi)者刷新服務(wù)列表,感知到服務(wù)提供者已經(jīng)下線了一個(gè)節(jié)點(diǎn),但是這個(gè)過程中Spring Cloud 的負(fù)載均衡組件 Ribbon 默認(rèn)的刷新時(shí)間是 30 秒 ,最差情況下需要耗時(shí) 30 秒。
    6、服務(wù)消費(fèi)者不再調(diào)用已經(jīng)下線的節(jié)點(diǎn)

    我們看到,當(dāng)一個(gè)Spring Cloud服務(wù)端通過SpringBoot提供的graceful shutdown下線時(shí),它會拒絕客戶端新的請求,并且等待已經(jīng)在處理的線程處理完成后,或者在配置的應(yīng)用最長等待時(shí)間到了之后進(jìn)行下線。

    但是在服務(wù)端重啟開始拒絕客戶端新的請求的時(shí)刻開始,即執(zhí)行了Connectors.stop開始,到客戶端感知到服務(wù)端該實(shí)例下線這段時(shí)間內(nèi),客戶端向該實(shí)例發(fā)起的所有請求都會被拒絕,從而引起服務(wù)調(diào)用異常。


    如果客戶端考慮增加重試能力,這一定程度上可以緩解發(fā)布過程中服務(wù)調(diào)用報(bào)錯(cuò)的問題,但是無法根本上保證下線過程的無損,如果服務(wù)調(diào)用報(bào)錯(cuò)期過程,或者分批發(fā)布時(shí)候同一批次下線的節(jié)點(diǎn)數(shù)過多,無法保證僅僅增加多次重試就能夠調(diào)用到未下線的節(jié)點(diǎn)上。這不能根本解決問題!同時(shí)需要考慮配置重試帶來的業(yè)務(wù)上存在不冪等的風(fēng)險(xiǎn)。

    EDAS 3.0 無損下線

    EDAS 3.0 通過Java Agent技術(shù)無侵入增強(qiáng)您的應(yīng)用,使其具備無損下線能力。
    ? 您無需修改一行代碼與配置,天然具備無侵入特點(diǎn)
    ? 同時(shí)支持 ECS 、K8s 場景
    ? 全面兼容開源,支持開源Dubbo、Spring Cloud 以及開源微服務(wù)網(wǎng)關(guān)

    EDAS的應(yīng)用如何做到無損下線?


    如圖看到,我們通過3個(gè)步驟的增強(qiáng),主動(dòng)注銷、服務(wù)提供者通知下線信息、服務(wù)消費(fèi)者調(diào)用其他服務(wù)提供者。

    可以看到,真正做到無損下線能力是需要客戶端增強(qiáng)一起聯(lián)動(dòng)的

    ? 主動(dòng)注銷
    我們在應(yīng)用服務(wù)下線前,主動(dòng)通知注冊中心注銷該實(shí)例
    ? 通知下線信息
    我們會在服務(wù)端實(shí)例下線前主動(dòng)通知客戶端,該服務(wù)節(jié)點(diǎn)下線的信息
    ? 調(diào)用其他提供者
    我們在客戶端增強(qiáng)其負(fù)載均衡能力,在服務(wù)端下線后,客戶端主動(dòng)調(diào)用其他服務(wù)提供者節(jié)點(diǎn)
    同時(shí)我們提供應(yīng)用等待的邏輯,使要下線的服務(wù)端等待已經(jīng)收到的請求處理完成再關(guān)閉 Spring 容器。

    完整的解決方案

    EDAS 3.0無損下線不僅僅支持 Spring Cloud 與 Dubbo 服務(wù),我們還打通了消息、網(wǎng)關(guān)等微服務(wù)組件,讓您的應(yīng)用在EDAS中做到全鏈路的下線無損。

    EDAS 3.0支持端到端的無損下線

    • 云上客戶存在多種微服務(wù)網(wǎng)關(guān),支持主流開源微服務(wù)網(wǎng)關(guān)(Spring Cloud Gateway、Zuul等)的無損下線
    • 有些用戶的流量是通過 Ingress、SLB、Nginx 等方式打到服務(wù)端的場景
    • MQ消息等異步訂閱關(guān)系的微服務(wù)場景
    • K8s 使用 Service 服務(wù)發(fā)現(xiàn)的微服務(wù)場景
      為了做到全鏈路的無損下線,EDAS 3.0 通過無侵入的方式涵蓋多種場景的完整解決方案,確保您的發(fā)布平滑無損。

    即使面對白天大流量的場景,發(fā)布依舊風(fēng)輕云淡。

    ?

    原文鏈接
    本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

    總結(jié)

    以上是生活随笔為你收集整理的Spring boot 2.3优雅下线,距离生产还有多远?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。