Несколько JVM против одного сервера приложений

Я имею дело с системой, которая запускает Java-приложение для каждого клиента в своей собственной JVM. У нас есть около полудюжины выделенных серверов, на которых сейчас работает около 100 JVM, и набор пользовательских сценариев для управления этими JVM. Эта установка действительно показывает свой возраст на данный момент: управление таким количеством JVM становится кошмаром мониторинга / управления, и мы постоянно имеем дело с проблемами размера кучи. Мы хотели бы перейти к более современному подходу и просто запустить несколько приложений на одном сервере приложений для каждой физической машины. Однако разделение приложений имеет определенные преимущества с точки зрения изоляции (например, ошибки нехватки памяти влияют только на одного клиента). Программный стек каждого клиента предъявляет различные требования к памяти.

Мой вопрос: есть ли способ получить лучшее из обоих миров и запустить несколько приложений в одной JVM (сервер приложений) и при этом сохранить некоторую степень изоляции? Или это просто современный факт жизни, который вам необходим для управления требованиями к памяти для набора приложений в наши дни? Есть ли здесь другие решения, кроме сервера приложений или контейнера Java EE (например, Wildfly или Spring), которые мне здесь не хватает? Похоже, что эта система - воздержание от другой эры!

4 ответа

Решение

Оформить заказ на "мультитенантных" JVM.

У JRE IBM это уже есть: http://www.ibm.com/developerworks/library/j-multitenant-java/

Waratek реализовал его поверх Oracle JRE и создал ElastiCat, вилку Tomcat, которая изолирует различные приложения в одном контейнере: http://www.elasticat.com/faq/

Ходят слухи, что мультитенантность появится и в официальной JVM Oracle Java 9.

================================================== =====

Обновление: Java 9 вышла, но от Oracle нет ни слова о многопользовательском режиме. Кажется, что они предпочитают иметь несколько JVM в наши дни, даже несколько контейнеров (например, Docker).

Есть плюсы и минусы любого подхода:

Совместная JVM

  • Меньшая нагрузка - объем памяти JVM (библиотеки ядра и т. Д.) Необходимо загружать только один раз.
  • Лучшее использование памяти. Процессы Java будут использовать память ОС для пространства кучи, которое в данный момент может не использоваться.

Отдельная JVM

  • Изоляция от "жадных" или "негерметичных" приложений.
  • Лучшая защита от вредоносного кода.
  • Более простые обновления, обновление одного приложения без сбивания другого.

В целом, я бы не стал устанавливать общую политику. Ищите небольшие / микро-сервисы или другие приложения с низким уровнем использования, которые могут быть хорошими кандидатами, чтобы поделиться ими и расширяться оттуда.

Взгляните на Spring Boot или Fabric8 для современного подхода к запуску Java управляемым способом

Еще одна важная причина иметь несколько JVM вместо одной - это столкновение с группами numa. Вы не можете распределять свои потоки в одной JVM, подходящей для групп numa, как вы можете с несколькими процессами jvm. По крайней мере, я так и не нашел способ сделать это.

У нас есть машины с двумя процессорами, каждый из которых имеет 18 ядер. Это дает две группы numa, и мы не можем принудительно распределить 34 потока на оба процессора, если используется только одна JVM. Это очевидно потому, что предполагается, что все потоки одного и того же процесса JVM должны иметь быстрый доступ к одной и той же памяти, что не так.

Имея 34 процесса, система предполагает, что им не нужна общая память, и таким образом распределяет их по обоим процессорам.

Если кто-то знает лучший способ сделать это, я был бы очень рад услышать это.

Другие вопросы по тегам