連接保活
WebSocket 行情推送是長連接服務。客户端需要正確處理 WebSocket 協議層的 ping/pong、網絡超時、斷線重連,以及重連後的重新鑑權和重新訂閲。
WARNING
當前行情推送接口不定義業務層 JSON 心跳消息。請不要向連接發送自定義的 { "action": "heartbeat" }、{ "type": "ping" } 等業務心跳幀,也不要依賴服務端返回某種 JSON 心跳事件。
連接保活應使用 WebSocket 協議層 ping/pong 能力,或使用客户端 SDK / WebSocket 庫提供的連接狀態、超時和重連機制。
Ping / Pong
WebSocket 協議本身支持 ping/pong 控制幀。不同運行環境的處理方式不同:
| 客户端類型 | 建議 |
|---|---|
| 瀏覽器 WebSocket | 瀏覽器會在協議層自動響應服務端 ping。業務代碼通常無法直接發送或監聽協議層 ping/pong,只需要處理 open、message、error、close 等事件。 |
| Node.js、Java、Go、Python 等服務端客户端 | 優先使用 WebSocket 庫內置的 ping/pong、讀寫超時和空閒檢測能力。收到服務端 ping 時應及時返回 pong;如客户端庫需要主動 ping,可按業務網絡環境配置。 |
| 移動端或弱網絡環境 | 關注前後台切換、網絡切換、系統省電策略導致的連接掛起。恢復網絡後應檢查連接狀態,必要時重連。 |
平台不要求客户端發送某個固定 JSON 格式的心跳包。若你的 WebSocket 庫支持協議層 ping,可以開啓庫自帶的 ping/pong 機制;若運行環境不暴露協議層 ping,則應通過連接關閉事件和業務消息超時來判斷連接是否可用。
定時刷新 Token
OAuth 2.1 簽發的 Access Token 有有效期限制。為避免 token 過期導致連接被服務端主動斷開,客户端應在 token 到期前定時刷新:
- 在獲取 token 時記錄
expires_in(有效期秒數)。 - 建議在 token 有效期過半或到期前 5 分鐘時,使用 Refresh Token 獲取新的 Access Token。
- 獲取新 token 後,通過當前 WebSocket 連接重新發送登錄鑑權消息,完成 token 更新。
- 如果刷新失敗(例如 Refresh Token 也已過期),應引導用户重新授權。
TIP
定時刷新 token 是長連接保活的關鍵步驟。即使網絡和 WebSocket 協議層 ping/pong 一切正常,token 過期後服務端仍會斷開連接。
超時處理
長連接可能因為以下原因斷開或變得不可用:
- 本地網絡切換、代理或防火牆中斷連接。
- 客户端進程休眠、移動端進入後台、系統回收網絡資源。
- 服務端發佈、擴縮容或維護。
- 連接長時間無有效讀寫,被中間鏈路或 WebSocket 庫判定為空閒超時。
建議客户端實現以下超時策略:
- 連接建立超時:發起連接後,如果在合理時間內未進入
open狀態,應關閉本次連接並重試。 - 鑑權響應超時:連接建立後需要先完成登錄鑑權。如果鑑權請求長時間沒有響應,應關閉連接並重新建立。
- 訂閲響應超時:訂閲請求發出後,如果長時間未收到響應,應結合連接狀態決定是否重試訂閲或重連。
- 業務消息空閒檢測:如果連接處於打開狀態但長時間沒有任何消息,應結合協議層 ping/pong、行情時段和訂閲標的活躍度判斷連接是否仍然健康。不要僅因非交易時段沒有行情推送就立即判定連接失效。
具體超時時間請按客户端所在網絡環境、產品實時性要求和 WebSocket 庫能力設置。文檔不承諾固定的公網 ping 間隔或超時閾值。
斷線重連
收到 close 事件、連接異常、鑑權失敗、訂閲鏈路不可用或本地檢測到連接失效時,客户端應重新建立 WebSocket 連接。
推薦重連流程:
- 停止向舊連接發送新請求。
- 清理舊連接的本地狀態,例如正在等待響應的請求、連接對象、臨時定時器等。
- 使用退避策略重新連接,避免短時間高頻重試。
- 連接建立後重新登錄鑑權。
- 鑑權成功後重新訂閲當前業務仍然需要的標的和數據類型。
- 訂閲恢復後,按需通過 REST 實時行情接口補齊最新狀態。
建議使用指數退避或分段退避策略,例如首次斷線後較快重試,連續失敗後逐步增加等待時間,並設置最大重試間隔。不要在網絡不可用或服務端持續拒絕時無限高頻重連。
重新鑑權與重新訂閲
WebSocket 訂閲狀態與當前連接會話相關。連接斷開後,不應假設服務端仍然保留舊連接上的訂閲狀態。
每次重連後都應按以下順序恢復:
建立 WebSocket 連接
-> 登錄鑑權
-> 訂閲 quote / order_book / ticker / kline 等數據
-> 接收推送注意事項:
- 重連後必須重新鑑權。不要複用舊連接的會話狀態。
- 重連後必須重新發送訂閲請求。客户端應在本地維護“當前業務需要訂閲什麼”,而不是依賴服務端恢復。
- 如果訪問憑證已經過期,應先刷新憑證,再重新建立連接或重新鑑權。
- 如果重連期間用户已經離開頁面或取消關注某些標的,不要恢復這些不再需要的訂閲。
- 訂閲請求建議攜帶客户端生成的請求
id,便於將響應與本地待恢復任務對應起來。
結合 REST 獲取首屏快照
WebSocket 推送更適合接收實時變化,不適合作為首屏完整狀態的唯一來源。為了減少首次渲染等待時間,並避免在斷線期間遺漏最新狀態,建議在以下場景結合 REST 實時行情接口:
| 場景 | 推薦做法 |
|---|---|
| 頁面首次打開 | 先調用 REST 獲取行情快照或實時報價,快速渲染首屏;隨後建立 WebSocket 連接並訂閲實時推送。 |
| 斷線重連成功後 | 使用 REST 查詢最新快照、買賣盤、當前 K 線或逐筆成交,再繼續消費 WebSocket 推送。 |
| 長時間後台後恢復 | 先檢查連接是否仍然有效;如果發生重連,建議用 REST 補齊恢復時刻的最新狀態。 |
| 對完整狀態一致性要求高 | 以 REST 查詢結果作為某一時點的完整狀態基線,再用 WebSocket 推送增量刷新。 |
相關 REST 接口可參考:
服務端會話清理
連接斷開後,服務端會在後台識別離線連接並清理對應會話和訂閲資源。該清理過程是服務端內部保護機制,用於釋放離線連接佔用的資源。
客户端不應依賴服務端清理時機來管理自身訂閲狀態:
- 正常退出頁面、切換標的或不再需要某類數據時,應主動發送反訂閲請求。
- 連接異常斷開時,客户端應按重連流程重新鑑權並重新訂閲,而不是等待舊會話恢復。
- 不要假設舊連接上的訂閲會在新連接中自動繼承。
- 不要依賴服務端會話清理完成後才重新訂閲;新連接應作為新的獨立會話處理。
客户端實現建議
建議客户端維護一份本地訂閲意圖表,用於記錄當前業務真正需要的訂閲項:
symbol + data_type + 可選參數(如 kline period / adjust)連接恢復時,根據這份訂閲意圖表重新發送訂閲請求。這樣可以避免以下問題:
- 斷線後忘記恢復部分訂閲。
- 用户已經取消關注後仍然恢復舊訂閲。
- 多個頁面或模塊重複訂閲同一標的,導致本地狀態混亂。
- 重連過程中無法區分哪些訂閲響應對應當前連接。
同時建議:
- 將連接狀態展示給用户,例如“連接中”“實時行情已連接”“正在重連”。
- 對連續重連失敗設置告警或用户提示。
- 對訂閲失敗、權限不足、配額不足等業務錯誤進行獨立處理,不要簡單地無限重連。
- 頁面關閉、組件卸載或業務不再需要時,主動反訂閲並關閉連接。
常見誤區
| 誤區 | 說明 |
|---|---|
| 發送 JSON 心跳包即可保活 | 行情推送不定義業務層 JSON 心跳協議。應使用 WebSocket 協議層 ping/pong 或客户端庫的連接保活能力。 |
| 斷線後訂閲會自動恢復 | 不應這樣假設。重連後應重新鑑權並重新訂閲。 |
| 有 WebSocket 推送就不需要 REST | WebSocket 適合實時變化;首屏完整狀態、斷線補齊和一致性校準仍建議結合 REST。 |
| 沒有行情推送就是連接斷了 | 非交易時段、標的不活躍或訂閲類型本身更新頻率低時,可能長時間沒有業務推送。應結合協議層心跳和連接事件判斷。 |
| 服務端清理舊會話後客户端才能重連 | 客户端可以直接建立新連接並恢復訂閲。服務端會自行清理離線會話資源。 |