最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Docker + Nginx 實(shí)現(xiàn) Java 服務(wù)零停機(jī)發(fā)布并解決發(fā)布502問題

 更新時(shí)間:2026年04月28日 09:08:54   投稿:zx  
本文介紹了一種低成本實(shí)現(xiàn)SpringBoot服務(wù)零停機(jī)發(fā)布的方案,通過雙實(shí)例兜底和Nginx自動(dòng)重試機(jī)制解決傳統(tǒng)部署中的502問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

本文為生產(chǎn)環(huán)境真實(shí)踩坑總結(jié),通用適用于:SpringBoot / 單體服務(wù) / Docker Compose + Nginx 架構(gòu),無 Kubernetes 也能實(shí)現(xiàn)低成本高可用發(fā)布。

一、前言

在傳統(tǒng)服務(wù)器部署中,我們更新后端服務(wù)通常是:

  • 停止舊容器
  • 啟動(dòng)新容器

這個(gè)過程會(huì)直接導(dǎo)致:

  • 發(fā)布期間接口 502 Bad Gateway
  • 用戶訪問中斷、前端報(bào)錯(cuò)
  • 監(jiān)控告警、接口超時(shí)失敗

即使使用 “先啟動(dòng)臨時(shí)實(shí)例、再關(guān)閉舊實(shí)例”,如果 Nginx 配置、健康檢查、腳本邏輯 不正確,依然會(huì)出現(xiàn)各種詭異問題:發(fā)布瞬間 502、腳本卡死、接口不通等。
本文帶你從零搭建一套真正可用、無感知、零停機(jī)的發(fā)布方案

二、遇到的典型問題(你大概率也踩過)

直接重啟容器 → 必現(xiàn) 502

nginx 502 Bad Gateway

原因:主容器重啟期間,Nginx 仍在轉(zhuǎn)發(fā)請(qǐng)求,無可用后端服務(wù)。

加了 backup 副本 → 依然偶爾 502

upstream ring_servers {
    server ring:8080;
    server ring_temp:8080 backup;
}

原因:

  • backup 只有主節(jié)點(diǎn)完全掛掉才會(huì)切換
  • Nginx 沒有失敗重試機(jī)制,重啟瞬間仍會(huì)丟請(qǐng)求
  • 健康檢查不及時(shí)

發(fā)布腳本檢查接口 → 直接卡死

curl 檢查接口返回 000,腳本不動(dòng)了

原因:

  • 接口未就緒時(shí),curl 阻塞等待
  • 檢查公網(wǎng)入口受 Nginx 影響,無法真實(shí)判斷服務(wù)狀態(tài)

健康檢查接口被登錄攔截 → 返回 401
原因:健康接口走了登錄校驗(yàn),HTTP 200 但業(yè)務(wù)碼 401,導(dǎo)致腳本誤判。

三、整體零停機(jī)發(fā)布方案(通用架構(gòu))

核心思路:雙實(shí)例兜底 + Nginx 自動(dòng)重試 + 安全發(fā)布腳本

  1. 正常運(yùn)行:主服務(wù)提供流量
  2. 發(fā)布時(shí):先啟動(dòng)臨時(shí)副本 → 等待就緒 → 重啟主服務(wù) → 主服務(wù)就緒 → 關(guān)閉臨時(shí)副本
  3. Nginx:自動(dòng)轉(zhuǎn)發(fā)到可用節(jié)點(diǎn),用戶無感知

四、第一步:Nginx 配置(最關(guān)鍵,解決 502)

  1. upstream 負(fù)載均衡配置
upstream ring_servers {
    least_conn;

    # 主服務(wù)
    server ring:8080 max_fails=1 fail_timeout=1s;
    # 臨時(shí)服務(wù)(發(fā)布兜底,backup 模式)
    server ring_temp:8080 max_fails=3 fail_timeout=30s backup;

    # 核心:出錯(cuò)自動(dòng)重試下一個(gè)節(jié)點(diǎn),用戶看不到 502
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_next_upstream_tries 2;
    keepalive 32;
}
  1. 代理通用配置
proxy_connect_timeout 10s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_buffering on;

說明:proxy_next_upstream 是零停機(jī)的靈魂,請(qǐng)求失敗會(huì)自動(dòng)重試下一個(gè)節(jié)點(diǎn)。

五、第二步:docker-compose.yml 配置

只保留核心結(jié)構(gòu),可直接套用:

version: "3.9"
services:
  # 主服務(wù)
  ring:
    image: ring:1.0.0
    restart: always
    ports:
      - "8080:8080"
    networks:
      - webnet
    healthcheck:
      test: ["CMD", "curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "http://localhost:8080/api/health"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 60s
  # 臨時(shí)服務(wù)(發(fā)布用)
  ring_temp:
    image: ring:1.0.0
    restart: "no"  # 不自動(dòng)重啟
    ports:
      - "8081:8080"
    networks:
      - webnet
networks:
  webnet:
    driver: bridge

六、第三步:生產(chǎn)可用零停機(jī)發(fā)布腳本

重要說明
腳本中使用的接口:

/api/app/checkServerStatus

這只是一個(gè)樣例接口,你可以替換為自己項(xiàng)目中能判斷項(xiàng)目正常運(yùn)行的任意接口,例如:

  • /actuator/health
  • /api/health
  • /system/health

只要該接口能在服務(wù)啟動(dòng)完成后返回 HTTP 200 即可。

零停機(jī)發(fā)布腳本(最終版)

#!/bin/bash
set +e
# ==================== 配置項(xiàng)(根據(jù)自己項(xiàng)目修改) ====================
# 公網(wǎng)要監(jiān)控的接口(驗(yàn)證用戶是否能正常訪問)
MONITOR_URL="https://你的域名/api/app/checkServerStatus"
# 主服務(wù)端口檢查(不經(jīng)過 Nginx)
MAIN_CHECK_URL="http://127.0.0.1:8080/api/app/checkServerStatus"
# 臨時(shí)服務(wù)端口檢查
TEMP_CHECK_URL="http://127.0.0.1:8081/api/app/checkServerStatus"
MAX_RETRY=30
RETRY_INTERVAL=5
# ====================================================================
# 后臺(tái)實(shí)時(shí)監(jiān)控公網(wǎng)接口
start_monitor() {
    while true; do
        current_time=$(date "+%Y-%m-%d %H:%M:%S")
        HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --insecure $MONITOR_URL 2>/dev/null)
        if [ "$HTTP_CODE" = "200" ]; then
            echo -e "\033[32m[${current_time}] ? 公網(wǎng)接口正常:200\033[0m"
        else
            echo -e "\033[31m[${current_time}] ? 公網(wǎng)接口異常:${HTTP_CODE}\033[0m"
        fi
        sleep 1
    done
}
# 檢查端口服務(wù)是否就緒
check_service_ready() {
    local url=$1
    local desc=$2
    echo -e "\033[36m=== 等待 ${desc} 就緒 ===\033[0m"
    local retry=0
    while [ $retry -lt $MAX_RETRY ]; do
        code=$(curl -s -o /dev/null -w "%{http_code}" --insecure $url 2>/dev/null)
        if [ "$code" = "200" ]; then
            echo -e "\033[32m? ${desc} 啟動(dòng)成功\033[0m"
            return 0
        fi
        retry=$((retry+1))
        echo "重試 ${retry}/${MAX_RETRY},狀態(tài)碼:$[code],等待 ${RETRY_INTERVAL}s..."
        sleep $RETRY_INTERVAL
    done
    echo -e "\033[31m? ${desc} 啟動(dòng)超時(shí)\033[0m"
    kill $MONITOR_PID 2>/dev/null
    exit 1
}
# ==================== 發(fā)布主流程 ====================
echo -e "\n==================== 開始零停機(jī)發(fā)布 ====================\n"
# 1. 啟動(dòng)后臺(tái)監(jiān)控
start_monitor &
MONITOR_PID=$!
# 2. 啟動(dòng)臨時(shí)副本
echo -e "\n1. 啟動(dòng)臨時(shí)服務(wù)"
docker compose up -d ring_temp
check_service_ready "$TEMP_CHECK_URL" "臨時(shí)服務(wù)"
# 3. 重啟主服務(wù)
echo -e "\n2. 重啟主服務(wù)"
docker compose up -d --force-recreate ring
check_service_ready "$MAIN_CHECK_URL" "主服務(wù)"
# 4. 關(guān)閉臨時(shí)服務(wù)
echo -e "\n3. 關(guān)閉臨時(shí)服務(wù)"
docker compose stop ring_temp
docker compose rm -f ring_temp
# 5. 停止監(jiān)控
kill $MONITOR_PID 2>/dev/null
sleep 1
echo -e "\n\033[32m=====================================================\033[0m"
echo -e "\033[32m? 發(fā)布完成!全程無 502,用戶無感知\033[0m"
echo -e "\033[32m=====================================================\033[0m"
exit 0

七、第四步:使用與驗(yàn)證

  1. 賦予執(zhí)行權(quán)限
chmod +x deploy_ring.sh
  1. 執(zhí)行發(fā)布
./deploy_ring.sh
  1. 觀察效果
    你會(huì)看到:
    公網(wǎng)接口全程輸出 ? 200
    主服務(wù)重啟期間無任何 502
    發(fā)布完成后自動(dòng)關(guān)閉臨時(shí)副本
    用戶完全無感知

八、核心避坑總結(jié)(非常重要)

  1. 必須先啟動(dòng)臨時(shí)副本,再重啟主服務(wù)
  2. Nginx 必須配置 proxy_next_upstream,這是無 502 的關(guān)鍵
  3. 健康檢查不要檢查公網(wǎng)入口,直接檢查容器端口更穩(wěn)定
  4. 臨時(shí)服務(wù)使用 backup 模式,只做兜底不做負(fù)載,避免啟動(dòng)期間被流量打掛
  5. 健康接口盡量免登錄,只返回 HTTP 200 即可,不要做業(yè)務(wù)校驗(yàn)
  6. 腳本中 /api/app/checkServerStatus只是示例,替換成你自己的健康檢查接口

九、適用場景

  • SpringBoot 后端服務(wù)
  • 單體應(yīng)用 / 無微服務(wù)架構(gòu)
  • Docker Compose 部署
  • 中小企業(yè)服務(wù)器、無 K8s 環(huán)境
  • 追求低成本、穩(wěn)定、無感知發(fā)布

到此這篇關(guān)于Docker + Nginx 實(shí)現(xiàn) Java 服務(wù)零停機(jī)發(fā)布并解決發(fā)布502問題的文章就介紹到這了,更多相關(guān)Docker Nginx Java 服務(wù)零停機(jī)發(fā)布內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解docker中Dockerfile指令創(chuàng)建鏡像

    詳解docker中Dockerfile指令創(chuàng)建鏡像

    這篇文章主要介紹了詳解docker中Dockerfile指令創(chuàng)建鏡像,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • docker制作tomcat鏡像方法及異常處理

    docker制作tomcat鏡像方法及異常處理

    在Docker中創(chuàng)建一個(gè)Tomcat鏡像是一個(gè)常見的需求,尤其是在開發(fā)、測試和部署Java Web應(yīng)用程序時(shí),這篇文章主要介紹了docker制作tomcat鏡像方法及異常處理的相關(guān)資料,需要的朋友可以參考下
    2025-08-08
  • Docker compose 編排工具詳解

    Docker compose 編排工具詳解

    Compose是一個(gè)用于定義和運(yùn)行多容器Docker應(yīng)用程序的工具。使用Compose,您可以使用Compose文件來配置應(yīng)用程序的服務(wù)。然后,使用單個(gè)命令,您可以從配置中創(chuàng)建并啟動(dòng)所有服務(wù)
    2021-09-09
  • Docker下MySQL配置文件不生效的解決方法(超全面!)

    Docker下MySQL配置文件不生效的解決方法(超全面!)

    在Docker中運(yùn)行MySQL并遇到需要調(diào)整配置的情況時(shí),比如想要關(guān)閉ONLY_FULL_GROUP_BY的嚴(yán)格模式,我們可以通過以下步驟來實(shí)現(xiàn)sql_mode的修改:以下是解決此類問題的步驟和思路,需要的朋友可以參考下
    2024-09-09
  • 非docker方式部署openwebui的完整過程記錄

    非docker方式部署openwebui的完整過程記錄

    這篇文章主要介紹了從使用Docker部署OpenWebUI到直接部署的切換過程,包括停止并刪除未使用的Docker鏡像以釋放硬盤空間,并記錄了直接部署的具體步驟,需要的朋友可以參考下
    2025-02-02
  • 解決docker數(shù)據(jù)文件過大導(dǎo)致根磁盤滿的問題

    解決docker數(shù)據(jù)文件過大導(dǎo)致根磁盤滿的問題

    本篇文章主要介紹了解決docker數(shù)據(jù)文件過大導(dǎo)致根磁盤滿的問題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • 云原生Docker容器自定義DNS解析

    云原生Docker容器自定義DNS解析

    Docker沒有為每個(gè)容器專門定制鏡像,那么怎么自定義配置容器的DNS配置呢?這篇文章主要給大家介紹了關(guān)于云原生Docker容器自定義DNS的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Docker 網(wǎng)絡(luò)模式及配置方式

    Docker 網(wǎng)絡(luò)模式及配置方式

    這篇文章主要介紹了Docker 網(wǎng)絡(luò)模式及配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • firewalld防火墻開啟后無法啟動(dòng)docker問題及解決

    firewalld防火墻開啟后無法啟動(dòng)docker問題及解決

    文章描述了在Linux上開啟或重啟防火墻后,創(chuàng)建docker自定義網(wǎng)絡(luò)時(shí)出現(xiàn)的錯(cuò)誤,原因是firewalld和docker在操作iptables時(shí)發(fā)生了沖突,文章提供了兩種解決辦法:1. 重啟Docker服務(wù);2. 讓Docker繞過firewalld
    2025-12-12
  • 使用docker部署java項(xiàng)目運(yùn)行環(huán)境的實(shí)現(xiàn)步驟

    使用docker部署java項(xiàng)目運(yùn)行環(huán)境的實(shí)現(xiàn)步驟

    本文主要介紹了使用docker部署java項(xiàng)目運(yùn)行環(huán)境的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

马公市| 沽源县| 浦县| 彭泽县| 汾西县| 慈利县| 饶河县| 花垣县| 屏东市| 苏尼特右旗| 青龙| 扎鲁特旗| 鹿邑县| 德钦县| 延边| 修水县| 佛山市| 萨嘎县| 特克斯县| 库伦旗| 乌兰浩特市| 库车县| 米泉市| 房产| 科技| 定州市| 嘉义县| 库尔勒市| 西吉县| 北流市| 沈丘县| 绥芬河市| 岳西县| 临猗县| 和田市| 兴义市| 政和县| 广宗县| 昂仁县| 广丰县| 徐州市|