From 451c18e42b5986fe50359c134969e25d31bf7cd2 Mon Sep 17 00:00:00 2001 From: Max Ronzhin Date: Sun, 9 Aug 2026 01:06:15 +0300 Subject: [PATCH] =?UTF-8?q?fix(redis):=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20=D0=BF=D1=83?= =?UTF-8?q?=D0=BB=D0=B0=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D1=8F=D0=B2=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit redis-py 8 поставил дефолт `max_connections=100`, а у нас на этом пуле висят не только команды, но и долгоживущие pub/sub-подписки комнаты — по одной на каждого участника, пока он в конференции. Сотый участник на воркер выгребал пул, и WS-хендшейк падал уже на `hgetall` очереди рук с `MaxConnectionsError`. Второй потолок того же рода, что и пул БД, только этажом ниже. Воспроизведён локально: при 99 одновременных WS вход переставал работать; с `redis_max_connections=500` те же 120 подключений проходят без единой ошибки. Соединения создаются по мере надобности, поэтому сам по себе поднятый лимит ничего не стоит. --- backend/core/config.py | 14 ++++++++++++++ backend/core/redis.py | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/core/config.py b/backend/core/config.py index 48f96b6..d6c535a 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -38,6 +38,20 @@ class Settings(BaseSettings): # и показывает проблему, а не висит полминуты, делая вид, что всё живо. db_pool_timeout: int = 10 + # --- Пул соединений с Redis --- + # Считается по УЧАСТНИКАМ, а не по запросам: каждое WS-подключение комнаты + # (`api/chat.py`) держит собственное pub/sub-соединение всё время, пока + # человек сидит в конференции, — и берёт его из этого же пула, что и + # обычные команды. redis-py 8 поставил дефолт `max_connections=100` + # (раньше предел был условно бесконечным), поэтому сотый участник на + # воркер выгребал пул досуха и WS падал уже на `hgetall` очереди рук — + # воспроизведено локально при 99 одновременных подключениях. + # 500 — с запасом на инстанс, рассчитанный на пару сотен участников + # на воркер; соединения создаются по мере надобности, само по себе + # значение ничего не стоит. Потолок сверху — `maxclients` у Redis + # (дефолт 10000) на ВСЕ процессы вместе, включая Celery-воркеры. + redis_max_connections: int = 500 + # --- Версия инстанса (релиз v0.0.1) --- # install.sh копирует значение из файла `VERSION` (корень репозитория) в # `.env` при каждой установке/обновлении — здесь только чтение готового diff --git a/backend/core/redis.py b/backend/core/redis.py index c709fdc..bcd7a19 100644 --- a/backend/core/redis.py +++ b/backend/core/redis.py @@ -6,4 +6,11 @@ from core.config import get_settings settings = get_settings() -redis_client: Redis = Redis.from_url(settings.redis_url, decode_responses=True) +redis_client: Redis = Redis.from_url( + settings.redis_url, + decode_responses=True, + # Размер пула задаём явно: дефолт redis-py (100) рассчитан на команды, а у + # нас на нём же висят долгоживущие pub/sub-подписки комнаты — по одной на + # участника (см. `core/config.py`, `redis_max_connections`). + max_connections=settings.redis_max_connections, +)