Files
pd-guard/compose.yaml
T
Максименко Никита Владимирович 6afe3442f2 fix: устойчивость Redis-кластера под нагрузкой и код-ревью замечания
Redis timeout 200ms давал ложные срабатывания под пиковой нагрузкой на общем
хосте — подняли до 800ms и добавили cpu/mem лимиты сервисам в compose, чтобы
соседи не выедали CPU у Redis. Добавили метрику и WARN на случай, когда
демаскирование не находит соответствие ни по id, ни по отпечатку маски (раньше
тихо превращалось в повторное маскирование без единого следа в логах).

Кластерные узлы (node-a/node-b) получили обе NER-модели (WikiNEuRal для имён,
ruBERT для адресов) — раньше конфиг ссылался на несуществующие свойства и
вторая ступень молча не работала. lb (nginx) и volume для prometheus/grafana
данных зафиксированы в compose.

Плюс код-ревью фиксы: утечка нативных ONNX-ресурсов при ошибке загрузки модели
(BLOCKER), неверный HTTP-статус при сбое обработки, generic Exception в
LlmClient заменён на конкретные, лишние same-package импорты убраны.
2026-09-22 21:40:18 +03:00

114 lines
4.9 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `docker compose up` поднимает кластер целиком: redis, node-a, node-b за
# nginx-балансировщиком на 8080, плюс Prometheus на 9090 и Grafana на 3000.
#
# Маскирование детерминировано и работает на любом узле, а вот обратный шаг
# требует общего состояния — отсюда общий Redis между node-a и node-b.
#
# Лимиты CPU/RAM: сервер — 4 vCPU. Без лимитов node-a/node-b/prometheus/grafana
# под нагрузкой отжимали CPU у Redis, тот не укладывался в таймаут команд, узлы
# теряли общее состояние и демаскирование съезжало на резервный путь. Лимиты —
# это потолок (docker compose без swarm не умеет в гарантированные reservations),
# но они не дают соседям выесть Redis подчистую.
services:
prometheus:
image: prom/prometheus:v2.54.1
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=6h
- --web.enable-lifecycle
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
cpus: 0.5
mem_limit: 512m
grafana:
image: grafana/grafana:11.2.0
ports:
- "3000:3000"
environment:
# Демонстрационный стенд: вход без пароля, чтобы жюри не искало учётные данные.
# Для контура с реальными данными это надо снять.
GF_AUTH_ANONYMOUS_ENABLED: "true"
GF_AUTH_ANONYMOUS_ORG_ROLE: Admin
GF_AUTH_DISABLE_LOGIN_FORM: "true"
GF_USERS_DEFAULT_THEME: light
# Сразу открывать дашборд модуля, а не пустую главную.
GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH: /var/lib/grafana/dashboards/pd-guard.json
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro
- grafana-data:/var/lib/grafana
cpus: 0.3
mem_limit: 512m
redis:
image: redis:7-alpine
command: ["redis-server", "--save", "", "--appendonly", "no", "--maxmemory", "1gb", "--maxmemory-policy", "allkeys-lru"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 2s
retries: 5
cpus: 1.0
mem_limit: 1200m
node-a: &node
image: pd-guard-spring:jvm
cpus: 1.0
mem_limit: 2200m
environment:
PDGUARD_STORE_BACKEND: redis
SPRING_DATA_REDIS_HOST: redis
PDGUARD_MAX_CONCURRENT: "2000"
PDGUARD_WARMUP_ITERATIONS: "2000"
# Вторая ступень распознавания — две модели под разные задачи (см.
# NameCascade.java): WikiNEuRal размечает имена, ruBERT — составляющие
# адреса. Модели в репозиторий не входят: ./tools/fetch-ner-model.sh.
# Пока движок не задан, соответствующая часть ступени выключена и
# сервис работает на одних правилах.
PDGUARD_NER_NAME_ENGINE: wikineural
PDGUARD_NER_NAME_MODEL: /deployments/models/wikineural-ner
PDGUARD_NER_ADDRESS_ENGINE: rubert
PDGUARD_NER_ADDRESS_MODEL: /deployments/models/rubert-ner
# ВРЕМЕННО для разового разбора формата тестовых payload'ов — пишет сырые ПД
# в логи узла. LOGGING_LEVEL_* не подходит: relaxed binding из env приводит
# имя логгера к нижнему регистру и не совпадает с ru.pdguard.core.Pipeline
# (заглавная P), поэтому уровень задан через -D, где регистр сохраняется.
# Выключить (убрать переменную) перед официальным нагрузочным прогоном.
JAVA_OPTS: "-Dspring.config.additional-location=optional:file:/deployments/config/ -Dlogging.level.ru.pdguard.core.Pipeline=DEBUG"
volumes:
- ./config:/deployments/config:ro
- ./models:/deployments/models:ro
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
interval: 10s
timeout: 2s
retries: 3
node-b:
<<: *node
lb:
image: nginx:1.27-alpine
cpus: 0.3
mem_limit: 128m
ports:
- "8080:80"
volumes:
- ./nginx/lb.conf:/etc/nginx/nginx.conf:ro
depends_on:
node-a:
condition: service_healthy
node-b:
condition: service_healthy
volumes:
prometheus-data:
grafana-data: