Docker Swarm更新时短时间连接被拒绝,如何让SpringBoot完全启动后再标记任务为运行状态
解决方案
核心是给Docker服务配置健康检查(Healthcheck),Docker Swarm默认仅判断容器进程是否启动就标记为running,配置健康检查后,Swarm会等待检查完全通过才会将任务标记为健康状态,此时负载均衡才会向该节点转发流量,具体配置步骤如下:
步骤1:SpringBoot项目开启就绪检查端点
推荐使用SpringBoot官方的actuator组件提供的就绪检查接口,它可以准确判断应用上下文、依赖服务、数据库连接等是否完全初始化完成:
- 引入actuator依赖(Maven示例):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
- 配置文件开启就绪端点暴露(application.yml示例):
management: endpoints: web: exposure: include: health endpoint: health: show-details: never health: livenessstate: enabled: true readinessstate: enabled: true
配置完成后,SpringBoot完全启动就绪时,访问http://localhost:8080/actuator/health/readiness会返回200状态码,启动过程中返回503状态码。
步骤2:配置健康检查规则
有两种配置方式,选其中一种即可:
方式一:直接修改Dockerfile添加健康检查
修改后的Dockerfile如下:
FROM openjdk:11 COPY target/*.jar app.jar EXPOSE 8080 # 基础镜像默认无curl,先安装依赖 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* # 健康检查配置 HEALTHCHECK --interval=5s --timeout=3s --retries=3 --start-period=30s \ CMD curl -f http://localhost:8080/actuator/health/readiness || exit 1 ENTRYPOINT ["java","-jar","/app.jar"]
参数说明:
--start-period:给应用预留的启动缓冲时间,这段时间内检查失败不会计入失败重试次数,可根据自身项目启动时长调整,建议预留10s以上余量--interval:两次健康检查的间隔时长--timeout:单次健康检查的超时阈值,超时即判定为本次检查失败--retries:连续失败多少次后将容器标记为不健康状态
方式二:在Swarm部署文件中配置(无需重新构建镜像)
如果不想修改Dockerfile,可以直接在stack部署的docker-compose.yml中给对应服务添加健康检查配置:
version: '3.8' services: your-springboot-service: image: 你的镜像地址 ports: - "8080:8080" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health/readiness"] interval: 5s timeout: 3s retries: 3 start_period: 30s deploy: mode: replicated replicas: 3 # 滚动更新配置,确保新实例健康后再销毁旧实例 update_config: parallelism: 1 order: start-first failure_action: rollback delay: 10s
可选轻量方案:端口检查(无需引入actuator)
如果不想引入actuator组件,也可以直接检查8080端口是否处于监听状态,将健康检查命令替换为以下内容即可,缺点是无法判断应用内部依赖是否初始化完成,精度较低:
CMD nc -z localhost 8080 || exit 1
内容的提问来源于stack exchange,提问作者Changlei Xiao
相关产品推荐
相关产品推荐

