引言

承接首篇《AWS→GCP:一个人,三周,零预演,万级长连接迁徙实录》

AWS、GCP 双活架构下,用户App切到 GCP,设备还在 AWS,通信问题如何解决?

本文针对这个问题,提出了两个可以实际落地的轻量级方案,希望能给你带来一丝灵感。

方案一:Redis会话和MQ双写

核心思路:

用 Redis 在 GCP 和 AWS 之间同步留存设备上线会话标识,用 MQ 双写实现“双写双消费”

当用户已迁入 GCP,设备仍停留在 AWS 时:

App 下发控制指令后,GCP 环境执行 MQ 双写。AWS 消费者收到 MQ 消息,通过比对 Redis 中的会话标识,发现设备属于自己,正常执行业务;GCP 消费者同样收到这条消息,比对后发现设备不在本地,直接空消费。

这种方式保留了原有的程序架构,同时打通了双环境的业务交互。

改造清单:
组件改动方式说明
Redis 缓存模块注入 RedisTemplateWrapper(第二个数据源),改写写入逻辑向两个RedisTemplate同时写入会话标识
MQ 生产者模块注入 MessageSenderWrapper (第二个发送者),改写发送逻辑向两个MessageSender同时发送消息
消费路由器收到 MQ 消息时,从 Redis 读取设备会话标识判断设备是否属于当前环境:属于当前环境则路由执行,不属于则空消费
为什么改动这么少

项目原有的 Redis 缓存、MQ 消息发送和消费路由都已高度模块化。我只需要新增两层包装类,就能做到业务代码零侵入,实现双向双写。路由器在消息处理源头加一层判断,根据会话标记决定路由或空消费。

优点: 三处改动合计不到一百行代码,全程不侵入原业务逻辑。双架构理论上独立运行,迁移窗口期出现意外问题的概率低。

方案确实可行,代码已经改完、本地简单模拟测试也通过了。但在欧洲节点实际部署时,我发现 GCP 环境无法连接 AWS 环境的 RocketMQ——Broker 绑的是内网 IP,外网不通,被迫放弃这个方案。

方案二:前置转发

核心思路很简单:不在MQ层解决问题,在网关层解决问题。

在 GCP 新环境网关前置一个转发服务,给 GCP 新环境上线的设备打上会话标记。当用户 App 接入 GCP 新环境、设备还在 AWS 旧环境时,转发服务发现会话标记为空或归属不一致,就把请求转发到旧环境网关。

流程解析:
  1. 写入标记: 改写新环境设备网关代码,当设备在 GCP 新环境上线时,按 KEY(设备编号)— VALUE(GCP 新环境标记) 写入缓存,供转发服务查询。
  2. 路由判断: 统计所有 App 下行控制设备的接口,统一交由转发服务管理。转发服务收到 App 请求时,根据设备编号查询 Redis 缓存中的标记,若发现设备不是在 GCP 新环境上线的,就把请求转发到 AWS 旧环境业务网关处理。
  3. 逐批迁移: 按批次把设备从旧环境迁到新环境,每迁一批,缓存中的标记就更新一批,转发服务自动将对应设备的流量切到新环境。
方案优势:
  1. 对旧环境:零入侵, 完全感知不到迁移在进行

  2. 对新环境:业务网关层前置一个转发服务, 配合几行设备网关代码改动

  3. 迁移完成后:转发服务和 AWS 旧环境服务直接下线,不留痕迹

方案约束:
  1. 零预演下的精确把控
    迁移全程没有预演,所有操作都是第一次执行。前置转发依赖对设备编号的精确识别,但系统经过多年迭代,不同控制指令接口的设备偏好参数名称并不一致。转发服务需要统一识别这些标识,任何一个接口遗漏,都会导致指令下发失败。

    建议参考此方案时务必预演。我能跳过预演,是因为这套系统从0开始由我作为主程一直迭代至今。

  2. 跨系统迁移的复杂度
    前置转发需要同时操作新旧两套系统,虽然对AWS 旧环境零入侵,对GCP 新环境代码入侵也很少,但流程复杂度远高于 Redis 和 MQ 双写方案。迁移过程中如果出现异常,面对的将不再是“修复一个系统”,而是“在两个系统之间找到断点”。

    预演无法完全覆盖这类问题,只能靠团队对系统架构的熟悉程度兜底。

方案可行,但危险性较高。我在迁移过程中也遇到了一些突发问题——部分问题在方案一身上不会发生。建议参考该方案时慎重评估,优先考虑 Redis 和 MQ 双写。

收尾

发现 MQ 外网不通时,已经接近第一周周三快下班了。必须在当周内完成欧洲节点的迁移,重启 MQ、部署第二个 Broker 都不现实。

最终依靠方案二完成了迁移。欧洲节点整个过程有惊无险,美国节点出了一个意想不到的问题,不过整体基本平稳度过。

下一篇讲述用户 App 和设备如何切流,以及切流过程中遇到的各种问题——方案二潜在的那些隐患、合作公司不按协议做的部分、黑客攻击……都留到那篇再讲。

更多推荐