服务器滚动更新配置:从零实现不停机发布
滚动更新的核心思路是:不一次性停掉所有服务,而是分批替换实例,每批替换后确认新实例正常,再处理下一批。
这样用户请求始终有可用后端承接,达到不停机发布的效果。
下面按准备、Nginx 手动滚动、Docker Compose 自动滚动、避坑与验证的顺序展开。
开始前需要确认的三件事
1. 服务必须是无状态的
如果应用把用户会话写在本地磁盘或内存里,滚动更新会导致部分用户登录态丢失。解决办法是把 session 存到 Redis 或数据库,或者用 JWT 等无状态令牌。
2. 至少两个后端实例
只有一个实例时无法滚动,必须先扩容到 2 个以上。本文假设后端为 10.0.0.11:8080 和 10.0.0.12:8080 两台。
3. 准备好健康检查接口
应用需要提供一个返回 HTTP 200 的路径,例如 /health,用于判断新实例是否真正可用。没有健康检查的滚动更新等于盲发。
用 Nginx 手动控制流量切换
Nginx 本身不做滚动,但可以通过临时摘除 upstream 节点来实现分批发布。
在 nginx.conf 中配置 upstream:
upstream backend {
server 10.0.0.11:8080 max_fails=2 fail_timeout=10s;
server 10.0.0.12:8080 max_fails=2 fail_timeout=10s;
}
发布第一批时,编辑配置将 10.0.0.11 注释掉,只保留 10.0.0.12,然后执行:
nginx -t && nginx -s reload
nginx -t 先检查语法,避免配置写错导致 reload 失败。
reload 后 Nginx 会平滑关闭旧 worker,已有连接不会立刻断开。
此时 10.0.0.11 不再接收新请求,可以安全停服、更新代码、重启。
新实例起来后,用 curl http://10.0.0.11:8080/health 确认返回 200,再把该节点加回 upstream 并 reload。
接着用同样方式处理 10.0.0.12。
关键点:每次只动一个节点,动完必须验证健康接口,再动下一个。
Docker Compose 的滚动更新参数
如果用 Docker Compose 管理服务,可以在 docker-compose.yml 中声明更新策略:
services:
app:
image: myapp:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
failure_action: rollback
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 3s
retries: 3
parallelism: 1表示每次只更新一个容器delay: 10s是两批之间的等待时间order: start-first先启动新容器再停旧容器,避免容量下降failure_action: rollback健康检查失败时自动回滚
执行更新:
docker compose up -d --no-deps app
Docker 会按策略逐个替换容器。
用 docker compose ps 观察状态,全部变为 healthy 即完成。
注意:deploy 字段在普通 docker compose up 下部分参数可能不生效,
正式环境建议用 docker stack deploy 或 Docker Swarm 模式,
参数支持更完整。
避坑清单
- 健康检查写得太浅:只检查端口通不代表业务可用,最好检查数据库连接和关键依赖。
- 没设
max_fails:Nginx 默认会继续往故障节点转发,导致部分请求 502。 - 忘记 reload 就停服:先摘流量再停服,顺序反了会出现短暂不可用。
- 数据库迁移与代码发布同时进行:先做兼容性迁移(加字段、加表),再发新代码,避免旧代码读到新结构报错。
- 回滚没准备:更新前记录旧镜像 tag 或代码 commit,出问题能快速切回。
怎么确认滚动更新真的生效
发布过程中在另一台机器持续请求服务:
while true; do curl -s -o /dev/null -w "%{http_code}\n" http://your-domain/; sleep 0.5; done
如果全程只看到 200,没有 502 或超时,说明流量切换正常。
发布结束后检查所有实例日志,确认新版本已生效,并观察 5 到 10 分钟的错误率和响应时间,无异常才算完成。
滚动更新不复杂,难在顺序和验证。
先摘流量、再更新、后验证、最后恢复,这个节奏适用于 Nginx、Docker 以及大多数负载均衡场景。