From 95d2903766deb19bfd84352d986d2dcd17a37d66 Mon Sep 17 00:00:00 2001 From: jze9 Date: Thu, 27 Aug 2026 16:54:26 +0500 Subject: [PATCH] =?UTF-8?q?docs(DR-HA):=20=D0=B7=D0=B0=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D1=80=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=20RabbitMQ=20consumer=5Ftimeout=20+=20Infisical=20?= =?UTF-8?q?failover?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Обнаруженный на практике 26.08 краш-луп (долгий retry в Celery-таске дольше 1800с consumer_timeout → брокер рвёт канал → падение → бесконечный повтор) стоит знать при добавлении новых долгих retry-циклов. Заодно поправлена инструкция failover PostgreSQL — POSTGRES_HOST теперь меняется в Infisical, не в .env на сервере (перезапишется следующим деплоем). --- docs/DR-HA.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/DR-HA.md b/docs/DR-HA.md index 30fcb08..d6cf033 100644 --- a/docs/DR-HA.md +++ b/docs/DR-HA.md @@ -30,7 +30,9 @@ bash scripts/ops/pg_restore_verify.sh # креды из .env 2. **Replica**: `pg_basebackup -h 1.38 -U replicator -D $PGDATA -R` (создаёт `standby.signal` + `primary_conninfo`), затем старт — догоняет primary по WAL. 3. **Failover**: ручной `pg_ctl promote` на реплике + переключение `POSTGRES_HOST` - в `.env` (или автоматизация через Patroni + etcd — если нужен авто-failover). + в Infisical (окружение `prod` — не в `.env` на сервере напрямую, его перезапишет + следующий деплой, см. ARCHITECTURE.md §10) и передеплой/рестарт сервисов + (или автоматизация через Patroni + etcd — если нужен авто-failover). 4. Проверка лага: `SELECT * FROM pg_stat_replication` на primary. ## 4. HA Redis — реплика + Sentinel (требует новый LXC) @@ -53,3 +55,19 @@ Redis у нас — кэш/rate-limits/LSH-индекс (префикс `antipla | Векторный индекс | было | `VECTOR_BACKEND=qdrant` снимает (см. README) ✅ | | RabbitMQ .82 | да | мониторинг ловит падение ✅; кластер — по потребности | | app/ES 1.32 | да | воркеры горизонтальны; ES single-node (для BM25 не критично) | + +## 6. Известный операционный риск — RabbitMQ `consumer_timeout` vs долгие таски + +Обнаружено на практике (2026-08-26): RabbitMQ по умолчанию рвёт канал, если consumer +не сделал ack за 1800с. Любой Celery-таск с retry-логикой (rate-limit backoff у +парсеров, ожидание зависшего внешнего сервиса вроде Ollama), суммарно занимающий +дольше — брокер обрывает соединение раньше, чем таск успевает сдаться и +подтвердиться, весь Celery-процесс падает (`exitCode=1`), Docker +(`restart: unless-stopped`) поднимает его заново, недоставленное сообщение +передоставляется — и цикл повторяется бесконечно, монополизируя весь пул воркера +(было и на `worker-indexer` из-за backoff `scripts/parsers/openalex.py`, и на +`worker-gpu` из-за зависшей Ollama на embedding-gpu). Текущая митигация — держать +retry-бэкоффы заведомо короче 1800с (пример: `MAX_RATE_LIMIT_RETRIES` в +`openalex.py`). Более глубокий фикс — поднять `consumer_timeout` на самом RabbitMQ +(доступа для этого пока не заводили) — актуально при добавлении любых новых +долгих retry-циклов в Celery-тасках.