前面我们已经讲解了如何让应用和容器优雅下线以及如何优雅滚动发布,相信大家对“优雅”已经有了一定的认识,这里提供某大型ToC项目的配置实例:
问题现象:在生产环境进行发版、服务滚动更新的这段时间内,如果刚好有用户访问系统会出现报错。针对流量比较大且始终有顾客在使用的商城系统,短暂的出现访问出错也是不可接受的。
问题原因:新的POD拉起,旧的POD销毁,在这个过程中资源会有一定的延迟更新,导致流量可能进入还没准备好的新POD或者进入已经销毁的旧POD,从而出现访问出错。
配置优雅下线
旧的POD销毁这段时间,只要我们控制流量不进入销毁中的POD,就能达到优雅下线的目的:
高版本Spring Boot(Hzero1.7及1.7之后),已经提供了优雅下线的参数,配合K8S的钩子和优雅下线宽限期,可以达到真正的优雅下线,三个关键参数分别为50秒+40秒+30秒。
设置要求:TerminationGracePeriodSeconds>Prestop中Sleep的时间>Spring.lifecycle.timeout-per-shutdown-phas时间
步骤一:设置50秒TerminationGracePeriodSeconds
步骤二:休眠40秒Prestop
利用K8S的钩子,在程序销毁前先睡眠40秒(建议值,具体时间视请求的处理时间而定);在这40秒的时间内Eureka发现检测失败会把这个Pod剔除,不再转发流量到Pod上,同时也有40秒的时间能处理剩余的流量正常返回,从而避免出错的情况。
项目上通过步骤二单一配置,报错率大概降低了98%,针对流量不大的ToB系统基本可以满足了,针对大流量的系统或者ToC的场景,建议把步骤一到步骤三做完(或者在休眠前调用自定义脚本,主动剔除Eureka的注册POD,也能达到目的)
步骤三:设置30秒timeout-per-shutdown-phas
停止设置为优雅停止,时间设置为30秒,可以在Yml文件中配置也可以设置在VM参数中
JAVA_OPTS=-Dserver.shutdown=graceful-Dspring.lifecycle.timeout-per-shutdown-phase=30s
配置优雅滚动发布
新的POD拉起这段时间,只要我们控制流量不进入未完全准备好的POD,就能达到优雅上线的目的,两个配置步骤解决:
步骤一:设置探针
K8S提供了两种检查探针,分别为存活检查和就绪检查,从名字上也能清晰地知道两种探针的作用。
存活检查:让K8S知道应用是否还正常提供服务,如果应用已经挂了,K8S会自动移除该POD并启动一个新的POD替换它;
就绪检查:让K8S知道应用是否已经准备好接收流量,只有就绪检查通过才会把流量转发到POD,否则会停止向POD发送流量,直至检查通过;
探针配置如下:
协议 |
HTTP |
路径 |
Hzero的服务默认都集成了Actuator健康监控,直接配置即可。 Hzero1.7版本及以上,两种探针分别配置: /actuator/health/liveness /actuator/health/readiness
Hzero1.7版本以下的,两种探针都配置:/actuator/health |
端口 |
Yml配置文件的管理端口,Management.server.port |
延迟探测时间 |
120秒 如果服务启动时间长可适当延长 |
执行探测频率 |
10秒 |
超时时间 |
10秒 |
不健康阈值 |
3 |
步骤二:配置服务注册
之所以需要配置服务注册参数,是为了避免这种情况:
当探针延迟120秒POD状态还没变为Running时,Eureka注册中心上的节点已经是UP的状态,如果是以POD IP的形式注册到Eureka上,此时内部Fegin调用的流量有可能会分发到非探测通过的POD上,导致程序出错。
我们的解决整体思路是配置改为Hostname注册值Eureka,Hostname和SVC名称一致,这样就会去请求SVC再负载到POD上,当POD未就绪的时候,就不会参与到SVC的负载上。
-
配置PreferIpAddress
修改Bootstrap.yml,PreferIpAddress: ${EUREKA_INSTANCE_PREFER_IP_ADDRESS:true}修改为PreferIpAddress: ${EUREKA_INSTANCE_PREFER_IP_ADDRESS:false};
或者在环境启动参数EUREKA_INSTANCE_PREFER_IP_ADDRESS设置为False,效果是一样的。
-
配置Hostname
根据服务名称命名,且需要跟后续的SVC名称保持一致,修改Bootstrap.yml,加入以下配置:
eureka:
instance:
hostname: hzero-gateway
或者服务启动指定参数Eureka.instance.hostname=hzero-gateway,效果是一样的。
-
创建SVC
Name: Hzero-gateway,与Bootstrap.yml文件的Hostname需要保持一致,否则会报500
apiVersion: v1
kind: Service
metadata:
labels:
choerodon.io/release: hzero-gateway
name: hzero-gateway
namespace: xxx
spec:
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: service-0
- port: 8081
targetPort: 8081
protocol: TCP
name: service-1
selector:
choerodon.io/release: hzero-gateway
type: ClusterIP
通过上述的两大配置五大步骤,能够达到系统24小时可用,代码发布不影响顾客前端操作体验的效果。
所谓优雅就是平滑切换不报错,核心思路是在新的POD拉起、旧的POD销毁这个过程中,也就是POD还没准备好的时间窗口,不要把流量分发过去。理解了流量会经过哪些组件、组件的缓存策略,要达到优雅这个目的,我们的配置方式可以是多种多样,但万变不离其宗,大家也可以自己尝试新的配置方式。
联系我们
产品试用请登录开放平台。请在 PC 端打开:
https://open.hand-china.com/market-home/trial-center/
产品详情请登录开放平台:
https://open.hand-china.com/document-center/
如有疑问登录开放平台提单反馈:
▲ 更多精彩内容,扫码关注 “四海汉得” 公众号