问题场景
我在公司负责投研系统的行情数据模块,最近有一个新的需求:需要同时监控多只热门美股的实时逐笔成交,并把数据分发给下游的风控和策略服务。一开始我沿用了基于 REST 的轮询方案,但很快遇到两个棘手的麻烦:一是轮询频率稍高就触发 API 限流,二是两次请求之间的时间盲区导致丢单。这不是我想要的“实时”。
技术选型考量
替换方案必须满足三个条件:低延迟、全量推送、易集成。HTTP 轮询和长轮询都不达标,Server-Sent Events 虽然推送,但兼容性和控制力不如 WebSocket。最终我选择了 WebSocket 协议,并找了一个稳定、文档清晰的数据源做对接——我使用了 AllTick 的实时行情接口,它支持通过 WebSocket 订阅多只股票的 tick 流,推送格式为 JSON,容易解析。
最小的可行示例(MVP)
为了让团队快速验证可行性,我写了一个轻量级的 Python 脚本,完成连接、订阅和打印。代码如下:
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# 打印逐笔成交价格和量
print(f"{data['symbol']} 价格: {data['price']} 成交量: {data['volume']}")
def on_open(ws):
# 批量订阅活跃美股
symbols = ["AAPL", "TSLA", "AMZN"]
for symbol in symbols:
ws.send(json.dumps({
"action": "subscribe",
"symbol": symbol
}))
ws = websocket.WebSocketApp("wss://apis.alltick.co/ws/stock-tick",
on_message=on_message,
on_open=on_open)
ws.run_forever()运行后,三只股票的每一笔成交都在毫秒级内推送到控制台。这也让团队对 WebSocket 方案的实时性有了直观感受。
数据落地与消费
光看控制台肯定不够,我们做了标准化处理:
- 接入层:用 Python asyncio 将 WebSocket 推送解析后写入 Redis Pub/Sub,解耦生产与消费。
- 存储层:按日期分表存入 PostgreSQL,每笔记录包含 symbol、价格、成交量、成交时间、买卖方向等。
- 服务层:后端拉取 Redis 实时流,计算分时指标并通过 WebSocket 二次分发给前端组件。
避坑指南
- 心跳保活:一定要开启 WebSocket 的 ping/pong 或定时发送心跳包,避免被中间代理关闭。
- 重连策略:on_close 时执行退避重试,不能立即无限循环重连,防止击穿服务端。
- 幂等去重:利用 tick 数据自带的 trade_id 做去重,避免统计时一笔成交计算两次。
- 限流保护:即便是推送模式,也要在客户端做流速控制,以防极端行情下下游服务被冲垮。
总结
从轮询切换到 WebSocket,实时性得到了质的飞跃,也解决了限流困扰。如果你正在为实时行情数据抓取头疼,不妨尝试用 WebSocket 重新设计你的数据入口,投入并不大,但回报是研发效率和信号质量的明显提升。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。