среда, 3 декабря 2008 г.

Интеграция Tomcat и Apache


Зачем?
Когда возникает необходимость размещать на сайте свои JSP-страницы и/или сервлеты на веб-сервере, то одним из самых лучших помощников есть Tomcat. Есть и другие бесплатные контейнеры сервлетов, например Jetty, но мне по душе Tomcat.
Зачем Tomcat связывать с Apache? Над этим вопросом я думал немало. На многих форумах пишут, что Apache быстрее работает со статистическими файлами (например, .gif, .html), но это было раньше. Последние версии Tomcat, в моем случае Tomcat 6, работают со статикой намного лучше, а на официальном сайте Tomcat пишут, что иногда даже лучше. Радует также то, что в Tomcat есть возможность использовать виртуальный хостинг (с алиасами), а также есть поддержка PHP! Для того чтобы клиентам не приходилось указывать порт веб-сервера (по умолчанию в Tomcat 8080) можно либо настроить в server.xml чтобы Tomcat запускался с обслуживание порта 80 либо сделать перенаправление с порта 8080 на порт 80 (если конечно никакой сервер этот порт еще не использует). В целях безопасности я предпочитаю второй вариант. В Linux это делается элементарно:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

Но в связке Tomcat и Apache есть свои преимущества:
можно использовать модуль mod_jk для балансировки нагрузки нескольких Tomcat серверов, а также для создания кластера.
Можно использовать разнообразные модули Apache (но не всегда они нужны и даже могут мешать безопасности)
Больше аргументов в пользу связки Apache и Tomcat для современных версий Tomcat я не нашел. Но этот первый пункт для меня был весомым. Возможно (и скорее всего) разработчики Tomcat реализуют эту функциональность и он станет достаточно самостоятельным веб-сервером. Но все-таки Tomcat в первую очередь нацелен на Java-разработчиков.

Как?
Есть 2 базовый варианта.
Первый: использовать модули Apache, а именно mod_proxy, mod_alias
Для этого нужно в httpd.conf или конфигурационном файле виртуально хоста (если он отдельно) прописать так:

RedirectMatch permanent ^/$ http://<домен>/<приложение>/
ProxyPass /<приложение> http://<домен>:8080/<приложение>/
ProxyPassReverse /<приложение> http://<домен>:8080/<приложение>/


mod_alias нужен для RedirectMatch и mod_proxy - для ProxyPass и ProxyPassReverse директив
В этом подходе есть преимущества — простота настройки и недостатки:
- Tomcat сервер не может находится во внутренней и/или DMZ-зоне (без специальных настроек фаервола и/или DNS)
- слабая поддержка балансировки и кластеризации (на официальном сайте пишут, что mod_proxy поддерживает балансировку, но производительность хуже)
- плохая производительность.

Второй. Использовать коннекторы. Из всего разнообразия коннектором на официальном сайте Apache указано, что сейчас для версии 6 поддерживается Jk и mod_proxy.
Коннекторы jserv, Jk2 (!), webapp — устарели. Первые два используют протокол AJP, последний — WARP.
Далее описывается как настроить коннектор jk (mod_jk).
Где взять модуль JK и как его установить?
Установить mod_jk можно используя репозитарий Linux. Просто сделайте поиск в репозитарии, например jk. Этот модуль я видел в дистрибутивах SuseOpenSuse), Mandriva, Debian, CentOS (соответственно должно быть и в RadHat и Fedora). В OpenSuse он назывался apache2-mod_jk. Я так понял, что этот модуль можно установить с репозитария во всех популярных дистрибутивах. Именно так я его установил.
Но, если нет такой возможности или хочется установить самый последний модуль, то его можно либо скачать в бинарном виде с этого сайта - обязательно учтите архитектуру процессора и версию Apache!
Либо установить с исходников. Для этого нужно скачать с этого сайта нужную версию, проверить на целостность, и установить. Важная заметка: для того чтобы при установке скомпилировалась именно та, версия, которая подходит для вашей версии Apache должна быть установлена программа apxs !

Как подключить mod_jk к Apache? На примере OpenSuse все очень просто:
В файле /etc/sysconfig/apache2 в строке APACHE_MODULES= дописываем mod_jk и перегружаем Apache. Чтобы убедиться, что он загружен используем команду:
apache2ctl -t -D DUMP_MODULES
В списке должно быть jk_module (shared)
Если модуль устанавливался НЕ с помощью репозитария дистрибутива, то модуль нужно скинуть в место где находятся библиотеки Apache (учитывайте архитектуру процессора), а загрузка модуля зависит от версии Apache, которую используете.
А теперь непосредственно настройка коннектора. Сделаем это в 4 шага
1) подключаем свой конфигурационный файл в httpd.conf
Include /etc/apache2/mod-jk.conf
2) в этом файле пишем:
JkWorkersFile /etc/apache2/workers.properties
JkLogFile /etc/apache2/mod-jk.log
JkLogLevel info
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkRequestLogFormat "%w %V %T"
JkExtractSSL On


/* пути исправляйте для собственных нужд */

Тут мы указываем на файл настроек так называемых workers (работники :) )
Обо всех остальных директивах и настройках для Apache можно почитать на этом сайте

3) описываем работу воркеров в файле workers.properties
worker.list=worker1, worker2
worker.worker1.port=8009
worker.worker1.host=hostname
worker.worker1.type=ajp13
worker.worker2.port=8010
worker.worker2.host=hostname
worker.worker2.type=ajp13


Что это значит?
worker.list — список воркеров
И ниже свойства каждого воркера, а именно port, host, type (порт, хост, тип).
Порт — это порт AJP, который слушает соответствующий Tomcat-сервер. По умолчанию это 8009
Хост — имя хоста или его Ip-адрес, где находится соответствующий Tomcat-сервер.
Тип — Тип воркера. В данном случае используется протокол AGP версии 1.3. Без особой необходимости его менять не нужно.
Дополнительно про настройку worker-ов можно почитать тут

4) Указываем как и когда использовать Tomcat, а не Apache.
Указать можно либо в самом файле httpd.conf например,
JkMount /jsp-examples worker1
либо непосредственно при настройке виртуального хоста
(внутри тега VirtualHost):
JkMount /* worker2


Вот и все ;)

И еще немного о виртуальных хостах (Virtual hosts).
Как делать виртуальные хосты в Apache написано тут
Например (внутри тега "VirtualHost"):

ServerAdmin webmaster@localhost
ServerName mysite.com.ua
ServerAlias www.mysite.com.ua
DocumentRoot /srv/www/htdocs/mysite.com.ua
ErrorLog /var/log/apache2/mysite.com.ua-error_log
CustomLog /var/log/apache2/mysite.com.ua_log combined
JkMount /* workername # если, конечно, необходим Tomcat

Создать виртуальный хост для Tomcat еще проще:
в /conf/server.xml создать разные хосты ()
Engine name="Catalina" defaultHost="ren"
Host name="site1.com" appBase="site1apps"
Host name="site2.com" appBase="site2apps"
Engine

Для создания алиасов используем элемент alias... внутри тега host, например alias> www.site1.com.ua /alias>
и создать соответствующие директории site1apps и site2apps.
При этом нужно чтобы эти директории не перекрывались (не находились друг в друге)
Контекст по умолчанию (например, сразу после того, как вводим site1.com) должен находиться в site1apps/ROOT или site1apps/root.war, а остальные контексты (например site1.com/mycontext) в той же директории, но не ROOT.
Подробней на английском читайте тут

А как связать виртуальные хосты (Virtual hosts) Apache c Tomcat?

Для этого нужно:
1) создать витруальные хосты в Apache.
2) Создать несколько директорий для разных хостов Tomcat, поменяв необходимые порты в каждом из них. Например, у нас уже есть директория с Tomcat, которая использует порты по умолчанию, а именно: 8080 — для веб, 8009 — для AJP, 8005 — для останова Tomcat (это значит останов или крах одного сайта не повлияет на другой).
Просто копируем и переименовуем новую директорию Tomcat, например, SITE1-Tomcat.
Потом в /conf/server.xml новой директории Tomcat меняем порты:
а) порт останова с 8005 на другой, например:
Server port="8006" shutdown="SHUTDOWN"
б) веб-порт с 8080 на другой, например:
Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

в) порт для AGP c 8009 на другой, например:
Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
3) В файле workers.properties мы для каждого сайта создаем свой worker, например site1worker

4) В настройках виртуального хоста Apache внутри тега VirtualHost используем соответствующий worker, например
JkMount /* site1worker

Если что-то не получается смотрим логи модуля mod_jk, в данном примере он был указал в файле mod-jk.conf в директории JkLogFile /etc/apache2/mod-jk.log. Также не забываем о логах Apache, логах Tomcat и системных логах.

Некоторые полезные ссылки:
http://www.opennet.ru/base/dev/apache2_tomcat5.txt.html — об интеграции Apache c Tomcat (на русском)
http://www.javatalks.ru/sutra31163.php — дополнительно о кластеризации (на русском)
http://voituk.kiev.ua/2007/06/25/tomcat-cluster/ - тоже хорошо о кластеризации (на русском)
http://people.apache.org/~mturk/docs/article/ftwai.html — о кластеризации Apache Tomcat (на английском)
http://tomcat.apache.org/tomcat-6.0-doc/connectors.html - рассуждение о коннекторах от разработчиков (на английском)

2 комментария:

Ali комментирует...

Спасибо, статья помогла =)

Lexандр комментирует...

Отлично!