Как вы управляете встроенными файлами конфигурации и библиотеками в java webapps?

StackOverflow https://stackoverflow.com/questions/582248

Вопрос

В настоящее время я работаю над проектом j2ee, который уже некоторое время находится в стадии бета-тестирования.Прямо сейчас мы просто решаем некоторые проблемы, связанные с процессом развертывания.В частности, в war встроен ряд файлов (некоторые xml-файлы и .properties), для развертывания которых требуются разные версии в зависимости от того, находитесь ли вы в среде разработки, тестирования или производства.Такие вещи, как уровни регистрации, пулы подключений и т.д.

Поэтому мне было интересно, как здешние разработчики структурируют свой процесс развертывания веб-приложений.Загружаете ли вы как можно больше конфигурации на сервер приложений?Заменяете ли вы файлы настроек программно перед развертыванием?Выбрать версию в процессе сборки?Вручную редактировать войны?

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

Это было полезно?

Решение

Я работаю в среде, где отдельная серверная команда выполняет настройку серверов контроля качества и производства для наших приложений.Каждое приложение обычно развертывается на двух серверах в режиме контроля качества и трех серверах в режиме производства.Моя команда разработчиков обнаружила, что лучше всего свести к минимуму объем требуемой конфигурации на сервере, поместив как можно больше настроек в war (или ear).Это упрощает настройку сервера, а также сводит к минимуму вероятность того, что команда сервера неправильно настроит сервер.

У нас нет конфигурации для конкретной машины, но у нас есть конфигурация для конкретной среды (Dev, QA и Production).У нас есть файлы конфигурации, хранящиеся в файле war, которые названы по среде (например.dev.properties, qa.properties, prod.properties).Мы помещаем свойство -D в командную строку java виртуальной машины сервера, чтобы указать среду (например.java -Dapp.env=prod ...).Приложение может искать системное свойство app.env и использовать его для определения имени используемого файла свойств.

Я полагаю, что если у вас есть небольшое количество специфичных для машины свойств, то вы также могли бы указать их как общие свойства.Конфигурация Commons предоставляет простой способ объединить файлы свойств со свойствами системы.

Мы настраиваем пулы подключений на сервере.Мы называем пул подключений одинаковым для каждой среды и просто указываем серверы, назначенные каждой среде, на соответствующую базу данных.Приложение должно знать только одно имя пула соединений.

Другие советы

Я думаю, что если свойства зависят от машины / развертывания, то они принадлежат машине.Если я собираюсь завершить работу в war, она должна быть недоступна для удаления, что не означает ничего специфичного для машины, на которой она запущена.Эта идея рухнет, если в war будут присутствовать свойства, зависящие от машины.

Что мне нравится делать, так это создавать проект с файлом properties.example, на каждой машине есть файл .properties, который находится там, где war может получить к нему доступ.

Альтернативным способом было бы иметь муравьиные задачи, напримердля dev-war, stage-war, prod-war и имеют наборы свойств, являющиеся частью проекта, запеченные в war-build.Мне это не нравится так сильно, потому что в конечном итоге у вас будут такие вещи, как расположение файлов на отдельном сервере, как часть сборки вашего проекта.

файлы конфигурации wrt, я думаю У Стива ответ - лучший на данный момент.Я бы добавил предложение создать внешние файлы относительно пути установки файла war - таким образом, у вас может быть несколько установок war на одном сервере с разными конфигурациями.

например ,Если мой dev.war распаковывается в /opt/tomcat/webapps/dev, тогда я бы использовал ServletContext.getRealPath чтобы найти базовую папку и имя папки war, чтобы затем файлы конфигурации находились в ../../config/dev по отношению к войне, или /opt/tomcat/config/dev для абсолюта.

Я также согласен с Билл о том, чтобы как можно меньше помещать в эти внешние конфигурационные файлы.Используйте базу данных или JMX в зависимости от вашей среды для хранения столько, сколько в этом есть смысл.Конфигурация Apache Commons имеет приятный предмет для обработки конфигураций, поддерживаемых таблицей базы данных.

Что касается библиотек, я согласен с неизвестный чтобы иметь все библиотеки в WEB-INF/lib папка в файле war (самоупаковывающаяся).Преимущество заключается в том, что каждая установка приложения является автономной, и у вас могут быть разные сборки war, использующие разные версии библиотек одновременно.

Недостатком является то, что это будет использовать больше памяти, поскольку каждое веб-приложение будет иметь свою собственную копию классов, загружаемую его собственным загрузчиком классов.

Если это представляет реальную проблему, то вы могли бы поместить банки в общую папку библиотеки для вашего контейнера сервлетов ($CATALINA_HOME/lib для tomcat).Однако все установки вашего веб-приложения, запущенного на одном сервере, должны использовать одни и те же версии библиотек.(На самом деле, это не совсем верно, поскольку вы могли бы поместить переопределяющие версии в отдельные WEB-INF/lib папка, если необходимо, но это становится довольно запутанным в обслуживании.)

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

Обычно я создаю два файла свойств:

  • один для специфики приложения (сообщения, внутренние "волшебные" слова), встроенные в приложение,
  • другой для специфики среды (доступ к БД, уровни журналов и пути ...), отображаемый в classpath каждого сервера и "прикрепленный" (не поставляется с моим приложением).Обычно я "мавенизирую" или "изменяю" их, чтобы задать конкретные значения, в зависимости от целевой среды.
  • Классные ребята используют JMX для поддержки своего приложения conf (conf можно изменять в режиме реального времени, без повторного развертывания), но это слишком сложно для моих нужд.

Серверные (статические?) библиотеки:Я настоятельно не рекомендую использовать серверную библиотеку в своих приложениях, поскольку это добавляет зависимости к серверу:

  1. ИМО, мое приложение должно быть "самоупакованным".:прекращаю свою войну, и это все.Я видел войны с 20 Мб банок в них, и это меня не беспокоит.
  2. Обычной наилучшей практикой является ограничение ваших внешних зависимостей тем, что предлагается догмой J2EE:API J2EE (использование сервлетов, Ejbs, Jndi, JMX, JMS ...).Ваше приложение должно быть "независимым от сервера".
  3. Размещение зависимостей в вашем приложении (war, ear, wathever) является самодокументируемым:вы знаете, от каких библиотек зависит ваше приложение.С серверными библиотеками вы должны четко документировать эти зависимости, поскольку они менее очевидны (и вскоре ваши разработчики забудут об этом маленьком волшебстве).
  4. Если вы обновите свой appserver, вероятность того, что библиотека сервера, от которой вы зависите, также изменится.Редакторы AppServer не должны поддерживать совместимость своих внутренних библиотек от версии к версии (и в большинстве случаев они этого не делают).
  5. Если вы используете широко используемую библиотеку, встроенную в ваш AppServer (на ум приходит jakarta commons logging, она же jcl), и хотите обновить ее версию, чтобы получить новейшие функции, вы сильно рискуете тем, что ваш AppServer не будет ее поддерживать.
  6. Если вы полагаетесь на статический серверный объект (в статическом поле серверного класса, напримеркарта или журнал), вам придется перезагрузить ваш appserver, чтобы очистить этот объект.Вы теряете возможность горячего повторного развертывания вашего приложения (старый серверный объект все еще будет существовать между повторными развертываниями).Использование объектов на уровне сервера приложений (отличных от тех, которые определены J2EE) может привести к незначительным ошибкам, особенно если этот объект используется совместно несколькими приложениями.Вот почему я настоятельно не рекомендую использовать объекты, которые находятся в статическом поле библиотеки AppServer.

Если вам абсолютно необходим "этот объект в jar этого сервера приложений", попробуйте скопировать jar в свое приложение, надеясь, что нет зависимости от jar другого сервера, и проверяя политику загрузки классов вашего приложения (у меня вошло в привычку устанавливать политику загрузки классов "родительский последний" во всех моих приложениях:Я уверен, что я не буду "загрязнен" серверными банками - но я не знаю, является ли это "лучшей практикой").

Я поместил всю конфигурацию в базу данных.Контейнер (Tomcat, WebSphere и т.д.) предоставляет мне доступ к первоначальному подключению к базе данных, и с этого момента все выходит из базы данных.Это позволяет использовать несколько сред, кластеризацию и динамические изменения без простоев (или, по крайней мере, без повторного развертывания).Особенно приятно иметь возможность изменять уровень журнала "на лету" (хотя вам понадобится либо экран администратора, либо фоновое обновление, чтобы отслеживать изменения).Очевидно, что это работает только для вещей, которые не требуются для запуска приложения, но, как правило, вы можете довольно быстро получить доступ к базе данных после запуска.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top