← Production Mastery
🏠 Главная 📚 Все курсы 🎯 RVV proof 📊 Paper proof

Урок 9 — Multi-bot architecture

Урок 9 из 10 · Production Mastery

🟢 Не теория — наш живой бот: RVV Hunter MTF работает прямо сейчас (WR 66%, +$141 за 15 дней). Всё что в этом уроке — настроено на нашей боевой системе.

Урок 9: Multi-bot architecture: как держать несколько ботов на одном VPS

Длительность: ~30 минут

Контекст: Поздравляю! Ваш первый торговый бот уже работает в production. Вы настроили Docker, мониторинг, бэкапы и CI/CD. Он стабильно работает и, надеемся, приносит прибыль. Но рынок не стоит на месте, и у вас появилась новая идея — новая стратегия для другой торговой пары. Что делать? Покупать второй VPS? Удваивать расходы? Нет. Давайте поступим умнее и научимся размещать несколько ботов на одной машине, экономя деньги и не теряя в стабильности.


⏱️ + 📖 Быстрый словарь

Прежде чем мы погрузимся в детали, давайте определим несколько понятий простыми словами. Это наша основа.


❌ До / ✅ После

Вот как меняется наш подход:

❌ ДО (Дорого и неэффективно):

VPS_1 (€10/мес)
└── Бот_BTC
└── Postgres
└── Grafana

VPS_2 (€10/мес) - ???
└── Бот_ETH
└── Postgres
└── Grafana

ИТОГО: ~€20/мес
    

✅ ПОСЛЕ (Экономно и централизованно):

VPS_1 (€10/мес)
├── Бот_BTC (свой контейнер)
├── Бот_ETH (свой контейнер)
│
└── Общая инфраструктура
    ├── Postgres (общая база)
    └── Grafana (общий мониторинг)

ИТОГО: ~€10/мес
    

История: Боль одного трейдера

Давайте назовем нашего студента Алексеем. Его бот, торгующий парой BTC/USDT, уже три месяца стабильно работает на небольшом VPS. Алексей доволен. За это время он разработал и протестировал новую стратегию для ETH/USDT. Она выглядит еще более многообещающей.

И вот он стоит перед выбором. "Я хочу запустить второго бота, — думает Алексей, — но я боюсь. Что если они начнут конфликтовать? Вдруг новый бот 'съест' всю память, и мой старый, проверенный BTC-бот упадет в самый ответственный момент? А что если они как-то перезапишут данные друг друга в базе данных? Покупать второй VPS — это значит удвоить расходы на инфраструктуру. Я хочу реинвестировать прибыль в торговлю, а не в железо".

Эта боль абсолютно реальна. Без правильного подхода два бота на одной машине могут превратиться в двух пауков в одной банке. Наша задача — сделать из них дружных соседей по коммунальной квартире, где у каждого своя комната, но кухня и ванная — общие.


Часть 1: Принципы — что разделять, а что использовать совместно?

Это ключевой "Ага!"-момент. Секрет не в том, чтобы изолировать всё, а в том, чтобы грамотно разделить зоны ответственности.

✅ Что должно быть своим у каждого бота:

🤝 Что может (и должно) быть общим:


Часть 2: Собираем всё в docker-compose.yml

Теперь превратим наши принципы в код. Возьмем ваш существующий docker-compose.yml для одного бота и расширим его для второго.

Основное изменение: в секции services у нас теперь будет не один бот, а два — bot_btc и bot_eth. Каждый со своим env_file.


# docker-compose.yml

version: '3.8'

services:
  # ==================================================
  # Первый бот: BTC/USDT
  # ==================================================
  bot_btc:
    container_name: bot_btc
    build:
      context: ./bots/btc_bot # Указываем путь к Dockerfile и коду первого бота
    env_file:
      - ./bots/btc_bot/.env   # У него свой файл с настройками
    restart: unless-stopped
    depends_on:
      - postgres
    networks:
      - backend

  # ==================================================
  # Второй бот: ETH/USDT
  # ==================================================
  bot_eth:
    container_name: bot_eth
    build:
      context: ./bots/eth_bot # Указываем путь к Dockerfile и коду второго бота
    env_file:
      - ./bots/eth_bot/.env   # И у него свой файл с настройками
    restart: unless-stopped
    depends_on:
      - postgres
    networks:
      - backend

  # ==================================================
  # Общая инфраструктура
  # ==================================================
  postgres:
    container_name: postgres
    image: postgres:14-alpine
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: trading_bots
    ports:
      - "5432:5432" # Пробрасываем порт для удобства подключения извне (например, DBeaver)
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - backend

  grafana:
    container_name: grafana
    image: grafana/grafana:latest
    ports:
      - "3000:3000" # Пробрасываем порт для доступа к веб-интерфейсу
    volumes:
      - grafana_data:/var/lib/grafana
    restart: unless-stopped
    networks:
      - backend

# ==================================================
# Настройки сетей и volumes
# ==================================================
volumes:
  postgres_data:
  grafana_data:

networks:
  backend:
    driver: bridge

Теперь, когда вы запустите docker-compose up -d, Docker поднимет оба бота и общую инфраструктуру. Каждый бот будет использовать свои настройки из своего .env файла, но оба будут подключаться к одной и той же базе данных postgres по адресу host=postgres.


Часть 3: Устанавливаем лимиты ресурсов (Resource Limits)

Чтобы один бот не "съел" всю память и процессор, добавим ограничения. Это делается с помощью ключа deploy. Он гарантирует, что даже если в коде бота есть утечка памяти, она не затронет соседа и всю систему.

Добавим этот блок в описание сервисов bot_btc и bot_eth в нашем docker-compose.yml:


# ... фрагмент docker-compose.yml для одного из ботов ...
  bot_btc:
    # ... все предыдущие настройки ...
    deploy:
      resources:
        limits:
          cpus: '0.50' # Может использовать не более 50% одного ядра CPU
          memory: '512M' # Может использовать не более 512 MB RAM
        reservations:
          cpus: '0.25' # Гарантированно получит 25% одного ядра CPU
          memory: '256M' # Гарантированно получит 256 MB RAM

Важно: ключ deploy работает в "swarm mode" или при использовании docker stack deploy. Если вы используете простой docker-compose up, для версий compose файла до 3.x и Docker Engine до 19.03 эти лимиты могут не применяться. В современных версиях Docker Compose V2 это работает "из коробки". Это страховка от плохого поведения одного из ваших приложений.


Часть 4: Изоляция сетей (Network Isolation)

В нашем примере выше мы уже использовали базовую изоляцию, создав сеть backend. Все сервисы находятся в ней и могут общаться друг с другом по именам (bot_btc может достучаться до postgres). Никто извне не может подключиться к нашей базе данных, кроме тех сервисов, чьи порты мы явно "пробросили" (Grafana и Postgres).

Для еще большей безопасности можно создать несколько сетей. Например, frontend для сервисов, смотрящих наружу (Grafana), и backend для внутренней кухни (боты и база данных).


Часть 5: Разделяем логи

По умолчанию Docker пишет логи всех контейнеров в один общий поток. Это неудобно. Давайте настроим запись логов каждого бота в свой отдельный файл на сервере.

Добавим секцию logging в описание сервисов ботов:


# ... фрагмент docker-compose.yml для одного из ботов ...
  bot_btc:
    # ... все предыдущие настройки ...
    logging:
      driver: "json-file"
      options:
        max-size: "10m"   # Максимальный размер лог-файла 10 MB
        max-file: "3"     # Хранить 3 последних лог-файла (ротация)
        # Путь к файлу логов на хост-машине. Убедитесь, что директория существует.
        path: "/var/log/docker/bot_btc.log"

Сделайте то же самое для bot_eth, указав другой путь, например, /var/log/docker/bot_eth.log. Теперь, если BTC-бот упадет, вам нужно будет смотреть только один маленький и чистый файл логов, а не продираться через сообщения от всех сервисов сразу.


Часть 6: Настраиваем дашборды в Grafana

Ваш сервер Grafana уже работает. Зайдите в него по адресу http://your_vps_ip:3000. Ваша задача проста:

  1. Убедитесь, что у вас настроен Data Source для подключения к вашей общей базе postgres.
  2. Создайте новый дашборд и назовите его "BTC Bot Performance". Настройте панели, используя SQL-запросы, которые выбирают данные только по этому боту (например, SELECT * FROM trades WHERE bot_name = 'btc').
  3. Скопируйте этот дашборд (Save As...), назовите копию "ETH Bot Performance" и просто измените в запросах 'btc' на 'eth'.

Готово! У вас есть раздельный, наглядный мониторинг для каждого из ваших активов.


Часть 7: Реальный пример — 6 ботов на одной машине

Думаете, два бота — это предел? Это только начало. Чтобы доказать, что этот подход работает в реальном мире, вот пример из нашей собственной инфраструктуры проекта NEXUS.

На одном-единственном сервере Hetzner CX22 (2 vCPU, 4 GB RAM) стоимостью всего €4.79 в месяц у нас одновременно работают:

И все это работает стабильно, с разделением ресурсов, логов и конфигураций по тем же самым принципам, которые мы только что рассмотрели. Экономия очевидна.


Клиффхэнгер: Следующий уровень проблем

Поздравляю! Ваши боты работают в гармонии, экономят вам деньги и приносят прибыль. Вы — настоящий хозяин своей инфраструктуры.

Но... проходит неделя, и вы замечаете странное. Раз в несколько дней один из ботов на пару минут падает. Docker его автоматически перезапускает, и он работает дальше. В логах, которые вы настроили, пусто — ошибка происходит так быстро, что вы не успеваете ее "поймать". Что это было? Кратковременный скачок нагрузки? Проблема с сетью? Ошибка в коде, которая проявляется раз в 100 000 сделок?

Как поймать ошибку, которая живет всего 5 секунд? Как анализировать поведение всей системы целиком, а не только отдельных ее частей?

Для этого нам нужен "черный ящик" для наших сервисов. Система, которая собирает ВСЕ логи от ВСЕХ ботов и сервисов в одном месте, индексирует их и позволяет делать поиск в реальном времени. Это следующий шаг к настоящему Production Mastery.

В следующем уроке мы подключим Loki...


Перейти к Уроку 10: Централизованное логирование с Loki и Promtail [tokens: in=446 out=4148 thinking=2725 | cost=$0.0693]

Хочешь больше? Полный курс AI Agents включает Production-модуль + 27 других уроков

AI Agents $199 →