Как вы управляете встроенными файлами конфигурации и библиотеками в веб-приложениях Java? - PullRequest
15 голосов
/ 24 февраля 2009

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

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

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

Ответы [ 5 ]

8 голосов
/ 24 февраля 2009

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

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

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

6 голосов
/ 25 февраля 2009

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

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

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

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

4 голосов
/ 25 февраля 2009

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

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

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

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

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

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

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

2 голосов
/ 25 февраля 2009

Я обычно делаю два файла свойств:

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

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

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

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

0 голосов
/ 24 февраля 2009

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

...