← 文章 / 未分类
bytebytego 3小时前 · 2026-09-17 18:46:25 · 0 阅读

为可靠性而生:美国运通如何实现大规模支付处理

认证往往是应用中测试最不充分的部分。真实环境需要网络访问和真实凭证,而 mock 又模拟不出那些在生产环境中导致故障的失败场景。

@workos/emulate 可以在本地运行 WorkOS API,方便开发和自动化测试。你可以预置用户、组织、RBAC 角色和 SSO 连接,然后完整测试 AuthKit 登录流程、带签名的 webhook、token 刷新和错误处理,完全不用碰生产环境。响应和事件结构都来自 WorkOS OpenAPI spec,因此测试覆盖的就是应用在生产中实际调用的接口。通过 npm、Homebrew、Docker 或独立二进制文件,在本地或 CI 中运行即可。

在本地运行 WorkOS


用户刷卡支付时,期望几乎是瞬间得到批准或拒绝的结果。这一个需求决定了支付系统的全部设计,因为整笔支付的处理必须在这个极短的窗口内完成。

我们最近采访了 American Express 的 Distinguished Engineer Ben Cane,了解他们的平台是如何做到的。

要理解其中的运作方式,可以想象一笔交易到达 American Express 后会发生什么:它被路由到若干独立处理单元之一,然后经过一长串微服务的处理。但假如处理到一半,其中某个服务开始出故障,而收银台前的顾客还在等着呢。

在出故障的单元内重试这笔交易,风险显而易见。而把交易转移到另一台服务器,问题就更棘手了——因为第二个单元必须知道第一笔交易处理到了哪一步。要共享这类信息,就会引入依赖,把两个本应独立的单元变成一个脆弱的系统。

美运通工程团队采用基于 Cell(单元)的架构来处理这一问题,从而将中断造成的影响降至最低。在与该团队交流时我们了解到,大部分工程精力都投入到了在压力下维持这种隔离性上。本文旨在解析交易如何流经此类单元架构,以及当部分服务失效时,支付流程如何依然得以处理。

核心支付生态系统

在典型的支付流程中,美运通处于交易链路的中间环节。商户与收单行建立合作关系,收单行将交易发送至美运通,再由美运通传递给持有账户余额的发卡行。完成这一“中间跳转”正是核心支付网络的核心职责。

下方的图示展示了这一架构配置:

2018 年,美运通开始将该平台迁移到云原生基础设施上。很快便发现,一个前提假设必须做出改变。旧系统运行在专门设计为持续运行的硬件上,而云基础设施的行为则大相径庭。服务器可能因任何团队都无法控制的原因而消失。因此,必须假设这些完全不可控的故障会更频繁地发生,并据此构建应用程序。

当时考虑了两种熟悉的设计模式:

  • 事件驱动处理并不契合。该负载需要大规模运行、低延迟以及实时响应,几乎没有延迟空间。虽然存在异步任务,但结果本身仍必须快速送达。

  • 单体架构是大多数团队的起点,但其很难满足扩展性要求。

美国运通工程团队最终的设计决策,部分源于内部数十年的思考。Ben 指出,早在 SOA 时代、微服务概念尚未成型之前,他的团队就已经在尝试降低单个故障对特定系统的影响。即便在“单元化架构”(cell-based architecture)这一更正式的术语出现之前,相关模式已经存在。

单元边界

在单元化架构中,一个单元是支付处理栈的完整、自给自足的副本。换句话说,处理交易所需的一切都位于同一个边界内。这包括微服务、数据库、DNS 以及支撑性基础设施。

单元具备五个关键属性:

  • 独立部署,自行处理支付。

  • 独立拥有其微服务、数据库及其他组件。

  • 构成单一故障域,内部问题不会外溢。

  • 可因维护或事故被移出轮换,平台其余部分继续运行。

  • 关键路径上没有跨单元的同步依赖。

参考数据仍在单元间复制,可观测性数据可以在单元间聚合,路由实例之间也跨单元通信。但绝不允许在交易处理的关键路径上出现单元间的阻塞调用。

换句话说,cell 是由故障边界来定义的,而不是由某种具体的基础设施形态。一个 cell 完全位于单个 region 之内,处理所需的全部资源也都封闭在这个边界里。

cell 该划多大,需要靠经验判断。American Express 的工程师把它看作一种权衡:你肯定不希望把整个企业都塞进一个 cell 里。理想情况下,边界应该围绕所支持的业务旅程来画。以支付为例,就是要涵盖给出即时应答所需的最小组件集合,也就是一笔交易的实时链路。至于事后处理的链路,完全可以放在另一个 cell 里。

需要说明的是,cell 不等于微服务。微服务是按功能切分系统,cell 则是按故障切分。一个 cell 里可以包含许多微服务。边界之所以重要,是因为一旦跨越 cell 边界,就进入了危险地带,需要相应的弹性能力、流程和业务逻辑来应对可能出现的故障。

数据本地化

一个 cell 要做到自给自足,前提是它所需的数据已经存在于 cell 内部。American Express 的工程团队根据数据变化的频率,采用三种不同的数据策略:

  • 不可变数据:一次性设置好,之后不再变动。

  • 半静态数据:变化频率从几小时一次到一年一次不等,例如汇率、商户类别码、国家代码。

  • 动态数据:每笔交易都会变化。

针对前两类数据,American Express 会在交易需要之前,就把这些参考数据分发到每个 cell。否则就只能靠 fall-through 读取——也就是本地缓存未命中后,交易只能干等着,去中央系统查询记录。提前推送数据带来了多重好处:

  • 首笔交易无需为冷缓存买单。

  • 关键路径避免了同步调用跨越 Cell 边界。

  • 复制工作完全在交易路径之外执行。

Ben 对比了更常见的模式。他表示,他们倾向于采用 Push 和分发机制,而非传统的 Pull 加缓存模式,从而让首笔交易免于构建缓存。

不过,这种方法在处理动态数据时存在不足。虽然复制速度快且异步执行,但仍会存在一个时间窗口,在此期间 Cell 可能持有旧状态,而交易恰好到达。若将交易发送至持有旧数据的 Cell,会增加延迟并导致处理失败的风险。

为应对这一场景,American Express 反转了问题逻辑:平台不将数据移动到交易侧,而是将交易引导至数据所在地。

这通过确定性路由(Deterministic Routing)实现,即决策依据交易自身的内容(如合作伙伴、市场、支付类型),而非 Cell 的负载或可用性。一个叫 Global Transaction Router 的组件在前端入口处做出决策,下一节将详细介绍该组件。

确定性路由是两种模式之一。路由器还支持基于优先级的路由,Cell 具有特定排序,流量会导向可用的最高优先级健康 Cell。具体采用哪种模式取决于使用场景。

然而,这种路由并非通用规则。American Express 仅在有强一致性需求时选择性地应用确定性路由。这取决于交易类型,某些交易类型数据需求较少,可以自由路由。

单元格之间的消息复制一直在进行,因此故障切换数据并不只存在于一个位置。这里的时序至关重要,因为所有在途事务都会继续推进,无需等待复制完成。

全局事务路由器

全局事务路由器负责转发流量,并强制执行单元格边界。

每笔交易进入

原始来源: bytebytego

评论 (0)