家里WiFi突然卡顿,游戏掉线、远程桌面断开、监控页面黑屏……别急着重启程序,加个自动重连机制,让软件自己‘拍拍灰’再连上。
先想清楚三件事
不是所有连接都适合自动重连——比如发一次就完的HTTP请求,重连意义不大;但WebSocket长连接、数据库连接池、SSH隧道这类需要持续通信的场景,重连就是刚需。
写之前盯紧三点:什么时候触发重连?重连失败怎么办?连上了要不要恢复状态?
最简实用版(JavaScript)
以WebSocket为例,浏览器里几行就能跑起来:
let ws = null;
let reconnectTimer = null;
const MAX_RETRY = 5;
let retryCount = 0;
function connect() {
ws = new WebSocket('wss://api.example.com/ws');
ws.onopen = () => {
console.log('已连接');
retryCount = 0; // 连上就清零计数
};
ws.onerror = (err) => {
console.error('连接出错', err);
};
ws.onclose = () => {
if (retryCount < MAX_RETRY) {
retryCount++;
console.log(`尝试第 ${retryCount} 次重连...`);
clearTimeout(reconnectTimer);
reconnectTimer = setTimeout(connect, 2000 * retryCount); // 指数退避
} else {
console.warn('重连失败次数超限,停止尝试');
}
};
}
connect();
关键点:用 retryCount 控制最大重试次数,用 setTimeout 延迟重连,且每次延迟时间递增(2s、4s、8s…),避免疯狂刷请求把服务端打崩。
Java 后端常见写法(Spring Boot + Redis)
比如一个定时拉取Redis消息的线程,断连后要自动续上:
@Service
public class RedisSubscriber {
private final JedisPool jedisPool;
private volatile boolean running = true;
public void startListening() {
new Thread(() -> {
while (running) {
try (Jedis jedis = jedisPool.getResource()) {
jedis.subscribe(new JedisPubSub() { /* 处理逻辑 */ }, "channel");
} catch (JedisConnectionException e) {
System.err.println("Redis连接中断,3秒后重试...");
try { Thread.sleep(3000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
}
}
}).start();
}
}
注意这里用了 volatile boolean running 控制开关,手动 sleep 避免空转,比无脑 while(true) + try-catch 更稳。
小提醒:别忘了清理和防抖
重连前记得关掉旧连接(ws.close()、jedis.close()),否则可能留下僵尸连接;如果用户点了“手动断开”,就别自作主张重连——加个标志位判断当前是否为用户主动断开。
另外,重连成功后别光顾着高兴,检查下有没有消息丢了。比如MQ消费者重连后,得从上次offset继续拉;聊天客户端得补发离线期间的消息。这些不是重连本身的事,但没它们,重连只是个半成品。