使用异步私有WebSocket连接获取FTX交易所数据时消息重复接收问题
问题原因与解决方案
核心故障原因
代码中重复启动了两次handler协程,创建了两个独立的WebSocket连接,两个连接都完成了登录和同频道订阅操作,因此每条推送消息都会被两个连接分别接收一次,表现为消息重复。
同时代码存在变量名冲突问题:登录消息变量名auth和导入的auth模块重名,存在变量覆盖风险,建议修改为其他名称如auth_msg。
修复方案
1. 移除重复的协程启动代码
删除末尾冗余的create_task调用即可解决绝大多数重复接收问题:
# 原有导入、handler函数逻辑不变,仅修改末尾启动代码 if __name__ == "__main__": # Python 3.7+ 推荐直接使用asyncio.run asyncio.run(handler()) # 老版本Python可替换为: # loop = asyncio.get_event_loop() # loop.run_until_complete(handler())
2. 新增消息去重逻辑(可选,适配重连场景)
如果修复后仍存在重复消息,大概率是连接抖动重连时服务端重复推送历史消息,可增加基于消息ID的去重逻辑,完整修改后代码如下:
import asyncio import websockets import json import time import auth import hmac import pprint api_key = auth.api_key secret_key = auth.secret_key # 全局去重集合,存储已处理的成交ID processed_fill_ids = set() async def handler(): async with websockets.connect('wss://ftx.com/ws/') as ws: ts = int(time.time() * 1000) signature = hmac.new(secret_key.encode(), f'{ts}websocket_login'.encode(), 'sha256').hexdigest() # 修改变量名避免和导入的auth模块冲突 auth_msg = {'op': 'login', 'args': {'key': api_key, 'sign': signature, 'time': ts, 'subaccount':'python' }} await ws.send(json.dumps(auth_msg)) sub_msg = {'op': 'subscribe', 'channel': 'fills'} await ws.send(json.dumps(sub_msg)) async for message in ws: data = json.loads(message) if data['type'] == 'update': # 取成交ID做去重判断 fill_id = data['data']['id'] if fill_id in processed_fill_ids: continue processed_fill_ids.add(fill_id) pprint.pprint(data) if __name__ == "__main__": asyncio.run(handler())
3. 其他排查方向
- 确认没有在其他位置重复调用订阅接口,同一连接下重复订阅同一频道也会导致重复推送
- 检查服务端ping帧响应逻辑,
websockets库默认会自动回应ping,若手动修改过配置需确保pong响应正常,避免服务端主动断连重推
注:FTX交易所已在2022年停止服务,若当前使用的是兼容FTX API的其他交易平台,上述接口逻辑通用。
内容的提问来源于stack exchange,提问作者stanvooz
相关产品推荐
相关产品推荐

