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

Сколько RAM нужно для Nexus Repository

MAATRIX

Nexus Repository Manager — это Java-процесс, и типичная ошибка при выборе сервера под него — считать память по объёму хранимых артефактов: "у нас на диске 500 ГБ jar-ников, значит и RAM нужно много". На деле диск и оперативная память в Nexus почти не связаны: файлы лежат в blob store и памяти под себя не требуют, а вот метаданные — версии, checksums, индекс поиска, состояние очередей — живут в JVM heap и базе данных, и именно они определяют, сколько гигабайт закладывать под сервер. Разберём, из чего складывается потребление RAM у Nexus, какие цифры реалистичны для разных сценариев и как настроить heap, чтобы не ловить OutOfMemoryError на growing-репозитории.

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

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

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

Из чего состоит память Nexus: heap, off-heap, datastore и blob store

Nexus Repository (и OSS, и Pro) — это одна JVM плюс внешние хранилища вокруг неё:

  • JVM heap — здесь живёт сама логика приложения: обработка HTTP-запросов, прокси-кэширование, задачи очистки (cleanup policies), REST API. Настраивается через -Xms/-Xmx.
  • Off-heap / direct memory — используется для сетевого ввода-вывода (NIO buffers) и части кэшей. Задаётся отдельно через -XX:MaxDirectMemorySize и в сумме с heap даёт реальный "аппетит" процесса.
  • Datastore (метаданные) — раньше Nexus 3 хранил метаданные во встроенной OrientDB прямо внутри процесса, что было источником немалой доли проблем с памятью и коррупции при OOM. Актуальные версии используют новый datastore на базе SQL: для небольших инсталляций это встроенный H2 (тоже часть процесса Nexus, тоже требует heap), для серьёзного продакшена — внешний PostgreSQL, который живёт своим процессом и своей памятью, разгружая JVM Nexus.
  • Blob store — собственно файлы артефактов на диске (или в S3-совместимом хранилище). Сама запись/чтение блоба почти не грузит heap, но активно использует файловый кэш ОС — поэтому больше свободной RAM всё равно ускоряет отдачу популярных артефактов, просто это не heap-память.

Итог: сервер под Nexus нужно считать как сумму heap JVM + запас под datastore (если он встроенный) + системный overhead ОС + буфер под файловый кэш для blob store. Диск может расти хоть до нескольких терабайт, а RAM при этом должна масштабироваться совсем по другой логике — по числу компонентов и интенсивности использования, а не по объёму хранимых файлов.

Что реально влияет на потребление памяти

Прежде чем брать цифры из таблицы ниже, полезно понимать, какие параметры двигают потребление RAM у Nexus сильнее прочих:

  • Количество компонентов в базе метаданных. Тысяча jar-файлов и миллион — это разная нагрузка на datastore и поисковый индекс, даже если суммарный объём на диске одинаковый (например, много мелких npm-пакетов против нескольких больших Docker-образов).
  • Число и тип репозиториев. Прокси-репозитории (proxy) кэшируют метаданные удалённых реестров (npm registry, Maven Central, PyPI, Docker Hub) — чем активнее ими пользуются, тем больше метаданных оседает локально. Hosted-репозитории растут медленнее, но каждая загрузка тоже пишет метаданные.
  • Формат Docker. Docker-репозитории в Nexus заметно прожорливее по памяти, чем Maven или npm: манифесты, теги, многослойные образы и garbage collection неиспользуемых слоёв — процесс, который сам по себе требует ресурсов на анализ ссылок между слоями.
  • Cleanup policies и задачи обслуживания. Плановая очистка старых снапшотов, компакция blob store, перестроение поискового индекса — фоновые задачи, которые на время своей работы ощутимо добавляют нагрузку к базовому потреблению, и именно на них чаще всего ловят кратковременные всплески памяти.
  • Число одновременных пользователей и CI-агентов. Каждый параллельный запрос от Jenkins/GitLab CI Runner, mvn deploy или docker push держит соединение и часть буферов в памяти, пока не завершится.

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

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

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

Сколько RAM нужно: ориентировочные цифры по сценарию

Цифры ниже — отправная точка, не гарантия. У Sonatype в официальной документации есть общие рекомендации по sizing, но конкретное число компонентов и интенсивность использования у вас может отличаться в разы — начинайте с этих значений и следите за реальным потреблением в первые недели.

СценарийРепозиторииRAM сервераHeap JVM (-Xmx)vCPU
Тест / одиночный разработчик1–2 (Maven или npm), немного компонентов4 ГБ1,5–2 ГБ2
Малая командаMaven + npm, несколько прокси8 ГБ3–4 ГБ2–4
Средняя команда с CIMaven + npm + Docker registry, активный CI16 ГБ6–8 ГБ4
Крупная команда / много форматовMaven + npm + PyPI + Docker + raw, миллионы компонентов32 ГБ и больше12–16 ГБ8+

Важное правило: heap не должен занимать всю RAM сервера. Разумный ориентир — не больше 50–60% физической памяти под -Xmx, остальное — под ОС, файловый кэш для blob store и (если используете встроенный H2 без внешнего PostgreSQL) под сам datastore. Если на том же сервере крутится ещё и CI-раннер или Jenkins-агент, считайте RAM по сумме компонентов, а не по максимуму — подробнее про типовую нагрузку CI-стека есть в статье про настройку VPS под разработчика и CI/CD.

Настройка heap: где и что менять

Параметры JVM для Nexus задаются в файле nexus.vmoptions, который нужно переопределять не в каталоге установки, а в data-директории — иначе настройки слетят при следующем обновлении:

# файл переопределения (создаётся, если его ещё нет)
<data-dir>/etc/nexus.vmoptions

Типичное содержимое для сервера с 16 ГБ RAM:

-Xms6703m
-Xmx6703m
-XX:MaxDirectMemorySize=6703m
-XX:+UnlockDiagnosticVMOptions
-XX:+UseG1GC
-Djava.util.prefs.userRoot=${karaf.data}/tmp

Несколько практических моментов:

  • -Xms и -Xmx стоит выставлять равными — так JVM не тратит время на изменение размера кучи в рантайме.
  • Дефолтные значения "из коробки" подбираются инсталлятором под память конкретной машины на момент установки и обычно занижены для продакшен-нагрузки — не полагайтесь на них, если ставите сервер один раз и не проверяете параметры позже.
  • -XX:MaxDirectMemorySize часто забывают — если он не задан явно, суммарное потребление процесса окажется заметно больше, чем -Xmx в одиночку.
  • После изменения nexus.vmoptions нужен полный рестарт сервиса, reload конфигурации недостаточно.

Если Nexus запущен как systemd-сервис, путь к data-директории обычно задаётся переменной NEXUS_HOME или напрямую в юнит-файле — проверьте /etc/systemd/system/nexus.service, прежде чем искать nexus.vmoptions в неправильном месте.

Nexus в Docker Compose с явными лимитами

Для тестового или продакшен-окружения на VPS проще всего поднимать Nexus в контейнере — так лимиты памяти и heap видны в одном файле:

services:
  nexus:
    image: sonatype/nexus3:latest
    environment:
      INSTALL4J_ADD_VM_PARAMS: "-Xms4703m -Xmx4703m -XX:MaxDirectMemorySize=4703m -XX:+UseG1GC"
    mem_limit: 8g
    mem_reservation: 6g
    ports:
      - "8081:8081"
      - "8082:8082"  # порт под Docker-репозиторий, если используете
    volumes:
      - nexus_data:/nexus-data
    restart: unless-stopped
    ulimits:
      nofile: { soft: 65536, hard: 65536 }

volumes:
  nexus_data:

Обратите внимание: mem_limit контейнера должен быть больше, чем -Xmx + -XX:MaxDirectMemorySize в сумме — иначе контейнер будет убит OOM killer'ом Docker раньше, чем JVM успеет сама пожаловаться на нехватку heap. Разница в примере выше (8 ГБ лимит против ~4,7+4,7 ГБ JVM) — это запас под метаданные datastore, файловый кэш и процессы ОС внутри контейнера.

Если репозиторий предполагается большим и растущим — вынесите blob store на S3-совместимое хранилище вместо локального диска контейнера, это не влияет на потребление RAM напрямую, но упрощает масштабирование и бэкапы; в связке с Nexus для этого часто ставят MinIO — сколько ресурсов закладывать под него самого, разобрано в статье сколько RAM нужно для MinIO.

Datastore: встроенный H2 или внешний PostgreSQL

Отдельный фактор, который сильно влияет на память именно JVM-процесса Nexus, — какой datastore вы используете:

  • Встроенный H2 — работает внутри той же JVM, что и сам Nexus, то есть делит heap с основным приложением. Подходит для небольших и средних инсталляций, но при росте числа компонентов начинает конкурировать за память с остальной логикой Nexus.
  • Внешний PostgreSQL — рекомендуемый вариант для серьёзного продакшена и обязательный для HA-конфигураций (кластер из нескольких нод Nexus). PostgreSQL живёт отдельным процессом со своей памятью, разгружая heap Nexus и снимая часть нагрузки на GC.

Если вы уже используете PostgreSQL под другие проекты на том же сервере — прежде чем разворачивать ещё один инстанс под Nexus, стоит прикинуть общий сайзинг сервера по сумме нагрузок; общие соображения по выбору СУБД собраны в статье PostgreSQL или MySQL для сервера (для Nexus выбор уже сделан за вас — поддерживается только PostgreSQL).

Переход с H2 на внешний PostgreSQL стоит планировать заранее, а не постфактум: миграция базы метаданных у Nexus не мгновенная операция, особенно при десятках и сотнях тысяч компонентов, и требует времени на остановку сервиса.

Диагностика: как понять, что памяти не хватает

Не ждите, пока Nexus упадёт с OutOfMemoryError в логах — есть более ранние сигналы:

# посмотреть текущее потребление heap JVM (если процесс запущен нативно, не в Docker)
jstat -gcutil $(pgrep -f nexus) 5000

# в Docker — обычная статистика контейнера
docker stats nexus

# если ловите частые Full GC — проверьте логи GC
tail -f <data-dir>/log/jvm.log

Дополнительно в самом интерфейсе Nexus (Administration → Support → System Information) можно посмотреть параметры JVM, использование heap и активные потоки — полезно, чтобы быстро понять, приближается ли процесс к лимиту -Xmx.

Если сервер регулярно уходит в своп из-за Nexus — это почти всегда сигнал, что -Xmx выставлен слишком близко к физической RAM без запаса под ОС и datastore. Своп для JVM особенно болезненен: паузы сборщика мусора на подкачиваемой памяти превращаются в затяжные подвисания интерфейса и таймауты у CI-раннеров, пытающихся сделать deploy или docker push. Если на сервере вообще предусмотрен swap, стоит заранее понимать, как правильно рассчитать его размер под VPS, чтобы он служил страховкой на пиковые всплески, а не заменой недостающей физической памяти.

Если Nexus используется в первую очередь как приватный Docker registry, а не полноценный менеджер артефактов под несколько форматов — возможно, для вашего случая избыточен целый Nexus, и стоит сравнить его с более лёгкой альтернативой; вариант с нуля разобран в статье как установить и настроить приватный Docker registry на VPS.

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

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

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

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

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

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

Можно ли запустить Nexus на 2 ГБ RAM?

Формально стартует и подходит для короткого ознакомительного теста с парой репозиториев, но это не тот объём, на котором стоит держать что-то важнее локального прототипа: при активном использовании прокси-репозиториев или загрузке Docker-образов велика вероятность OOM. Для стабильной работы даже одиночного разработчика закладывайте минимум 4 ГБ.

Почему Nexus ест память, даже если на диске всего пара гигабайт артефактов?

Потому что память расходуется в первую очередь на метаданные (datastore) и обработку запросов, а не на сами файлы — они лежат в blob store и почти не трогают heap. Небольшой объём на диске не гарантирует небольшое потребление RAM, если компонентов (отдельных версий пакетов) много.

Docker-репозиторий в Nexus требует больше памяти, чем Maven или npm?

Да, на практике формат Docker обычно заметнее нагружает JVM — из-за обработки манифестов, многослойных образов и garbage collection неиспользуемых слоёв. Если планируете активно использовать Nexus как Docker registry, закладывайте RAM по верхней границе диапазона для вашего размера команды.

Что делать, если после нескольких месяцев работы память стала заканчиваться чаще?

Скорее всего вырос datastore вместе с числом компонентов и историей версий. Проверьте cleanup policies — включена ли автоматическая очистка старых снапшотов и неиспользуемых Docker-слоёв — и при необходимости пересчитайте heap на следующий тир по таблице выше.

Обязательно ли переходить на внешний PostgreSQL?

Нет, для небольших и средних команд встроенный H2-datastore работает стабильно. Переходить стоит, когда планируете HA-кластер из нескольких нод Nexus, либо когда встроенная база начинает заметно конкурировать за heap с остальной логикой приложения на больших объёмах.

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

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

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