百万 TPS 服务发布无感知!详解轻量消息队列无损发布实践
作者:辛八
前言
阿里云轻量消息队列(原 MNS)【1】是一款易集成、高并发、弹性可扩展的消息队列服务,助力开发者在分布式组件间高效传递数据,构建松耦合架构。它凭借轻量化架构、高可靠性及动态弹性优势,在业务异步处理、AI 场景(如 LLM 推理调度、GPU 资源调度)中实现规模化应用,服务涵盖零售、金融、汽车、游戏等领域的数千家企业客户。
本文将从开发者视角出发,深入解析轻量消息队列中一项关键能力------"无损发布"的核心优势、技术实现以及实践经验,如果您的业务也有类似需求,本文将为您提供一套经过生产环境验证的实践参考。
- "无损发布"的核心优势与业务价值
(1)核心优势
"无损发布"并非一个新概念,在业内有各种各样的方案。相比之下,轻量消息队列的"无损发布"具备以下几个关键优势:
- 百万 TPS 级无感知、无报错的服务发布:大多数"无损"方案依然会造成一部分流量的业务中断,而本方案经百万 TPS 生产实践验证,在发布过程中,客户侧不会有任何业务中断。
- 兼容存量用户:客户侧无需任何改造,避免"要求客户端升级"这类难以推行的操作。
- 高鲁棒、低维护:方案简洁、鲁棒性强,在不改动架构的情况下无须进行维护。
- 通用性强:可适配绝大多数基于 HTTP 协议的无状态应用。
(2)业务价值
面对发布期间可能出现的分钟级概率性报错,我们不禁会问:是否有必要投入资源去解决?我们的业务是否需要借鉴本文方案进行改造?
通过业务改造前后对比(见下图)可见,实现"无损发布"带来的业务收益远超多数人的预期,下方清晰地展示了其业务价值,为上述问题提供了明确的答案。
接下来,将从开发者视角出发,依次介绍轻量消息队列"无损发布"的网络架构、核心实现以及落地实践。
- 阿里云轻量消息队列"无损发布"方案解析
(1)网络架构
轻量消息队列"无损发布"的网络架构简化模型如上图所示,其设计有以下几个核心点:
- 聚焦网络入口层:对于无状态应用(MNS 实际存在有状态部分,本文暂不涉及),升级过程中只需考虑如何将待发布的应用进行 TCP 连接优雅摘除即可,故重点聚焦于架构的网络入口层。
- 架构通用性强:该架构与大部分 HTTP 业务架构类似,因此具备良好的通用性,可被广泛采用。
- 方案兼容性强:在方案落地过程中,我们遇到了多种不同的部署形态及组件,如 ACK(阿里云 Kubernetes 服务)、ECS 的不同部署形态,LB 多种不同组件的不同版本,ACK 的不同网络架构等。尽管过程中面临诸多挑战,但最终实现了全面兼容,验证了该方案具备组件可替换、通用性好的优点。
- 与应用解耦:该实现与应用解耦,不需要对应用进行改造(注:如不存在 nginx proxy,也可将对应能力移植到应用上),可适用于大多数场景下的应用。
- 客户端无感知:这是本方案的一大优势,仅需在服务侧进行改造即可,Client 无须任何变动,因此可以很好地兼容存量用户。
(2)核心实现流程
轻量消息队列(原 MNS)"无损发布"的核心实现流程如上图所示,简化描述如下:
阶段一:摘除待发布应用的连接
- 步骤一:摘除 TCP 建连请求,且保证残余连接正常转发以及应用正常响应(实现参考下文 4.(1)部分)。
- 步骤二:优雅关闭残余连接(实现参考下文 4.(2)部分)。
阶段二:发布应用
- 步骤三:确认应用已无连接以及请求后,进行发布。
- 步骤四:流量引入发布完成后应用。
在技术方案的设计过程中,我们始终遵循"奥卡姆剃刀法则":极简的往往最鲁棒、通用,而本实现流程正是这一原则的体现。
在技术方案的落地过程中,尽管轻量消息队列(原 MNS)历史较长,架构、组件情况较为复杂,遇到了多种部署架构(如 K8S、ESC),各类组件(如 client、LB、nginx、kube-proxy)的配置与兼容性等问题,该方案在轻量消息队列(原 MNS)的架构中最终得以成功落地,充分验证了其通用性与鲁棒性。
- 百万 TPS 轻量消息队列"无损发布"实践
(1)摘除 TCP 建连请求
概述
摘除 TCP 建连请求的方式,简单理解就是使用 LB(负载均衡)将对应 RS(后端服务器)摘掉,但要实现真正"优雅"的无损发布(即客户侧无任何报错与感知),需要解决以下几个关键技术问题:
-
如何摘除新建连请求? -- 需要明确摘除 RS 的管控方式,如果基于 API 可能会因为组件依赖导致可迁移性差。
-
如何保证优雅? -- 摘除 RS 后,新建连接请求会被拒绝,但存量 TCP 连接也会因路由规则被移除而中断,从而导致流量受损。
-
如何兼容 K8S 架构? -- 在 K8S 架构下,LB 与 POD 之间多了 kube-proxy 这一网络组件,且这个组件在 ACK 不同网络架构下又有不同表现,该如何兼容?
为了解决以上问题,我们针对 K8S、ECS 架构及不同版本组件,都提出了相应的解决方案。
实现方案
- ECS
- K8S(阿里云容器服务 ACK)
在 ACK 架构下,由于多增加一层 K8S 的网络架构,实现过程经历了较多曲折。最终方案的实现原理涉及 K8S 的 kube-proxy 网络组件,下面的每个配置几乎都是都是经过权衡后的标准化配置。为了简洁说明,下面将重点阐述实现方式。
(2)优雅断连
"优雅断连"指的是在业务无中断前提下关闭 TCP 连接,这一实现是本方案中的核心技术难点,也是最重要的部分。
概述
实现"优雅断连",我们需要重点关注两个核心点:
-
TCP 连接只能由客户端关闭
- 原因:TCP 网络链路为 client -> LB (-> kube-proxy) -> tengine -> 应用,若断连 LB 下游任一连接,都会导致 client 侧依然认为与 LB 的连接存在,会继续往对应连接发送 http 请求,由于下游连接已中断,从而导致业务中断。
-
不能要求客户升级客户端
- 原因:无法要求所有客户升级,无损改动无意义。
基于以上两点,我们通过两个方式保证优雅断连:
-
对于有请求连接
- 方式:返回 Response 带上 HTTP 关闭帧。
- 原因:由于 client 对 http 协议的原生兼容,接收到 Response 后会完成本次请求 + 自行关闭连接。
-
对于无请求连接
- 方式:在摘除 LB 后等待 socketTimeOut 时间。
- 原因:等待 socketTimeOut 时间内,对于有请求的连接,已经通过第一种方式关闭掉,对于没请求的连接,client 会自行对该连接标志为废弃连接。
该方案之所以具备通用性,是因为其利用了所有标准 HTTP 客户端均支持的协议特性。
实现方案
前置改造:
- 改造 nginx 源码 ,提供一个主动向 client 端发 HTTP 协议的关闭帧信息的开关。
原因:nginx(or tengine)不支持用户控制的向 client 端发送关闭帧信息的能力(源码中写死) ,只能通过自行改造源码进行能力支持。(相关讨论参考相关 github issue)
发布步骤:
- 步骤一:打开 nginx 回复关闭帧的开关 -- MNS 侧是通过 status 标志文件控制,删除 status 标志文件后会摘除 LB 的 RS 以及 nginx 回复关闭帧。
- 步骤二:等待 socketTimeOut 时间 -- 关闭(keep-alive-timeout 内)无请求的连接。
- 步骤三:确认已无连接 -- 通过请求量、连接数等可观测手段,确认已无残余连接,此时应用已经摘除所有流量,可以进行升级操作。
(3)CI/CD 接入
前文(1)、(2)聚焦在架构侧的改造,由于其能力实现较为细节和深入,对于平时较少接触相关业务内容的同学来说,可能会较为抽象,甚至产生"接入自动化复杂、门槛高"的误解。实际上,该方案设计简洁,能够轻松融入现有的大部分 CI/CD 和 K8s 体系,下面将介绍如何接入。
ECS
ECS 接入 CI/CD,只需改造 offline 部分以及 online 部分 CI/CD 脚本即可,以下为发布脚本的伪代码:
pubstart) offline stop_http stopjava startjava start_http online ;; offline_http() { echo "[ 1/10] -- offline http from load balance server" # 删除标志文件 # 效果: # 1. (改造一)LB健康检查失败,摘除新建连请求 # 2. (改造二)nginx对所有response带上HTTP中断帧,client侧受到response后关闭连接 rm -f $STATUSROOT_HOME/status # 效果:应用侧对所有请求快速返回,防止极端情况 curl localhost:7001/shutDownGracefully # 等待socketTimeout + LB健康检查时间 # 效果:client侧(到发布中应用的)所有连接到达Timeout,发布中应用的所有连接被摘除 sleep $SOCKET_TIMEOUT + $HEALTH_CHECK } stop_http() { 关闭nginx } stopjava() { 关闭java } startjava() { 启动新java包 } start_http() { 启动nginx } online() { # 回挂标志文件 touch $STATUSROOT_HOME/status }
K8S 架构
K8S 架构下,pod 关闭过程中原生预留了优雅关闭的接口,将上述脚本放至 preStop 即可,yaml 定义如下:
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 1 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: main-container image: my-image:latest lifecycle: # 将下线脚本定义为preStop即可 preStop: exec: command: - sh - /home/admin/offline.sh ports: - containerPort: 8080 - name: sidecar-container image: sidecar-image lifecycle: # 其他sideCar等待即可,防止影响主容器 preStop: exec: command: - sh - -c - sleep 100
(4)验证
以模拟场景的测试数据举例说明,对比本方案在改造前后的差异:
从以上的测试结果可以看到,在经过"无损发布"改造后,发布期间的客户侧的错误率归零。
- 总结
本文详细阐述了阿里云轻量消息队列(原 MNS)实现"无损发布"的核心技术路径。
其关键点在于:
首先,通过改造负载均衡(LB)的健康检查机制与利用其 Draining 能力,实现了新流量的无感知隔离;
其次,通过对 Nginx 源码的改造,在 HTTP 响应中注入关闭帧,引导客户端主动、优雅地关闭活跃连接,并结合超时机制处理空闲连接,最终确保在应用更新前所有流量被平滑清空。
最终,给出兼容 ECS 与 Kubernetes 等多种部署环境的落地实践。
正是基于上述这些关键点的实现,MNS 才得以在客户侧无改造的前提下,对外提供真正意义上的无损能力。无论是在百万级 TPS 的高并发场景下,还是在复杂的网络架构中,MNS 都能确保服务发布和版本迭代对客户业务的零中断、零感知,从而持续提升了客户的整体体验。无损发布不仅是轻量消息队列众多优点之一,更是我们产品践行"追求卓越""客户第一"理念的切实体现。
【1】阿里云轻量消息队列(原 MNS)
https://www.aliyun.com/product/smq
点击此处,了解轻量消息队列(原 MNS)更多详情

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Nacos 开源 MCP Router,加速 MCP 私有化部署
作者:正己 Nacos MCP Router 简介 Nacos MCP Router 是一个基于 MCP 官方 SDK 开发的标准 MCP Server,为 MCP Client 提供 MCP Server 的智能搜索、安装、代理等功能,极大地简化了 MCP 服务的使用流程。同时,Nacos MCP Router 跟 Nacos MCP Registry 结合,可以实现 MCP Server 和 Tool 的全生命周期管理,如 MCP Server 及 Tool 可见性、版本管理等。 今天,我们很高兴地宣布 Nacos MCP Router 发布全新版本,带来了多项重要更新,包括对 SSE 和 StreamableHTTP 协议的全面支持、Docker 容器化部署方案以及革命性的 MCP Server 协议一键转换功能。这些新特性将为开发者提供更加灵活、高效的 MCP 服务使用体验,推动 MCP 生态系统的繁荣发展。 项目地址:https://github.com/nacos-group/nacos-mcp-router 应用场景 新版 Nacos MCP Router 的特性组合,为...
- 下一篇
从硬盘爆满到 GitHub 封号,一位前端开发者的开源历险记
前段时间,我结识了一位前端工程师「1024小神」。他的“战友”是一台 MacBook Air M3(8G+256GB),原本用来开发网页、小程序,绰绰有余。 然而,他的噩梦始于老板轻描淡写的一个需求。 某天,老板让他开发 Windows 软件。他二话没说,装了虚拟机、Win11、Flutter...硬盘瞬间少了 100GB。 一个月后,老板又让他开发 iPhone 和 iWatch 程序。他再次接下所有,安装了 Xcode、SwiftUI...硬盘再减 128GB。 接下来,还有用 Cocos 开发直播间小游戏、把 CRM 系统做成跨平台应用等各种需求接踵而至。 直到那天,小神的电脑屏幕上弹出一个冰冷的提示——“您的磁盘空间不足”。 这台曾经与他并肩作战的 MacBook Air,如今仅剩 300M 空间。此刻它像一个被塞满的行囊,发出了无声的悲鸣。 那个深夜,小神望着屏幕,陷入了沉思。一个前端工程师,为何要活成一个“八爪鱼”,被迫装上所有平台的开发环境?难道就没有一种更优雅、更轻量的方式,去实现所谓的“跨平台”吗? 他试图在开源社区中寻求破解之道,但始终没有找到完全契合需求的项目。如...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Mario游戏-低调大师作品
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Thymeleaf,官方推荐html解决方案