feat: 提升并发容量默认配置
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""raise the default chat concurrency to thirty
|
||||
|
||||
Revision ID: 0028_chat_concurrency
|
||||
Revises: 0027_content_generation
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = "0028_chat_concurrency"
|
||||
down_revision = "0027_content_generation"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
config = sa.table(
|
||||
"sys_system_config",
|
||||
sa.column("config_key", sa.String(length=100)),
|
||||
sa.column("config_value", sa.Text()),
|
||||
sa.column("description", sa.String(length=255)),
|
||||
)
|
||||
connection = op.get_bind()
|
||||
_set_default(
|
||||
connection,
|
||||
config,
|
||||
key="chat_max_active_requests",
|
||||
old_default="2",
|
||||
new_default="30",
|
||||
description="用户正式问答的全局执行上限;Redis 可用时由所有后端实例共享,超过后进入排队。",
|
||||
)
|
||||
_set_default(
|
||||
connection,
|
||||
config,
|
||||
key="chat_max_queue_size",
|
||||
old_default="20",
|
||||
new_default="90",
|
||||
description="超过最大并发后允许等待的请求数量。默认按并发数的 3 倍预留。",
|
||||
)
|
||||
_set_default(
|
||||
connection,
|
||||
config,
|
||||
key="chat_queue_timeout_seconds",
|
||||
old_default="60",
|
||||
new_default="90",
|
||||
description="请求在排队中超过该时间后自动结束。默认可覆盖约三轮请求释放。",
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# 运行时配置可能已经被管理员调整,降级代码版本时不覆盖现场值。
|
||||
pass
|
||||
|
||||
|
||||
def _set_default(
|
||||
connection,
|
||||
config,
|
||||
*,
|
||||
key: str,
|
||||
old_default: str,
|
||||
new_default: str,
|
||||
description: str,
|
||||
) -> None:
|
||||
current = connection.execute(
|
||||
sa.select(config.c.config_value).where(config.c.config_key == key)
|
||||
).scalar_one_or_none()
|
||||
if current is None:
|
||||
connection.execute(
|
||||
config.insert().values(
|
||||
config_key=key,
|
||||
config_value=new_default,
|
||||
description=description,
|
||||
)
|
||||
)
|
||||
return
|
||||
if str(current).strip() == old_default:
|
||||
connection.execute(
|
||||
config.update()
|
||||
.where(config.c.config_key == key)
|
||||
.values(config_value=new_default, description=description)
|
||||
)
|
||||
@@ -59,9 +59,9 @@ class Settings(BaseSettings):
|
||||
|
||||
default_daily_chat_limit: int = 100
|
||||
default_user_name_prefix: str = "用户"
|
||||
chat_max_active_requests: int = 2
|
||||
chat_max_queue_size: int = 20
|
||||
chat_queue_timeout_seconds: int = 60
|
||||
chat_max_active_requests: int = 30
|
||||
chat_max_queue_size: int = 90
|
||||
chat_queue_timeout_seconds: int = 90
|
||||
chat_active_lease_seconds: int = 900
|
||||
periodic_report_worker_enabled: bool = True
|
||||
periodic_report_poll_seconds: int = 5
|
||||
|
||||
@@ -27,6 +27,7 @@ from app.services.security_state_service import SecurityStateService
|
||||
from app.services.auth_service import AuthService
|
||||
from app.services.model_service import ModelClientService
|
||||
from app.core.observability import RequestObservabilityMiddleware
|
||||
from app.core.config import Settings
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -43,6 +44,14 @@ def test_secret_is_encrypted_and_masked():
|
||||
assert SecretService.masked(encrypted) == MASKED_SECRET
|
||||
|
||||
|
||||
def test_production_chat_capacity_defaults_cover_expected_burst():
|
||||
settings = Settings(_env_file=None)
|
||||
|
||||
assert settings.chat_max_active_requests == 30
|
||||
assert settings.chat_max_queue_size == 90
|
||||
assert settings.chat_queue_timeout_seconds == 90
|
||||
|
||||
|
||||
def test_migration_revision_ids_fit_default_alembic_version_column():
|
||||
versions_dir = Path(__file__).parents[1] / "alembic" / "versions"
|
||||
revision_pattern = re.compile(r'^revision\s*=\s*["\']([^"\']+)', re.MULTILINE)
|
||||
|
||||
Reference in New Issue
Block a user