From a9c3d2595c495ac832e47d73763963435c278932 Mon Sep 17 00:00:00 2001 From: SXP-Simon Date: Wed, 11 Mar 2026 23:11:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8F=90=E5=8D=87=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=9F=A7=E6=80=A7=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=94=B9=E7=94=A8?= =?UTF-8?q?=E5=8D=95=E8=B0=83=E6=97=B6=E9=92=9F=E5=B9=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E9=99=90=E6=B5=81=E9=87=8D=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 CircuitBreaker 计时器改为 time.monotonic(),规避系统时钟回滚风险 - 允许 GlobalRateLimiter 在运行时根据配置动态调整信号量并发数 - 增加限流器配置变更时的日志记录 --- src/utils/resilience.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils/resilience.py b/src/utils/resilience.py index 4d13dcb..a99b061 100644 --- a/src/utils/resilience.py +++ b/src/utils/resilience.py @@ -72,7 +72,7 @@ class CircuitBreaker: """ if self.state == self.STATE_OPEN: # 检查冷却时间是否已过,过则进入试探性的半开状态 - if time.time() - self.last_failure_time > self.recovery_timeout: + if time.monotonic() - self.last_failure_time > self.recovery_timeout: self._half_open_circuit() return True return False @@ -81,7 +81,7 @@ class CircuitBreaker: def _open_circuit(self) -> None: """动作:开启熔断""" self.state = self.STATE_OPEN - self.last_failure_time = time.time() + self.last_failure_time = time.monotonic() logger.warning( f"熔断器 CircuitBreaker[{self.name}] 已激活!将拦截请求 {self.recovery_timeout} 秒。" ) @@ -125,6 +125,14 @@ class GlobalRateLimiter: if cls._instance is None: cls._instance = cls() cls._semaphore = asyncio.Semaphore(max_concurrency) + elif ( + cls._semaphore is not None and cls._semaphore._value != max_concurrency # type: ignore + ): + # 如果请求的并发数发生变化,重新创建信号量 + logger.info( + f"GlobalRateLimiter 重新配置:{cls._semaphore._value} -> {max_concurrency}" + ) + cls._semaphore = asyncio.Semaphore(max_concurrency) return cls._instance @property