概述
在实际生产环境中,由于 eureka 是 AP,导致每次发布程序时,k8s 的 pod 被终止了,但是 eureka 还认为服务存活(缓存),内部没有将流量拦截,部分请求仍然被分发到终止的容器,导致出现 500 的错误,因此优雅停机显得十分重要。
整个方案的关键在于以下几点:
- 利用 k8s 容器
PreStop
钩子触发容器预结束事件 - curl 方式将 eureka server 中的实例修改为
DOWN
状态 - 根据 eureka 客户端以及 ribbon 的相关设置,等待合适的时间,再结束
定义预结束事件操作
k8s 在容器被终结之前,会发送一个 preStop 事件,它是阻塞的,所以它必须在删除容器的调用发出之前完成。如果钩子在执行期间挂起, pod 会一直保持 running 状态。
参考 k8s 官方的例子 pods/lifecycle-events.yaml
,我们可以根据自己的情况仿照写一下即可:
1 | apiVersion: v1 |
为了简单点,我们在命令中直接执行预先写好的 shell 脚本(也可以将shell脚本做的事情写到这个 yaml 文件里)
1 | ... |
shell 脚本
spring-cloud-with-eureka-graceful-down.sh
脚本执行需要四个入参:
- EUREKA 地址
- 需要停止的服务名
- 服务的实例 ip
- 服务停止缓冲时间
1 | !/bin/sh |