與 API 供應商的錢包轉帳:讓請求佇列保持暢通
平台與 API 供應商之間串接的轉帳呼叫如何塞爆請求佇列,以及佇列、快速回應和推送結果如何讓平台在供應商變慢時依然穩定。
平台保管使用者的錢包;API 供應商則運行平台所提供服務背後的伺服器。使用者要用某個供應商的服務前,資金從平台轉到供應商;用完之後再轉回來。大多數整合把這些轉帳做成雙向串接的同步 HTTP 呼叫。流量一大,這條鏈會同時塞滿雙方的請求佇列,一個變慢的供應商就能拖垮整個平台。你的平台穩不穩定,不該取決於別人的伺服器。
一筆轉帳就是一條請求鏈
平台的 worker 在整趟往返中都被佔住,包括供應商回呼平台的那一段。供應商的 worker 則在等那次回呼時被佔住。雙方互相等待,所以流量上升時兩邊的連線池會同時塞滿。一次逾時就讓轉帳狀態不明,接著就是狀態輪詢和重試;如果沒有冪等鍵,重試還可能讓錢轉兩次。
一個慢供應商怎麼變成所有人的問題
以下是推算範例,不是壓測結果(撰寫於 2026-11-09):每秒 500 筆轉帳,分散在三個供應商,平台的連線池有 200 個 worker。Little 定律算出使用中的 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 上每次發佈算一則訊息;付費方案不計算送給訂閱者的份數。請看價格。
產品名稱為其所有者的商標。