MAATRIX / Блог / Сколько RAM нужно для Zulip

Сколько RAM нужно для Zulip

MAATRIX

Zulip выбирают за тредовую модель обсуждений — топики внутри каналов вместо одной бесконечной ленты, как в Slack или Rocket.Chat. Но при развёртывании быстро выясняется, что это не «ещё один чат на Node.js»: под капотом Django, Tornado, PostgreSQL, RabbitMQ, Redis и Memcached одновременно, и официальный минимум в документации не всегда совпадает с тем, что происходит на реальном сервере. Разберём, из чего складывается потребление RAM в Zulip и сколько закладывать под конкретный размер команды.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Из чего состоит Zulip и почему память нужно считать по частям

Zulip — это не один процесс, а связка сервисов, которые вместе поднимает установочный скрипт (или docker-zulip):

  • Django-приложение через uwsgi — обрабатывает HTTP-запросы: логин, отправку сообщений, API, вебхуки от интеграций. Число uwsgi-воркеров Zulip подбирает исходя из количества ядер CPU на сервере, и каждый воркер — это отдельный процесс со своим куском памяти.
  • Tornado — отдельный процесс для realtime-доставки: именно он держит долгоживущие соединения и рассылает новые сообщения в браузер без перезагрузки страницы. При росте числа одновременно открытых вкладок это один из самых заметных потребителей RAM.
  • PostgreSQL — хранит сообщения, топики, реакции, права доступа, полнотекстовый индекс для поиска. Отдельный процесс с собственным бюджетом памяти, который нельзя вычесть из «памяти Zulip» — его нужно считать сверху.
  • RabbitMQ — брокер очередей, через который проходят все фоновые задачи: отправка email-уведомлений, digest-рассылки, обработка входящих писем в email-mirror, вебхуки, индексация для поиска. Под RabbitMQ поднимается порядка полутора-двух десятков отдельных воркер-процессов (deferred_work, missedmessage_emails, embed_links, outgoing_webhooks, digest_emails и другие — точный список worker'ов немного отличается между версиями), и каждый из них — это свой процесс под управлением supervisor, а не бесплатная абстракция.
  • Redis — используется для rate limiting и части сессионных данных, памяти ест немного, но должен быть в бюджете.
  • Memcached — кэширует часто запрашиваемые объекты (пользователей, каналы, права), заметно снижает нагрузку на PostgreSQL, но сам держит выделенный кусок RAM под кэш.
  • nginx — фронтует всё это, отдаёт статику, на память почти не влияет.

Итог: даже пустой Zulip без единого пользователя уже держит в памяти десяток-другой процессов, потому что архитектура рассчитана на масштабирование, а не на минимальный footprint. Это плата за то, что каждый компонент (очереди, кэш, realtime) можно потом вынести на отдельный сервер, если организация вырастет.

Официальный минимум и что происходит с ним на практике

В документации Zulip минимальные требования для продакшен-инсталляции обычно формулируются как «около 2 vCPU и 4 GB RAM» — это цифра, рассчитанная на небольшую организацию с несколькими десятками активных пользователей и без экзотической нагрузки вроде массового импорта истории из Slack. Здесь важны две оговорки:

  1. Это минимум для старта, а не гарантия комфортной работы под нагрузкой — на 4 GB всё поднимется и будет работать, но запас памяти под пики (импорт истории, много одновременных загрузок файлов, всплеск активности в момент онбординга новой команды) будет минимальным.
  2. Официальные цифры ориентированы на определённый диапазон пользователей и с ростом организации требования растут не линейно, а скачками — сначала за счёт числа воркеров и подключений, потом за счёт роста самой базы данных.

На практике для тестового стенда или совсем маленькой команды (5-15 человек) можно уложиться и в 4 GB, но с почти нулевым запасом — если параллельно на этом же сервере крутится что-то ещё, лучше сразу закладывать больше. Актуальные минимальные требования стоит сверить с документацией вашей версии Zulip перед покупкой сервера — они периодически уточняются разработчиками.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Сколько RAM нужно по размеру организации

Точная цифра зависит не столько от числа зарегистрированных аккаунтов, сколько от того, сколько людей одновременно онлайн и насколько активно используются треды, реакции и интеграции. Ниже — ориентировочная вилка для типового сценария «рабочий чат команды», без агрессивного использования ботов и вебхуков:

Размер организацииОбычно онлайн одновременноRAM: Zulip (Django + Tornado + очереди)RAM: PostgreSQLИтого, ориентир
до 20 человек~5-102-3 GB1 GB4 GB
20-100 человек~15-403-4 GB1-2 GB6-8 GB
100-500 человек~50-2004-6 GB2-4 GB8-16 GB
500-1500 человек~200-6006-10 GB4-8 GB16-24 GB, стоит разносить БД отдельно
1500+ человек600+горизонтальное масштабированиеотдельный сервер БД, репликисчитается индивидуально

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

Для команды до 100-150 человек обычно достаточно одного VPS, где Zulip и PostgreSQL живут на одной машине — выносить базу на отдельный сервер на этом масштабе избыточно и только добавляет сетевую задержку на каждый запрос.

PostgreSQL, RabbitMQ и Memcached — где реально расходуется память

Дефолтные настройки PostgreSQL из коробки (shared_buffers в районе 128 MB) рассчитаны на слабое железо и на живой нагрузке будут ограничивать скорость поиска по истории сообщений. Базовые ориентиры для тюнинга, если под PostgreSQL выделено, например, 4 GB RAM:

# postgresql.conf, при 4 GB, отданных под Postgres
shared_buffers = 1GB          # обычно 25% от памяти, выделенной под Postgres
effective_cache_size = 3GB    # 50-75% от RAM — подсказка планировщику запросов
work_mem = 16MB                 # осторожнее увеличивать при большом max_connections
maintenance_work_mem = 256MB
max_connections = 100

Здесь та же ловушка, что и в любой другой связке с PostgreSQL: work_mem расходуется на каждую операцию сортировки или хеширования отдельно, а не выделяется один раз, и при большом числе одновременных подключений с завышенным work_mem легко упереться в OOM именно в момент пиковой активности — например, когда несколько человек одновременно ищут по истории. Подробный разбор параметров и типичных ошибок — в статье про тюнинг PostgreSQL на сервере; если PostgreSQL под Zulip разворачивается впервые — базовая установка описана в статье как установить и настроить PostgreSQL на VPS.

RabbitMQ по умолчанию начинает применять давление на память (memory alarm) при достижении определённой доли доступной RAM, и на маленьких серверах это может неожиданно поставить очереди на паузу под нагрузкой — если фоновые задачи (например, отправка email-уведомлений) зависают на пике активности, в первую очередь стоит проверить именно memory watermark в конфигурации RabbitMQ, а не список задач. Memcached работает предсказуемее — размер кэша задаётся явно и не растёт сверх лимита, но заниженный лимит означает больше промахов кэша и больше нагрузки на PostgreSQL, так что урезать его до пары десятков мегабайт ради экономии RAM не стоит.

Puppet-инсталлятор против Docker — разница в накладных расходах

Zulip официально ставится через собственный установочный скрипт на базе Puppet прямо на сервер (Ubuntu/Debian), а есть и неофициальный, поддерживаемый сообществом вариант через docker-zulip. Разница по памяти не в самих компонентах — Django, PostgreSQL, RabbitMQ работают одинаково в обоих случаях, — а в накладных расходах вокруг них:

  • Нативная установка через Puppet-скрипт разворачивает все сервисы напрямую на хост-системе под управлением supervisor. Накладные расходы минимальны, но обновления и откат версий менее прозрачны — при проблеме сложнее откатиться на предыдущее состояние одной командой.
  • Docker-инсталляция добавляет слой контейнеризации (обычно несколько контейнеров: сам Zulip, PostgreSQL, RabbitMQ, Memcached), что даёт сотни мегабайт накладных расходов на изоляцию и упрощает бэкапы и откат версий через volumes, но требует более внимательного контроля лимитов памяти на каждый контейнер, иначе один разросшийся контейнер может задушить соседей через файловый кэш и swap хоста.

Для небольшой и средней организации разница на практике укладывается в несколько сотен мегабайт — не тот фактор, который должен определять выбор способа установки. Документация Zulip подробнее покрывает нативную установку, поэтому для первого self-hosted проекта такого рода разумнее начать с неё, а к контейнерам переходить, когда уже понятен профиль нагрузки команды.

Как проверить фактическое потребление и снизить нагрузку

Прежде чем апгрейдить сервер «на всякий случай», стоит посмотреть, что реально происходит на текущем железе:

# общая картина по памяти
free -h

# кто именно ест RAM — сортировка процессов по потреблению
ps aux --sort=-%mem | head -20

# статус всех сервисов Zulip под supervisor
sudo supervisorctl status

# если Zulip установлен через Docker — потребление по контейнерам
docker stats --no-stream

Если после установки при малой команде память всё равно уходит целиком, в первую очередь проверьте:

  • Число uwsgi-воркеров — Zulip подбирает его по количеству CPU на сервере, и на многоядерной, но памятью бедной машине это может оказаться избыточным для реального числа пользователей; уточняйте актуальные параметры конфигурации под вашу версию, они периодически меняют имена и расположение.
  • Лишние воркеры очередей, которые не нужны при вашем сценарии использования — например, обработка email-mirror, если входящая почта не подключена, всё равно держит процесс в памяти просто на случай, если функция включена.
  • Кэш файловой системы, который free -h показывает как «занято», но который ядро отдаст под реальные нужды при необходимости — это не повод паниковать и сразу апгрейдить сервер, если available в выводе free -h выглядит нормально.
  • Swap — небольшой своп (1-2 GB) на сервере с Zulip не страшен и сглаживает кратковременные пики, но если система реально ушла в активный своппинг на постоянной основе, а не эпизодически — это уже сигнал, что памяти не хватает, а не что-то настраивать не так. Общий разбор симптомов и решений — в статье что делать при нехватке RAM.

Если запускаете Zulip в Docker, дополнительно стоит явно выставить лимиты памяти на каждый контейнер в docker-compose.yml, а не полагаться на общий пул хоста — иначе при утечке или пике в одном контейнере может пострадать вся связка сразу. Базовые принципы разбора таких лимитов — в статье про Docker: лимиты CPU и памяти.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Хватит ли 2 GB RAM для тестового стенда Zulip?

Технически поднять получится, но с очень небольшим запасом — при первом же всплеске активности (несколько человек одновременно, импорт истории) велика вероятность OOM. Для честного теста лучше брать от 4 GB.

Сколько памяти добавляет каждый новый активный пользователь?

Линейной формулы нет — сильнее влияет не число аккаунтов, а сколько людей одновременно держат открытую вкладку (это Tornado и uwsgi-соединения) и как активно используются треды и реакции, а не сам факт регистрации.

Стоит ли сразу разносить PostgreSQL на отдельный сервер?

Для организаций до нескольких сотен человек — обычно нет, это лишняя сетевая задержка без ощутимой выгоды. Разносить имеет смысл, когда база данных сама по себе начинает конкурировать за ресурсы с остальными сервисами Zulip на одной машине.

Zulip есть в готовом Docker-образе — значит, он легче нативной установки?

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

Как понять, что пора апгрейдить сервер, а не тюнинговать конфиги?

Если после проверки лишних воркеров и настройки PostgreSQL память всё равно стабильно занята выше 85-90% в рабочие часы, а не только на коротких пиках — это уже сигнал к апгрейду, а не к дальнейшему тюнингу.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →