Эффективно развертывайте несколько экземпляров одной и той же WAR (разные контексты, один и тот же контейнер)
У меня есть одна WAR (app.war) и один контейнер (Tomcat, Jetty, Glassfish, что угодно).
Моя цель - развернуть по запросу сотни экземпляров этого же веб-приложения в контейнере.
http://foo/app1 --> app.war
http://foo/app2 --> app.war
http://foo/app3 --> app.war
...
http://foo/appN --> app.war
Некоторые очевидные способы достижения этого:
- В Tomcat создайте один файл context.xml для каждого приложения (с именем appN.xml), все указывая на ту же WAR. Другие контейнеры имеют сходные методы
- Проблема с этим подходом: он взорвет WARN раз, заняв много места на диске.
- Используйте символические ссылки для создания папок webapp/{app1, app2, appN}, указывающих на взорванную версию app.war. Это предотвращает взрыв дискового пространства, но JVM по-прежнему загружает много дубликатов JAR в память.
- Используйте некоторую общую папку lib, чтобы содержать большинство банок (и комбинацию из двух предыдущих опций).
Интересно, есть ли лучший способ сделать это. В идеале, создание нового экземпляра не должно занимать больше места на диске (кроме крайних конфигурационных файлов) и обрабатывать только память, связанную со стеками выполнения потоков и другими распределениями времени выполнения.
Любые идеи?
Ответы
Ответ 1
Jetty добавила поддержку того, что вы ищете некоторое время назад, с так называемыми наложениями.
http://wiki.eclipse.org/Jetty/Tutorial/Configuring_the_Jetty_Overlay_Deployer
Копирование бит со страницы вики:
- Вы можете сохранить WAR файл неизменным, даже подписанным, чтобы было ясно, какая версия была развернута.
- Все изменения, внесенные вами для настройки/настройки веб-приложения, являются отдельными WAR-сообщениями и поэтому легко идентифицируются для просмотра и перехода на новые версии.
- Вы можете создать параметризованный наложение шаблона, который содержит общие настройки и настройки, которые применяются ко многим экземплярам веб-приложения (например, для развертывания с несколькими арендаторами).
- Поскольку многоуровневое развертывание четко идентифицирует общие и специфичные для экземпляра компоненты, Jetty может совместно использовать загрузчики классов и статические кэши ресурсов для шаблона, что значительно уменьшает объем памяти нескольких экземпляров.
Ответ 2
Извиняется за то, что немного не по теме, но, на мой взгляд, ваш сценарий выкрикивает приложение с несколькими приложениями, так что у вас есть одно приложение, которое будет обслуживать несколько "арендаторов" (клиентов).
Что касается многоуровневых установок, следует рассмотреть следующие соображения:
- Клиенты не могут обращаться к другим данным (если они хранятся в одной и той же базе данных, той же схеме и используют поля "дискриминатор" для разделения данных). Это может быть достигнуто с помощью Spring Безопасность с Списки контроля доступа
- Hibernate имеет встроенную поддержку для приложений с несколькими приложениями с версии 4.0.
- Эти два вопроса могут быть полезны
Преимущества многопользовательской работы:
- Общий код означает, что ошибка, исправленная для одного клиента, исправлена для всех (это может быть и недостатком, если разные клиенты имеют разные взгляды на то, что представляет собой ошибку и что представляет собой функцию).
- Кластеризованное развертывание может совместно использовать нагрузку между клиентами (однако необходимо обеспечить максимальную пропускную способность для всех клиентов).
Downsides:
- Код будет немного сложнее, так как запросы должны гарантировать, что "дискриминация" между клиентами работает без случайного раскрытия клиентам данных друг друга.
Ответ 3
Вы можете настроить Apache на передней панели (mod_proxy/mod_proxy_ajp), чтобы указать виртуальные хосты на одну WAR, развернутую на Tomcat. Ваше приложение должно быть спроектировано/написано таким образом, чтобы обслуживать весь запрос. Конфигурация конкретного веб-сайта может быть сохранена в базе данных или в виде файла конфигурации в вашем приложении - вашему приложению просто нужно будет исследовать имя пользователя, запрашивающего доменное имя, убедитесь, что установлены правильные настройки (один раз за сеанс). В общем, вы должны решить это с помощью одного приложения. Отличные разработчики LAZY.
Ответ 4
Хорошо, если это для эксперимента, то любой из перечисленных вами методов может работать.
Если это для производства, я бы рекомендовал против этого. Хотя я не тестировал ВСЕ контейнеры, контейнеры, которые я использовал, заставляют меня полагать, что он намного более устойчив, просто предоставляя безголовые виртуальные машины с контейнерами. Linux VM могут быть очень маленькими, и с технологией VM вы можете добавлять или вычитать столько случаев, сколько необходимо.
Если вы действительно хотите иметь динамически растущее решение, вам следует попытаться устранить отдельные точки отказа, а затем попытаться объединить весь мир в один.
Если вам действительно нужно "до второго" расширения/сжатия нагрузки, вы должны посмотреть на AWS или CloundFoundry.
Ответ 5
Если вы используете Jetty, вы можете добавлять контексты программно.
WebAppContext webapp = new WebAppContext();
webapp.setBaseResource(myBaseDirectory);
webapp.setContextPath(myContextPath);
Просто сделайте это в цикле для всех ваших контекстов. Он должен иметь близкие к нулю служебные данные дискового пространства.
Вероятно, аналогичный способ сделать это в Tomcat.