feat: fixwin限速支持设置窗口大小 (#791)

This commit is contained in:
RockChinQ 2024-05-26 10:29:10 +08:00
parent 910d0bfae1
commit d49cc9a7a3
4 changed files with 51 additions and 18 deletions

View File

@ -0,0 +1,29 @@
from __future__ import annotations
from .. import migration
@migration.migration_class("ad-fixwin-cfg-migration", 8)
class AdFixwinConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return isinstance(
self.ap.pipeline_cfg.data["rate-limit"]["fixwin"]["default"],
int
)
async def run(self):
"""执行迁移"""
for session_name in self.ap.pipeline_cfg.data["rate-limit"]["fixwin"]:
temp_dict = {
"window-size": 60,
"limit": self.ap.pipeline_cfg.data["rate-limit"]["fixwin"][session_name]
}
self.ap.pipeline_cfg.data["rate-limit"]["fixwin"][session_name] = temp_dict
await self.ap.pipeline_cfg.dump_config()

View File

@ -5,7 +5,7 @@ import importlib
from .. import stage, app from .. import stage, app
from ...config import migration from ...config import migration
from ...config.migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion from ...config.migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
from ...config.migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url from ...config.migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url, m008_ad_fixwin_config_migrate
@stage.stage_class("MigrationStage") @stage.stage_class("MigrationStage")

View File

@ -1,18 +1,15 @@
# 固定窗口算法
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import time import time
from .. import algo from .. import algo
# 固定窗口算法
class SessionContainer: class SessionContainer:
wait_lock: asyncio.Lock wait_lock: asyncio.Lock
records: dict[int, int] records: dict[int, int]
"""访问记录key为每分钟的起始时间戳value为访问次数""" """访问记录key为每窗口长度的起始时间戳value为访问次数"""
def __init__(self): def __init__(self):
self.wait_lock = asyncio.Lock() self.wait_lock = asyncio.Lock()
@ -47,30 +44,34 @@ class FixedWindowAlgo(algo.ReteLimitAlgo):
# 等待锁 # 等待锁
async with container.wait_lock: async with container.wait_lock:
# 获取窗口大小和限制
window_size = self.ap.pipeline_cfg.data['rate-limit']['fixwin']['default']['window-size']
limitation = self.ap.pipeline_cfg.data['rate-limit']['fixwin']['default']['limit']
if session_name in self.ap.pipeline_cfg.data['rate-limit']['fixwin']:
window_size = self.ap.pipeline_cfg.data['rate-limit']['fixwin'][session_name]['window-size']
limitation = self.ap.pipeline_cfg.data['rate-limit']['fixwin'][session_name]['limit']
# 获取当前时间戳 # 获取当前时间戳
now = int(time.time()) now = int(time.time())
# 获取当前分钟的起始时间戳 # 获取当前窗口的起始时间戳
now = now - now % 60 now = now - now % window_size
# 获取当前分钟的访问次数 # 获取当前窗口的访问次数
count = container.records.get(now, 0) count = container.records.get(now, 0)
limitation = self.ap.pipeline_cfg.data['rate-limit']['fixwin']['default']
if session_name in self.ap.pipeline_cfg.data['rate-limit']['fixwin']:
limitation = self.ap.pipeline_cfg.data['rate-limit']['fixwin'][session_name]
# 如果访问次数超过了限制 # 如果访问次数超过了限制
if count >= limitation: if count >= limitation:
if self.ap.pipeline_cfg.data['rate-limit']['strategy'] == 'drop': if self.ap.pipeline_cfg.data['rate-limit']['strategy'] == 'drop':
return False return False
elif self.ap.pipeline_cfg.data['rate-limit']['strategy'] == 'wait': elif self.ap.pipeline_cfg.data['rate-limit']['strategy'] == 'wait':
# 等待下一分钟 # 等待下一窗口
await asyncio.sleep(60 - time.time() % 60) await asyncio.sleep(window_size - time.time() % window_size)
now = int(time.time()) now = int(time.time())
now = now - now % 60 now = now - now % window_size
if now not in container.records: if now not in container.records:
container.records = {} container.records = {}

View File

@ -29,7 +29,10 @@
"strategy": "drop", "strategy": "drop",
"algo": "fixwin", "algo": "fixwin",
"fixwin": { "fixwin": {
"default": 60 "default": {
"window-size": 60,
"limit": 60
}
} }
} }
} }