与 API 供应商的钱包转账:让请求队列保持畅通
平台与 API 供应商之间串联的转账调用如何塞爆请求队列,以及队列、快速响应和推送结果如何让平台在供应商变慢时依然稳定。
平台保管用户的钱包;API 供应商则运行平台所提供服务背后的服务器。用户要用某个供应商的服务前,资金从平台转到供应商;用完之后再转回来。大多数集成把这些转账做成双向串联的同步 HTTP 调用。流量一大,这条链会同时塞满双方的请求队列,一个变慢的供应商就能拖垮整个平台。你的平台稳不稳定,不该取决于别人的服务器。
一笔转账就是一条请求链
平台的 worker 在整趟往返中都被占住,包括供应商回调平台的那一段。供应商的 worker 则在等那次回调时被占住。双方互相等待,所以流量上升时两边的连接池会同时塞满。一次超时就让转账状态不明,接着就是状态轮询和重试;如果没有幂等键,重试还可能让钱转两次。
一个慢供应商怎么变成所有人的问题
以下是推算示例,不是压测结果(写于 2026-11-09):每秒 500 笔转账,分散在三个供应商,平台的连接池有 200 个 worker。利特尔定律算出使用中的 worker 数:每秒转账数 × 每笔占住 worker 的秒数。
| 串联 HTTP | 队列、快速受理、推送结果 | |
|---|---|---|
| 一个用户请求占住平台 worker 的时间 | 20 ms + 150 ms 的供应商调用 = 170 ms | 20 ms |
| 每秒 500 笔转账时的忙碌 worker 数 | 500 × 0.17 秒 = 85 | 500 × 0.02 秒 = 10 |
| 三个供应商之一卡住直到 5 秒超时 | 约 900:200 个的连接池用光,所有供应商都失败 | 仍然 10:只有那个供应商的转账在等 |
| 等待结果期间的请求 | 每笔待处理转账每 2 秒轮询一次状态 | 没有,只有每个供应商每几分钟一次批量检查 |
改之后:快速受理、后台结算、推送结果
- 平台先响应用户。 把转账以“处理中”写进账本、放进队列,然后响应。用户的页面显示“处理中”,事件到达时自动更新。
- 由派送器把转账送给各供应商,带幂等键、短超时,而且每个供应商有固定数量的名额。供应商一记录好转账就回 202,所以用同一个键重试永远安全。
- 不要回调。 请求本身带齐供应商需要的一切并附上签章,供应商不必回调平台验证。
- 结果用推送。 供应商把
transfer.settled发布到给该平台的私有频道,例如private-partner-acme。平台后端保持一条 WebSocket 连接并订阅,由供应商的授权端点授权。平台更新账本,再把balance.updated发布到用户的钱包频道,做法同跨产品余额同步。 - 用一次检查补上遗漏。 平台每几分钟向每个供应商用一个批量请求查找仍在处理中的转账,而不是逐笔轮询。
供应商不稳时,平台照样稳定
- 每个供应商各有名额。 变慢的供应商只会占满派送器里自己的名额。登录、充值和其他供应商的 worker 都不受影响。
- 供应商不响应就暂停送出。 连续超时后,暂停该供应商的队列,把它的服务显示为暂时无法使用,等一下再试。转账停在你的账本里处于“处理中”,而不是卡在被占住的连接上。
- WebSocket 断线不会挡住任何事。 转账照常受理。连接恢复后,批量检查会把中间发生的都结算好。
- 用户从不等供应商的响应时间。 页面以平台自己的速度响应,结果好了就会出现。
常见问题
为什么一个慢的 API 供应商会拖慢整个平台?
因为平台的 worker 在等它。每个同步调用都会占住一个 worker,直到供应商响应为止,而这些 worker 是和其他所有功能共用的。一个供应商变慢,worker 就被用光,连根本不碰那个供应商的请求也得排在后面。
WebSocket 会取代转账 API 吗?
不会。转账本身仍是带幂等键的 HTTP 请求,并记录在双方账本里。WebSocket 取代的是等待:被占住的连接、状态轮询和回调。结果改以事件送达。
转账完成时平台刚好断线怎么办?
什么都不会遗失,因为双方账本都已记下这笔转账。pusher-js 和其他客户端库会自动重新连接,处理中转账的批量检查会结算任何漏掉的部分。用转账 ID 忽略已经应用过的事件。
这需要多少条连接?
平台后端到每个供应商的频道各一条 WebSocket 连接,就足以处理与该供应商的所有转账,不论服务多少用户。在 Hibira 上每次发布算一条消息;付费方案不计算送给订阅者的次数。请看价格。
产品名称为其所有者的商标。