做美股实时行情开发那会儿,我遇到过一个特别烦人的问题------网络稍微抖一下,WebSocket连接就断了,程序停在那里傻等,数据全丢了。刚开始我还以为是API的问题,后来才发现是自己没处理好重连逻辑。
有一次夜里跑策略测试,早上起来一看,程序在凌晨两点就断开了,整整六个小时没收到任何数据,那个心情真是复杂。从那以后,我下定决心要把自动重连机制搞得稳稳当当。
为什么WebSocket连接会断
说实话,网络环境没想象中那么可靠。服务器主动断开、网络波动、防火墙超时,甚至本地网络切换,都可能导致连接掉线。如果程序不做重连,数据就断档了。
我以前试过简单粗暴的定时重连,但那样效果很差------明明连接正常却要强行重连,反而增加了负担。后来摸索出一套更智能的重连策略。
我的自动重连方案
以 AllTick API为例,我写了一个带自动重连功能的WebSocket客户端,核心思路是:检测到断开就尝试重连,重连成功后重新订阅之前的股票代码。
python
python
import websocket
import json
import time
class AutoReconnectWebSocket:
def __init__(self, url, symbols):
self.url = url
self.symbols = symbols
self.ws = None
self.reconnect_attempts = 0
self.max_attempts = 10
def on_message(self, ws, message):
data = json.loads(message)
print(f"收到数据: {data}")
def on_error(self, ws, error):
print(f"出错了: {error}")
def on_close(self, ws, close_status_code, close_msg):
print("连接关闭,准备重连...")
self.reconnect()
def on_open(self, ws):
print("连接成功")
self.reconnect_attempts = 0
subscribe_msg = {
"action": "subscribe",
"symbols": self.symbols
}
ws.send(json.dumps(subscribe_msg))
def reconnect(self):
if self.reconnect_attempts >= self.max_attempts:
print("重连次数超限,放弃")
return
wait_time = min(2 ** self.reconnect_attempts, 30)
print(f"{wait_time}秒后尝试第{self.reconnect_attempts + 1}次重连")
time.sleep(wait_time)
self.reconnect_attempts += 1
self.connect()
def connect(self):
self.ws = websocket.WebSocketApp(
self.url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
self.ws.run_forever()
url = "wss://api.alltick.co/stock/ws"
symbols = ["AAPL", "MSFT", "GOOGL"]
client = AutoReconnectWebSocket(url, symbols)
client.connect()
这段代码用了指数退避策略------第一次断开等1秒重连,第二次等2秒,第三次等4秒,最多等30秒。这样既不会频繁冲击服务器,又能快速恢复连接。
重连后要做的几件事
连接恢复了,数据就能自动续上吗?还不够。我发现重连后有几点需要格外留意:
重新订阅:新的WebSocket连接不会保留之前的订阅关系,必须在on_open里重新发送订阅消息。
数据补齐:断开期间的数据空缺怎么处理?我的做法是连接恢复后,调用历史数据接口把缺失的时间段补回来。
状态清理:重连前要把旧的缓存和临时数据清掉,避免新旧数据混在一起。
心跳保持:为了防止防火墙把空闲连接断开,我会定期发送ping消息。有些API自带心跳机制,如果没有就自己实现一个定时器。
实际运行中的调整
用了这套重连机制后,程序稳定多了。但我还发现一些细节值得优化:
重连次数不要无限累加,超过阈值后可以停止重连并报警,让开发者知道出了问题。
重连期间收到的数据请求可以先缓存起来,连接恢复后再批量处理。
不同场景对重连速度的要求不一样。做高频交易的可能希望1秒内就重连,做日常监控的可以放宽到十几秒。我会根据实际需求调整等待时间和重连次数。
一点体会
美股api的WebSocket自动重连看起来是个小功能,但做不好真的很影响使用体验。我现在的习惯是,不管用什么API,客户端层一定要把重连逻辑封装好。这样即使网络有些波动,程序也能自动恢复,不用半夜爬起来手动重启。
说到底,WebSocket只是个通道,怎么用好它还得靠我们自己在客户端下功夫。一套稳定的重连机制,能让数据流省心不少。