【云原生 | Kubernetes 系列】—SpringCloud - Nacos 结合 K8s 服务优雅上下线
版权 本文为云篆录原创文章,转载无需和我联系,但请注明来自云篆录 http://www.yunzhuan.site
🍇 问题描述
在生产环境中使用springbootforalibaba框架,在服务升级的过程中,pod会被直接停止,在高并发的情况下
部分请求被分发到终止的容器,服务出现500的情况,所以考虑使用优雅停止服务,和平滑上线,将错误率减少到最低。
🍋 解决思路
- 在pod关闭之前,新的请求不能够进来。因为nacos健康检查默认是5s,假如现在服务已经完全关闭了,而nacos还没有感知到, 依旧将新的请求调度到完全关闭的节点,那么请求就会500。因此,我们可以利用k8s的生命周期特性(preStop 钩子函数)在服务 关闭之前我们将服务的权重修改为0,这样新的请求就不会打到即将关闭的服务了。
- 在nacos服务权重为0后,因为nacos默认更新时间为30S,每个服务里面都会缓存一份naocs服务缓存表,这个时候我们还是不能关闭 服务,让程序继续跑,是为了处理旧的请求,以及有足够的时间返回请求,因此我们在preStop钩子函数里面sleep 45S(注意这个时间要大于30S) 留足够的时间处理。
🥭解决方案
- 获取podip,因为nacos提供的接口需要服务的podip,因此我们需要在容器里面获取podip
env:
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- 修改k8s Deploy,增加preStop钩子函数,所需要的参数
- nacos地址 http://127.0.0.1:8848
- serviceName,服务名称 applicationName
- clusterName 集群名称
- groupName 组名称
- ip pod的ip
- port 服务端口
- namespaceId nacos命名空间
lifecycle:
preStop:
exec:
command:
- bash
- "-c"
- 'curl -X "POST" "http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=applicationName&clusterName=DEFAULT&groupName=DEFAULT_GROUP&ip=$POD_IP&port=8080&ephemeral=true&weight=0&enabled=false&namespaceId=nacosNamespace" -H "Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8";sleep 45'
- 修改terminationGracePeriodSeconds,K8s 关闭机制里还有一个重要参数 terminationGracePeriodSeconds(默认 30s)K8s 在执行关闭过程中,因为上面有一些命令需要执行,难免会出现一些意外,导致程序一直卡死在那边,所以 K8s 有一个补偿机制,就是如果关闭流程消耗的时间大于这个参数时间时,马上 K8s 强制关闭,所以这个时间必须大于 sleep 的时间
spec:
terminationGracePeriodSeconds: 60
🥭验证效果
当我们停止一个服务的时候,看是否下线服务
- 停止前
- 停止中 此时服务已经下线
- 完全关闭,并重新生成新的服务
版权 本文为云篆录原创文章,转载无需和我联系,但请注明来自云篆录 http://www.yunzhuan.site
评论区