diff --git a/blivedm b/blivedm index b2c26b5..5525bf5 160000 --- a/blivedm +++ b/blivedm @@ -1 +1 @@ -Subproject commit b2c26b5f16ee4fd0f4a1ded8c94f9c37e1e2ff6a +Subproject commit 5525bf5419e282f4d0cc7b03cc1e0fd22cee7a73 diff --git a/frontend/src/api/chat/ChatClientOfficialBase/index.js b/frontend/src/api/chat/ChatClientOfficialBase/index.js index a03910c..5aea771 100644 --- a/frontend/src/api/chat/ChatClientOfficialBase/index.js +++ b/frontend/src/api/chat/ChatClientOfficialBase/index.js @@ -51,6 +51,7 @@ export default class ChatClientOfficialBase { this.needInitRoom = true this.websocket = null this.retryCount = 0 + this.totalRetryCount = 0 this.isDestroying = false this.heartbeatTimerId = null this.receiveTimeoutTimerId = null @@ -185,15 +186,17 @@ export default class ChatClientOfficialBase { return } this.retryCount++ - console.warn('掉线重连中', this.retryCount) + this.totalRetryCount++ + console.warn(`掉线重连中 retryCount=${this.retryCount}, totalRetryCount=${this.totalRetryCount}`) window.setTimeout(this.wsConnect.bind(this), this.getReconnectInterval()) } getReconnectInterval() { - return Math.min( - 1000 + ((this.retryCount - 1) * 2000), - 10 * 1000 - ) + // 不用retryCount了,防止意外的连接成功,导致retryCount重置 + let interval = Math.min(1000 + ((this.totalRetryCount - 1) * 2000), 20 * 1000) + // 加上随机延迟,防止同时请求导致雪崩 + interval += Math.random() * 3000 + return interval } onWsMessage(event) { diff --git a/frontend/src/api/chat/ChatClientRelay.js b/frontend/src/api/chat/ChatClientRelay.js index 479c0fa..cea9886 100644 --- a/frontend/src/api/chat/ChatClientRelay.js +++ b/frontend/src/api/chat/ChatClientRelay.js @@ -25,6 +25,7 @@ export default class ChatClientRelay { this.websocket = null this.retryCount = 0 + this.totalRetryCount = 0 this.isDestroying = false this.receiveTimeoutTimerId = null } @@ -92,15 +93,18 @@ export default class ChatClientRelay { if (this.isDestroying) { return } - console.warn(`掉线重连中${++this.retryCount}`) + this.retryCount++ + this.totalRetryCount++ + console.warn(`掉线重连中 retryCount=${this.retryCount}, totalRetryCount=${this.totalRetryCount}`) window.setTimeout(this.wsConnect.bind(this), this.getReconnectInterval()) } getReconnectInterval() { - return Math.min( - 1000 + ((this.retryCount - 1) * 2000), - 10 * 1000 - ) + // 不用retryCount了,防止意外的连接成功,导致retryCount重置 + let interval = Math.min(1000 + ((this.totalRetryCount - 1) * 2000), 20 * 1000) + // 加上随机延迟,防止同时请求导致雪崩 + interval += Math.random() * 3000 + return interval } onWsMessage(event) { diff --git a/frontend/src/views/Room.vue b/frontend/src/views/Room.vue index 2cb9959..b1e48a0 100644 --- a/frontend/src/views/Room.vue +++ b/frontend/src/views/Room.vue @@ -76,7 +76,12 @@ export default { }, mounted() { if (document.visibilityState === 'visible') { - this.init() + if (this.roomKeyValue === null) { + this.init() + } else { + // 正式房间要随机延迟加载,防止同时请求导致雪崩 + window.setTimeout(this.init, Math.random() * 3000) + } } else { // 当前窗口不可见,延迟到可见时加载,防止OBS中一次并发太多请求(OBS中浏览器不可见时也会加载网页,除非显式设置) document.addEventListener('visibilitychange', this.onVisibilityChange) @@ -496,7 +501,7 @@ export default { // 获取失败了默认为0 img.onerror = resolve // 超时保底 - setTimeout(resolve, 5000) + window.setTimeout(resolve, 5000) img.src = urlInClosure } )) diff --git a/services/chat.py b/services/chat.py index f164e6e..7ff6429 100644 --- a/services/chat.py +++ b/services/chat.py @@ -2,6 +2,7 @@ import asyncio import enum import logging +import random import uuid from typing import * @@ -10,7 +11,6 @@ import api.open_live as api_open_live import blivedm.blivedm as blivedm import blivedm.blivedm.models.open_live as dm_open_models import blivedm.blivedm.models.web as dm_web_models -import blivedm.blivedm.utils as dm_utils import config import services.avatar import services.translate @@ -114,7 +114,12 @@ class LiveClientManager: client_room_manager.del_room(room_key) -RECONNECT_POLICY = dm_utils.make_linear_retry_policy(1, 2, 10) +def _get_reconnect_interval(_retry_count: int, total_retry_count: int): + # 不用retry_count了,防止意外的连接成功,导致retry_count重置 + interval = min(1 + (total_retry_count - 1) * 2, 20) + # 加上随机延迟,防止同时请求导致雪崩 + interval += random.uniform(0, 3) + return interval class WebLiveClient(blivedm.BLiveClient): @@ -128,7 +133,7 @@ class WebLiveClient(blivedm.BLiveClient): session=utils.request.http_session, heartbeat_interval=self.HEARTBEAT_INTERVAL, ) - self.set_reconnect_policy(RECONNECT_POLICY) + self.set_reconnect_policy(_get_reconnect_interval) @property def room_key(self): @@ -158,7 +163,7 @@ class OpenLiveClient(blivedm.OpenLiveClient): session=utils.request.http_session, heartbeat_interval=self.HEARTBEAT_INTERVAL, ) - self.set_reconnect_policy(RECONNECT_POLICY) + self.set_reconnect_policy(_get_reconnect_interval) @property def room_key(self):