最近在折腾 K8S
,当删掉一个 Pod
之后(一个 Pod
上部署了一个微服务实例),Eureka Server
竟然没有将该服务实例标记成 DOWN
,正常来说,当一个 Eureka Client
关闭的时候会发送一个请求给 Eureka Server
,Eureka 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
的进程才能接收到终止信号,而 Docker
的 CMD
命令与 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
后续有问题,还是需要多看文档:
- 官方 Spring Boot Docker : 官方使用的是
ENTRYPOINT
- 官方 Dockerfile reference