Этот отрывок взят из книги « От Tomcat к WildFly », в которой вы узнаете, как перенести существующие архитектуры Tomcat на WildFly, включая как конфигурацию сервера, так и приложения, работающие на его вершине.
WildFly — это полностью совместимый контейнер Java Enterprise Edition 7 с гораздо более широким набором доступных сервисов и опций по сравнению с Tomcat.
Книга также предоставит вам информацию о наиболее распространенных ошибках и недостатках, которые могут возникнуть во время миграции.
Содержание
1. Введение
Проблема : у меня есть конфигурация источника данных на Tomcat, которая используется для сбора соединений с базой данных из пула. Мне нужно перенести мою конфигурацию на WildFly. |
На Apache Tomcat конфигурацию источника данных можно включить в глобальный раздел файла server.xml . Вот, например, конфигурация для популярной базы данных MySQL:
1
2
3
4
5
|
<Resource name = "jdbc/mysqlds" auth= "Container" type= "javax.sql.DataSource" maxActive= "100" maxIdle= "30" maxWait= "10000" username= "tomcat" password = "tomcat" driverClassName= "com.mysql.jdbc.Driver" url= "jdbc:mysql://localhost:3306/mydatabase" /> |
Кроме того, следующие строки должны быть размещены в WEB-INF / web.xml для содержимого приложения.
1
2
3
4
5
6
7
8
9
|
< web-app xmlns = "http://java.sun.com/xml/ns/j2ee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version = "2.4" > < description >Tomcat DB</ description > < resource-ref > < description >Database Connection</ description > < res-ref-name >jdbc/mysqlds</ res-ref-name > < res-type >javax.sql.DataSource</ res-type > < res-auth >Container</ res-auth > </ resource-ref > </ web-app > |
Чтобы иметь возможность загрузить драйвер MySQL JDBC, вам необходимо включить библиотеку JAR в папку CATALINA_HOME / lib :
Давайте посмотрим, как настроить конфигурацию источника данных в WildFly . Это может быть достигнуто несколькими способами, но все возможные решения включают следующие шаги:
- Установка драйвера JDBC как модуля
- Регистрация драйвера JDBC на сервере приложений
- Настройка источника данных, который использует драйвер JDBC
Мы увидим рекомендуемый подход, который требует использования интерфейса командной строки, хотя мы упомянем некоторые доступные альтернативы.
2. Установка драйвера JDBC как модуля
WildFly основан на предположении, что каждая библиотека сама является модулем. Итак, сначала мы превратим драйвер JDBC в модуль. Это можно сделать путем создания структуры пути к файлу в каталоге JBOSS_HOME / modules . Например, чтобы установить драйвер MySQL JDBC, создайте структуру каталогов следующим образом: JBOSS_HOME / modules / com / mysql / main .
- Скопируйте JAR-файл драйвера JDBC в основной подкаталог.
- В главном подкаталоге создайте файл module.xml, содержащий следующие определения (просто адаптируйте имя драйвера JDBC к вашему случаю):
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<? xml version = "1.0" encoding = "UTF-8" ?> < module xmlns = "urn:jboss:module:1.0" name = "com.mysql" > < resources > < resource-root path = "mysql-connector-java-5.1.24-bin.jar" /> </ resources > < dependencies > < module name = "javax.api" /> < module name = "javax.transaction.api" /> </ dependencies > </ module > |
Описанную выше процедуру можно также выполнить с помощью интерфейса командной строки , используя одну команду, которая создаст структуру файловой системы, скопирует драйвер JDBC в основную папку и настроит файл module.xml на основе параметров, предоставленных для CLI.
Вот как это сделать, если предположить, что драйвер JDBC MySQL доступен в папке / home / wildfly :
1
|
module add --name=com.mysql --resources=/home/wildfly/mysql-connector-java-5.1.24-bin.jar --dependencies=javax.api,javax.transaction.api |
3. Регистрация драйвера JDBC на сервере приложений
Теперь, когда ваш MySQL доступен как модуль на сервере приложений, мы зарегистрируем его как драйвер JDBC. При использовании CLI это одностадийная операция:
1
|
/subsystem =datasources /jdbc-driver =mysql:add(driver-name=mysql,driver-module-name=com.mysql) |
Теперь вы можете проверить, что ваш драйвер MySQL зарегестрирован через доступные драйверы JDBC. Вот как вы можете этого добиться:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
[standalone@localhost:9990 /] /subsystem=datasources:installed-drivers-list { . . . . . . . . . . . "driver-name" => "mysql" , "deployment-name" => undefined, "driver-module-name" => "com.mysql" , "module-slot" => "main" , "driver-datasource-class-name" => "" , "driver-xa-datasource-class-name" => "" , "driver-class-name" => "com.mysql.jdbc.Driver" , "driver-major-version" => 5, "driver-minor-version" => 1, "jdbc-compliant" => false } ] } |
4. Настройка источника данных, который использует драйвер JDBC
Последний шаг фактически создаст источник данных, который будет использоваться вашими приложениями. Для этого мы будем использовать команду быстрого доступа к источнику данных CLI, которая требует в качестве ввода имя пула, привязки JNDI, параметры соединения JDBC и, наконец, параметры безопасности (имя пользователя и пароль):
1
|
data-source add --jndi-name=java:/jdbc/mysqlds --name=MySQLPool --connection-url=jdbc:mysql://localhost:3306/mydatabase --driver-name=mysql --user-name=jboss --password=jboss |
Обратите внимание, что имя JNDI для источника данных должно использовать префикс java: /, чтобы быть принятым как действительный. Поэтому привязка, используемая в tomcat («jdbc / mysqlds»), была изменена на «java: / jdbc / mysqlds». |
5. Конфигурация вывода
Если вы выполнили вышеуказанные шаги, в вашем разделе источников данных должна быть доступна следующая конфигурация источника данных:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
< datasources > < datasource jndi-name = "java:/jdbc/mysqlds" pool-name = "MySQLPool" enabled = "true" > < connection-url >jdbc:mysql://localhost:3306/mydatabase</ connection-url > < driver >mysql</ driver > < security > < user-name >jboss</ user-name > < password >jboss</ password > </ security > </ datasource > < drivers > < driver name = "mysql" module = "com.mysql" /> </ drivers > </ datasources > |
6. Портирование параметров источника данных в WildFly
Настройка источника данных на сервере приложений — это первая веха для переноса ваших приложений на WildFly. Однако есть вероятность, что вы используете определенные параметры пула соединений, которые необходимо перенести на сервер приложений. Некоторые из этих параметров имеют одинаковое соответствие в WildFly, другие основаны на различных стратегиях объединения; поэтому вам необходимо адаптировать конфигурацию при переносе их на сервер приложений. Давайте посмотрим, как перенести наиболее распространенные параметры пула в WildFly:
6.1. Минимальный и максимальный размер пула
Выбор правильного размера пула является обязательным для производительности ваших приложений. Минимальный размер пула Tomcat определяется параметром minIdle, а максимальный размер пула настраивается через maxActive . Начальный размер пула, с другой стороны, настраивается с параметром initialSize . Вот пример конфигурации:
1
2
3
4
5
|
<Resource name = "jdbc/mysqlds" auth= "Container" type= "javax.sql.DataSource" maxActive= "100" minIdle= "30" initialSize=”15” username= "tomcat" password = "tomcat" driverClassName= "com.mysql.jdbc.Driver" url= "jdbc:mysql://localhost:3306/mydatabase" /> |
При портировании на WildFly параметры называются соответственно min-pool-size и max-pool-size и могут быть установлены любым инструментом управления. Вот как их изменить для источника данных по умолчанию:
1
2
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=min-pool-size,value=30) /subsystem =datasources /data-source =ExampleDS/:write-attribute(name=max-pool-size,value=100) |
Начальный размер пула , с другой стороны, может быть установлен с помощью:
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=initial-pool-size,value=5) |
Дополнительно обратите внимание, что WildFly также имеет атрибут с именем pool-prefill , который определяет, следует ли пытаться предварительно заполнить пул соединений до минимального количества соединений:
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=pool-prefill,value= true ) |
6.2. Работа с простыми соединениями
Соединения, которые были созданы, но не использовались вашими приложениями, классифицируются как свободные соединения. У WildFly и Tomcat разные способы работы с простаивающими соединениями. Более подробно, Tomcat использует параметры minIdle и maxIdle для определения соответственно минимального и максимального числа незанятых соединений, которые должны храниться в пуле. Мы уже обсуждали параметр minIdle, который можно превратить в размер минимального пула WildFly. С другой стороны, параметр maxIdle не имеет соответствующего соответствия в WildFly. Самое близкое совпадение — это i dle-timeout-minutes , которое представляет собой количество минут, после которых неиспользуемые соединения закрываются (по умолчанию 15 минут). Вы можете изменить этот параметр, скажем, до 10 минут следующим образом:
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=idle-timeout-minutes,value=10) |
6.3. Установка таймаута при установлении соединения
Если все ваши подключения в пуле заняты, вашим приложениям, очевидно, придется ждать, пока соединение не будет освобождено. Как вы можете себе представить, для этого сценария существует тайм-аут, который обрабатывается параметром maxWait в Tomcat. В следующем примере время ожидания установлено на 30 секунд:
1
2
3
|
<Resource name = "jdbc/mysqlds" auth= "Container" type= "javax.sql.DataSource" maxWait= "30000" . . . . /> |
WildFly имеет соответствующий параметр с именем blocking-timeout-wait-millis ; в следующей команде CLI мы устанавливаем ее на 1 секунду (1000 мс):
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=blocking-timeout-wait-millis,value=1000) |
6.4. Обработка утечек соединения
Утечка соединения называется в терминах Tomcat « Прерванное соединение », которое происходит, когда вы создаете оператор, или PreparedStatement, или CallableStatement, и вы пропускаете закрытие соединения или оператора (или чаще вы не включаете соединение закрыть в, наконец, блок).
Вы можете обрабатывать оставленные соединения в Tomcat, включив параметр removeAbandoned . Если установлено значение true, соединение считается разорванным и может быть удалено, если оно не использовалось дольше, чем removeAbandonedTimeout (по умолчанию 300 секунд).
1
2
3
|
<Resource name = "jdbc/mysqlds" auth= "Container" type= "javax.sql.DataSource" removeAbandoned = "true" removeAbandonedTimeout=”300” . . . . /> |
На стороне WildFly нет соответствующей настройки для внезапного закрытия соединений, которые квалифицируются как разорванные. С другой стороны, есть несколько полезных параметров, которые можно использовать для обнаружения или отслеживания проблемы.
Если вас интересуют операторы (и PreparedStatements), вы можете использовать параметр track-Statement, который проверяет наличие незамкнутых операторов, когда соединение возвращается в пул, и результирующие наборы закрываются, когда оператор закрывается / возвращается в подготовленный кэш операторов. Допустимые значения:
- false: не отслеживать заявления и результаты
- true: отслеживать операторы и наборы результатов и предупреждать, когда они не закрыты
- nowarn: отслеживать заявления, но не предупреждать о том, что они не разглашаются
Вот как установить этот параметр для использования NOWARN:
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=track-statements,value=NOWARN) |
Кроме того, вы можете включить отладку уровня кэширования, который обрабатывается в WildFly управляемым соединением в кэше , частью подсистемы Connector (JCA).
1
|
/subsystem =jca /cached-connection-manager =cached-connection-manager/:write-attribute(name=debug,value= true ) |
Вам также следует включить параметр error , который позволит вам обнаружить любую ошибку, связанную с кэшированным диспетчером соединений:
1
|
/subsystem =jca /cached-connection-manager =cached-connection-manager/:write-attribute(name=error,value= true ) |
Как только вы включите ведение журнала, вы увидите для каждого соединения, полученного из пула, следующую информацию:
1
|
DEBUG [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] (MSC service thread 1-4) {JNDI_NAME}: getConnection(null, null) [1 /100 ] |
С другой стороны, вы прочитаете следующее сообщение, когда соединения возвращаются в пул:
1
|
DEBUG [org.jboss.jca.core.connectionmanager.pool.strategy.OnePool] (MSC service thread 1-4) {JNDI_NAME}: returnConnection(607e334, false ) [1 /99 ] |
Если вы отлаживаете заявления, генерируемые вашими приложениями, вы можете легко узнать, где происходит утечка соединения.
Наконец, если вам нужны подробности о том, что происходит на уровне JDBC, вы можете записать в журнал операторы JDBC, установив в true свойство spy:
1
|
/subsystem =datasources /data-source =MySQLPool/:write-attribute(name=spy,value= true ) |
Чтобы отладить операторы JDBC в журналах вашего сервера, вам нужно создать элемент logger, который отслеживает пакет jboss.jdbc.spy. Вы можете сделать это следующим образом:
1
|
/subsystem =logging /logger =jboss.jdbc.spy/:add(level=TRACE) |
Перезагрузите конфигурацию сервера и проверьте журналы сервера, которые по умолчанию содержатся в JBOSS_HOME / standalone / log / server.log (автономный режим) или JBOSS_HOME / domain / [server-name] /log/server.log (режим домена).
6,5. Настройка кэша операторов
Предварительно подготовленный оператор — это предварительно скомпилированный объект в базе данных, план доступа которого будет использоваться повторно для выполнения дальнейших запросов намного быстрее, чем обычные запросы. Подготовленные операторы могут также кэшироваться самим сервером приложений, когда необходимо выдавать одни и те же операторы для разных запросов. Возможности Tomcat jdbc-pool могут управлять кэшем подготовленных операторов с помощью перехватчика JDBC , который задается как свойство JDBC при создании пула. Например:
1
2
3
|
<Resource name = "jdbc/mysqlds" auth= "Container" type= "javax.sql.DataSource" jdbcInterceptors= "StatementCache(prepared=true,callable=false,max=50)" </Resource> |
При работе в WildFly вы можете установить размер кэша PreparedStatement, написав атрибут prepare-reports -cache-size, как в следующем примере, который устанавливает его размер в 25 операторов:
1
|
/subsystem =datasources /data-source =ExampleDS/:write-attribute(name=prepared-statements-cache-size,value=25) |
Этот отрывок взят из книги « От Tomcat к WildFly », в которой вы узнаете, как перенести существующие архитектуры Tomcat на WildFly, включая как конфигурацию сервера, так и приложения, работающие на его вершине. Вы также получите информацию о наиболее распространенных недостатках и недостатках, которые могут возникнуть во время миграции.
Apache Tomcat — это популярный веб-сервер и контейнер сервлетов, разработанный Apache Software Foundation с 1999 года как проект с открытым исходным кодом. Сегодня это одна из наиболее широко используемых платформ для запуска веб-приложений как на простых сайтах, так и в больших сетях.
Тем не менее, количество библиотек, доступных в Apache Tomcat, обычно достаточно для очень простых архитектур, которые требуют только протокола HTTP и ограниченного числа служб; это вызвало естественную тенденцию к расширению его возможностей с помощью новых расширений или модулей, таких как Spring, Hibernate, JDO или Struts. Хотя цель этой книги не состоит в том, чтобы пролить плохой свет на эти архитектуры, мы считаем, что сравнительное знание других решений может помочь вам выбрать лучшее для ваших проектов.