下线先停写再停读:灰度摘流的两段式
【摘要】 下线一个实例时,最省事的做法是直接杀掉容器,或者把权重一下子打到零。流量看起来立刻没了,连接却还握在手里:已经进来的写请求被掐断,读请求又在重试里撞上还没摘干净的旧实例。结果不是平滑,而是一小波 502 和重复写入。更稳的顺序是两段式。第一段只停写。新的变更类请求不再打到这台实例,查询仍可服务。写路径上的在途请求给一个明确的排空窗口,和网关的空闲超时对齐,而不是跟容器的优雅退出时间各算各的。...
下线一个实例时,最省事的做法是直接杀掉容器,或者把权重一下子打到零。流量看起来立刻没了,连接却还握在手里:已经进来的写请求被掐断,读请求又在重试里撞上还没摘干净的旧实例。结果不是平滑,而是一小波 502 和重复写入。
更稳的顺序是两段式。
第一段只停写。新的变更类请求不再打到这台实例,查询仍可服务。写路径上的在途请求给一个明确的排空窗口,和网关的空闲超时对齐,而不是跟容器的优雅退出时间各算各的。这段时间里,就绪探针可以继续通过,但发布系统要把实例标成 draining,避免再被选进新的写连接。
第二段才停读。确认写队列清空、本地事务已经落盘或回滚之后,再把实例从读池拿掉,最后才发终止信号。读请求对一致性没那么敏感,但它们往往占着连接池。如果写还没停就先停读,客户端会把失败的写重试到别的实例,而旧实例上的半成品事务还在。幂等键如果只在入口生成、不传到下游,重试就会变成双写。
落地时有三个容易漏的点。
- 就绪探针和存活探针分开。摘流只该打就绪,不要让存活探针在排空期间把进程重启。
- 网关、注册中心、客户端缓存的 TTL 要对齐。注册中心已经摘掉,客户端本地缓存还拿着旧地址,等于没摘。
- 幂等键跟着请求走完整个写链路,而不是只在网关记一笔。排空窗口里的重试必须能被下游认出来。
灰度回滚也是同一套:先让新版本停止接收写,观察错误率,再决定是把读切回旧版本,还是继续放量。一步把读写都切走,出了问题很难判断是写失败还是读缓存脏。
发布窗口短的时候,两段式看起来多了一次操作。它换来的是可中止:写已经停了,读还可以继续撑到你确认数据没有分叉。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)