为什么进行服务重构,流量如何切换?

考查重点:重构收益与渐进切流。用已有耦合或性能问题说明重构目标;新旧服务并行兼容,小流量验证后逐步切换,异常退回旧链路

本题目录

参考答案

核心回答

服务重构通常是为了解决已经影响业务的问题,例如模块耦合导致修改牵连太大、重复逻辑增加交付成本,或者旧模型与调用链难以支持新的数据规模和业务形式。目标应落实为可验证的变化:哪些依赖要拆开、哪些能力要统一、性能或故障问题准备怎样改善,而不是仅仅更换框架或重新划分目录。

流量切换可以采用新旧服务并行、按边界逐步迁移:先保证接口和数据兼容,再让小范围用户或业务进入新链路,观察业务结果、错误、时延与数据差异,稳定后逐步扩大。路由可以按租户、用户、接口或权重控制;多服务协作时,还要传递灰度标记,避免请求在不兼容的新旧版本之间来回穿插。

**回退要同时考虑流量与数据。**旧服务保有承接能力,且仍能处理迁移期间的数据,才具备快速回切条件。新版本产生了旧版不认识的数据、外部操作已经发生,不能只改回路由就认为整个系统恢复了。

先说明重构解决了什么

可以从一个实际阻力出发:同一业务规则散落在多个服务,每次修改都要同步多处;新增一种数据类型需要复制整条处理链;故障时难以确认哪个模块负责。重构针对这些问题收拢规则、明确模块职责、建立稳定接口,保留确实需要的业务行为。

判断是否值得做,还要比较局部修复与重构的代价。一个查询缺索引,可能直接修正就够了;如果多处问题来自相同的耦合与模型缺陷,再考虑拆出独立能力。新系统也会增加迁移、双版本维护和运维成本,收益不只看代码行数变少。

完成后,用相同业务条件比较结果,例如新增同类需求需要改动多少模块、故障能否隔离、原有慢链路是否改善。具体数字来自相应观察和测试;方案阶段先明确指标及验证方法。

从一个可独立迁移的能力开始

优先选择业务边界明确、调用入口可控、可以单独验证的接口或流程。可以在旧入口后加入路由或适配层,让调用方逐步转向新实现,不必要求所有客户端同一天升级。

新旧实现并存期间,应核对输入输出、错误语义、超时与幂等约定,以及数据库、缓存和消息格式的兼容性。若同时改表结构,可以先增加兼容的新字段或新结构,使旧版本仍可运行,待迁移和回退窗口结束后再清理旧结构;不要把破坏性删改与首次切流绑在一起。

涉及数据迁移时,明确当前权威数据源、历史数据如何补齐、并发新增修改如何追上,以及怎样核对遗漏、重复和顺序。双写是可选方案,但写入两处不自动成为原子操作;部分失败的重试、补偿和对账仍需设计。

灰度流量怎样进入正确链路

**先验证结果,再扩大真实流量。**可以回放代表性请求,或对适合的只读请求做影子比对。带扣款、发消息等副作用的请求不能不加区分地复制执行;即使是影子链路,也要确认其工具、数据和外部访问不会影响真实业务。

**按合适的单位分流。**对有会话或状态连续性的业务,可以根据稳定的用户、租户或任务标识分组,让同一对象进入一致链路。按请求权重分流适合相应无状态场景,但不能假设少量请求就恰好符合配置比例。服务副本占比也不等于精确的业务流量占比。

**多跳调用保持标记与兼容。**入口判定属于灰度流量后,沿调用链传递相应路由信息,各层按约定选择版本。若某个下游没有对应版本,要明确兼容回落还是拒绝,不能让任意混用成为隐含规则。路由标签只用于版本选择,不能代替用户身份和数据权限。

**按业务表现推进。**同时比较新旧版本的业务成功率、结果差异、错误与超时、尾延迟、队列和资源。每个阶段要有足够的请求类型与观察时间,覆盖低频但重要的分支;比例和时长按风险、流量及容量选择,没有统一的“先 1% 就安全”。

一个逐步替换的例子

以“把订单查询中的数据聚合逻辑抽成独立服务”为设计示例:旧接口继续作为入口,新服务先返回与旧接口兼容的结果。先回放已有场景,再让指定测试租户进入新服务,其他请求继续走旧实现。

确认订单状态、字段、权限和错误处理一致后,再按稳定租户分组扩大范围。新服务出现异常时,入口可以把后续新请求转回旧服务;已在执行的请求则按状态等待结束、取消或有限重试,避免新旧两边同时处理同一个动作。这个例子先迁移读取能力,后续若涉及订单写入,还需单独设计写入所有权和数据恢复。

回滚为什么不只是切回旧地址

流量回退停止的是后续请求进入新路径,无法撤销已写入的数据、已发出的消息或已触发的外部动作。切换前应确认旧版能读取当前数据,保留足够容量,并有办法处理在途任务和部分完成状态。

若已经删除旧字段、停止维护旧数据,或完成不可逆的语义转换,直接回旧版本可能不再成立。这时要使用预先设计的数据修复或向前修复方案。最后退出旧链路时,也要核对定时任务、消息消费者、缓存与长连接等入口,不能只看网关 HTTP 流量降为零。

常见追问

蓝绿、金丝雀和渐进替换是同一件事吗?

它们关注的维度不同。蓝绿常通过两套可运行环境完成切换;金丝雀先让少量真实流量使用新版本;渐进替换则按业务边界逐步替换旧能力。一次系统重构可以用渐进替换控制范围,再用金丝雀验证其中某个服务版本,不必互相排斥。

新旧结果不完全相同,就说明重构失败吗?

先区分预期修正与意外差异。新增规则或修复旧错误会带来合理变化,需要明确适用范围和验证样本;接口兼容、权限、金额或状态语义的意外变化则要定位。不能只比较响应文本是否逐字相同,也不能把所有差异都解释成优化。

全量切流后能马上删除旧服务吗?

应先确认兼容与回退窗口已经结束,旧入口、后台任务和依赖都已迁移。下线旧服务可以结束双版本维护,但也意味着部分回退能力消失,应与数据清理和运行状态一起安排。

参考资料

相关面经

5 篇

蚂蚁集团

面经合集
查看原面经 →
技术债务重构的优先级怎么划分?系统演进时怎么保证业务不中断?

阿里巴巴

AI 全栈开发工程师
社招二面
查看原面经 →
项目追问
项目大重构思路?正交/冗余怎么处理?

阿里巴巴

基础设施平台开发工程师
社招一面
查看原面经 →
你们重构的平台具体聊一下。

传音

数据平台开发工程师
社招一面
查看原面经 →
项目追问
服务重构的背景是什么样子的?流量如何切换?

唯品会

Agent 开发工程师
社招二面
查看原面经 →
服务重构的动力和推动人

相关题目

4 题