K8S(Docker)优雅的关闭 SpringBoot 微服务

最近在折腾 K8S,当删掉一个 Pod 之后(一个 Pod 上部署了一个微服务实例),Eureka Server 竟然没有将该服务实例标记成 DOWN,正常来说,当一个 Eureka Client 关闭的时候会发送一个请求给 Eureka ServerEureka Server 会马上的将服务标记为 DOWN 状态,具体可以看本地开发日志。

o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
com.netflix.discovery.DiscoveryClient    : Shutting down DiscoveryClient ...
com.netflix.discovery.DiscoveryClient    : Unregistering ...
com.netflix.discovery.DiscoveryClient    : DiscoveryClient_ZUUL-SERVICE/192.168.8.14:zuul-service:5555 - deregister  status: 200
com.netflix.discovery.DiscoveryClient    : Completed shut down of DiscoveryClient

其实解决起来并没有很高大上,关键问题是就是 Docker 语法的区别,因为 Docker 容器在 stop 的时候,只有 pid 为 1 的进程才能接收到终止信号,而 DockerCMD 命令与 ENTRYPOINT 命令都有两种类型的执行方式:一种是 exec 也就是带中括号的,另一种是 shell 方式,也就是不带中括号,在使用的过程中只要使用 exec 的就能保证 Java 命令是在 pid 为 1 的进程上执行。

具体解决如下:

CMD 方式:

CMD ["/bin/bash", "-c", "java -jar /webapp/zuul-admin.jar"]

# 如果需要添加参数,可以这样做
ENV COMMON="-Xms128m -Xmx128m"
CMD ["/bin/bash", "-c", "java $COMMOND -jar /webapp/zuul-admin.jar"]

# 反例,错误使用,如果是这样的的话,那么需要在 docker run 的时候通过 -e "COMMON=xxx" 进行传参
CMD ["/bin/bash", "-c", "java", "$COMMOND", "-jar /webapp/zuul-admin.jar"]

# shell 模式,这种模式启动的 pid 不为 1
CMD java -jar /webapp/zuul-admin.jar

# shell 模式带参数,这种模式启动的 pid 不为 1
ENV COMMON="-Xms128m -Xmx128m"
CMD java -jar $COMMON /webapp/zuul-admin.jar

除了使用 CMD 命令外,还可以使用 ENTRYPOINT 命令,使用方法一样:

ENTRYPOINT ["/bin/bash", "-c", "java -jar /webapp/zuul-admin.jar"]

# 如果需要添加参数,可以这样做
ENV COMMON="-Xms128m -Xmx128m"
ENTRYPOINT ["/bin/bash", "-c", "java $COMMOND -jar /webapp/zuul-admin.jar"]

# 反例,错误使用,如果是这样的的话,那么需要在 docker run 的时候通过 -e "COMMON=xxx" 进行传参
ENTRYPOINT ["/bin/bash", "-c", "java", "$COMMOND", "-jar /webapp/zuul-admin.jar"]

# shell 模式,这种模式启动的 pid 不为 1
ENTRYPOINT java -jar /webapp/zuul-admin.jar

# shell 模式带参数,这种模式启动的 pid 不为 1
ENV COMMON="-Xms128m -Xmx128m"
ENTRYPOINT java -jar $COMMON /webapp/zuul-admin.jar

后续有问题,还是需要多看文档:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注