fix: 防止网关并发连接并优化重连逻辑

This commit is contained in:
sliverp
2026-01-29 20:26:40 +08:00
parent 922c6b3ff5
commit 3f0fdff0e0

View File

@@ -48,9 +48,15 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
let lastSeq: number | null = null;
let lastConnectTime: number = 0; // 上次连接成功的时间
let quickDisconnectCount = 0; // 连续快速断开次数
let isConnecting = false; // 防止并发连接
let reconnectTimer: ReturnType<typeof setTimeout> | null = null; // 重连定时器
abortSignal.addEventListener("abort", () => {
isAborted = true;
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
cleanup();
});
@@ -76,11 +82,18 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
return;
}
// 取消已有的重连定时器
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
const delay = customDelay ?? getReconnectDelay();
reconnectAttempts++;
log?.info(`[qqbot:${account.accountId}] Reconnecting in ${delay}ms (attempt ${reconnectAttempts})`);
setTimeout(() => {
reconnectTimer = setTimeout(() => {
reconnectTimer = null;
if (!isAborted) {
connect();
}
@@ -88,6 +101,13 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
};
const connect = async () => {
// 防止并发连接
if (isConnecting) {
log?.debug?.(`[qqbot:${account.accountId}] Already connecting, skip`);
return;
}
isConnecting = true;
try {
cleanup();
@@ -349,6 +369,7 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
ws.on("open", () => {
log?.info(`[qqbot:${account.accountId}] WebSocket connected`);
isConnecting = false; // 连接完成,释放锁
reconnectAttempts = 0; // 连接成功,重置重试计数
lastConnectTime = Date.now(); // 记录连接时间
});
@@ -485,6 +506,7 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
ws.on("close", (code, reason) => {
log?.info(`[qqbot:${account.accountId}] WebSocket closed: ${code} ${reason.toString()}`);
isConnecting = false; // 释放锁
// 检测是否是快速断开(连接后很快就断了)
const connectionDuration = Date.now() - lastConnectTime;
@@ -492,12 +514,17 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
quickDisconnectCount++;
log?.info(`[qqbot:${account.accountId}] Quick disconnect detected (${connectionDuration}ms), count: ${quickDisconnectCount}`);
// 如果连续快速断开超过阈值,清除 session 重新 identify
// 如果连续快速断开超过阈值,清除 session 并等待更长时间
if (quickDisconnectCount >= MAX_QUICK_DISCONNECT_COUNT) {
log?.info(`[qqbot:${account.accountId}] Too many quick disconnects, clearing session to re-identify`);
log?.info(`[qqbot:${account.accountId}] Too many quick disconnects, clearing session and waiting longer`);
sessionId = null;
lastSeq = null;
quickDisconnectCount = 0;
// 快速断开太多次,等待更长时间再重连
if (!isAborted && code !== 1000) {
scheduleReconnect(RATE_LIMIT_DELAY);
}
return;
}
} else {
// 连接持续时间够长,重置计数
@@ -518,6 +545,7 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
});
} catch (err) {
isConnecting = false; // 释放锁
const errMsg = String(err);
log?.error(`[qqbot:${account.accountId}] Connection failed: ${err}`);