Показаны сообщения с ярлыком Tomcat. Показать все сообщения
Показаны сообщения с ярлыком Tomcat. Показать все сообщения

вторник, 29 октября 2013 г.

Настраиваем связку Tomcat+Nginx

Это сугубо практичный пост: просто набор команд для настройки "маленького сервера с блекджеком и танцовщицами" для хостинга java-приложений. Настраивал сегодня wds на Ubuntu 12.04 и, наверное, в десятый раз вспоминал всё это. Теперь всё будет в одном месте.

1. Java
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java6-installer


в конец ~/.bashrc добавляем 
export JAVA_HOME=/usr/lib/jvm/java-6-oracle 

2. Tomcat
sudo apt-get install tomcat7

Tomcat будет стартовать при старте системы, приложения будут разворачиваться на порту 8080 (каждое в своём соответствующем контексте) если .war залить в  /var/lib/tomcat7/webapps/.
Так уже можно работать, но для клиентов нужно спрятать tomcat за прокси, чтобы иметь возможность фровардить порты и прятать контексты за доменными именами. 

3. Nginx
wget http://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key

В конец файла /etc/apt/sources.list добавляем строки:
deb http://nginx.org/packages/ubuntu/ codename nginx 
deb-src http://nginx.org/packages/ubuntu/ codename nginx

где codename - имя дистрибутива (посмотрите его в строчках выше или получите из сat /etc/*-release) 

sudo apt-get update
sudo apt-get install nginx

Это почти всё. Осталось только настроить проксирование запросов. Допустим, мы пишем конфиг для нашего хоста newgoogle.com, приложение для которого мы в tomcat-e развернули на контексте /ng:
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/newgoogle.com.conf
sudo vim /etc/nginx/conf.d/newgoogle.com.conf
меняем server_name на newgoogle.com и меняем location-секцию на: 
    location / {
        proxy_pass        http://localhost:8080/ng/;
        proxy_set_header  X-Real-IP  $remote_addr;
    }

P.s.: Ничего сверхестественного тут нет, любой админ сделает вам это одним пальцем с закрытыми глазами после восьми банок пива. Но зачем его беспокоить? То, что описано тут - достаточно тривиально, и сделав это однажды просто повторяйте всегда при необходимости точно также. Пусть гуру-админы занимаются тюнингом наших серверов и тонкой настройкой сетевого трафика. Простые вещи делаем сами.

пятница, 1 февраля 2013 г.

Создание websocket-приложения на Tomcat 7

Ранее я писал о своём опыте использования технологии websocket в связывании серверного java-приложения и android-клиента. Я предлагал использовать jetty 8 и делал обычное консольное java-приложение. Но если у нас websocket является частью web-приложения с сервлетами и т.п., то такой подход уже не годится. Да и зачем тянуть в свой проект jetty, если наш старый добрый Tomcat с версии 7.0.27 уже поддерживает websocket самостоятельно?
Сегодня мы сделаем websocket-приложение с помощью одного только Tomcat и javascript на клиенте.

WebSocketServlet
Ключевым механизмом реализации websocket в Tomcat является класс org.apache.catalina.websocket.WebSocketServlet. Он расширяет обычный javax.servlet.http.HttpServlet а значит мы можем "мапить" его на url как это делаем с остальными своими сервлетами. Собственно сама наша реализация крайне проста:

import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
 
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
 
@WebServlet(name = "WsServlet", urlPatterns = {"/ws"})
public class WsServlet extends WebSocketServlet {
    @Override
    protected StreamInbound createWebSocketInbound(String s, HttpServletRequest httpServletRequest) {
        return new WsConnection();
    }
}

Мы тут реализуем метод, который возвращает объект, отвечающий за обслуживание websocket-соединения. Сам объект WsConnection выглядит так:

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;
 
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.concurrent.ArrayBlockingQueue;
 
public class WsConnection extends MessageInbound {
 
    public static ArrayBlockingQueue<WsOutbound> connections = new ArrayBlockingQueue<WsOutbound>(100);
    private WsOutbound outbound;
 
    @Override
    protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
    }
 
    @Override
    protected void onTextMessage(CharBuffer charBuffer) throws IOException {
        broadcast(charBuffer.toString());
    }
 
    @Override
    protected void onOpen(WsOutbound outbound) {
        this.outbound = outbound;
        connections.add(outbound);
    }
 
    @Override
    protected void onClose(int status) {
        connections.remove(this.outbound);
    }
 
    private void broadcast(String message) {
        for (WsOutbound connection : connections) {
            try {
                CharBuffer buffer = CharBuffer.wrap(message);
                connection.writeTextMessage(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Тут мы расширяем MessageInbound, что позволяет нам переопределяя соответствующие методы обрабатывать события установления и обрыва соединения, получения сообщения и т.п. При подключении нового клиента мы добавляем его в синхронизированную очередь, при отключении - удаляем. При получении сообщения просто рассылаем его всем подключенным клиентам. Такой вот чатик :)
На клиентской стороне можно сделать много красивостей, но мы обойдёмся минимальным количеством кода. Только чтобы убедиться в работоспособности сервера.

<html>
  <head>
    <title></title>
      <script type="text/javascript">
          var socket = new WebSocket("ws://mydomain.com:8080/ws");
 
          socket.onopen = function() {
              alert("Соединение установлено.");
          };
 
          socket.onclose = function(event) {
              if (event.wasClean) {
                  alert('Соединение закрыто');
              } else {
                  alert('Обрыв соединения');
              }
              alert('Код: ' + event.code + ' причина: ' + event.reason);
          };
          socket.onmessage = function(event) {
              var logarea = document.getElementById("log");
              logarea.value = event.data+"n"+logarea.value;
          };
          socket.onerror = function(error) {
              alert("Ошибка " + error.message);
          };
 
          function send() {
              var s = document.getElementById("in").value;
              socket.send(s);
          }
 
      </script>
  </head>
  <body>
    <input type="text" id="in" /><input type="button" onclick="send()" value="send" />
    <br/>
    <textarea id="log" rows="8" cols="20">

  

пятница, 24 декабря 2010 г.

связка Apache+Tomcat

На днях пришлось решать задачу по настройке связки Apache 2+Tomcat 6.02 на Debian 5 сервере. Пришлось в очередной раз порыться в инете в поисках инструкций. Дабы не повторять этот процесс в следующий раз решил выложить тут алгоритм, который получил в итоге.

Итак, дано: VDS с Debian 5, Apache 2 уже установлен, на нём настроены несколько виртуальных хостов. Требуется: в поддиректории одного из сайтов исполнять jsp - страницы средствами Tomcat.

1. Устанавливаем JDK. 

apt-get install python-software-properties 
add-apt-repository ppa:sun-java-community-team/sun-java6 
apt-get update 
apt-get install sun-java6-jdk

Желательно после установки в /etc/profile добавить строки:

JAVA_HOME="/usr/lib/jvm/java-6-sun/"
export JAVA_HOME

2. Устанавливаем Tomcat:

Берём с официального сайта ссылку на последнюю версию и wget-ом вытягиваем её к себе на сервер. Распаковываем и переносим "на место постоянного проживания":

tar -xzvf apache-tomcat-6.0.29.tar.gz
mv apache-tomcat-6.0.29 /opt/tomcat

3. Делаем init-скрипт для запуска/останова/перезапуска Tomcat-а:

в /etc/init.d/tomcat
пишем:

#!/bin/sh
# Tomcat Init-Script
case $1 in
start)
sh /opt/tomcat/bin/startup.sh
;;
stop)
sh /opt/tomcat/bin/shutdown.sh
;;
restart)
sh /opt/tomcat/bin/shutdown.sh
sh /opt/tomcat/bin/startup.sh
;;
esac
exit 0

Ставим на него права 0755 и делаем:
update-rc.d tomcat defaults

4. Настраиваем логин в Tomcat Manager:

редактируем /opt/tomcat/conf/tomcat-users.xml

<tomcat-users>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="USERNAME" password="PASSWORD" roles="admin,manager"/>
</tomcat-users>


5. Проверяем работу "свежеустановленного" сервера:

/etc/init.d/tomcat start
по адресу http://ваш домен:8080/manager/html будет работать админка Tomcat-а.

6. Настраиваем модуль для связи Tomcat и Apache

Устанавливаем модуль для Apache:
aptitude install libapache2-mod-jk

взаимодействие между серверами реализуется с помощью worker-а. Описываем его конфигурацию в файле /etc/apache2/workers.properties:

workers.tomcat_home=/opt/tomcat
workers.java_home=/usr/lib/jvm/java-6-sun
ps=/
worker.list=default
worker.default.port=8009
worker.default.host=localhost
worker.default.type=ajp13
worker.default.lbfactor=1

Тут, как видим, устанавливается имя нашего worker-а: default
Описываем конфигурацию модуля в файле /etc/apache2/conf.d/jk.conf

JkWorkersFile /etc/apache2/workers.properties
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel error
Перезагружаем сервера:
/etc/init.d/apache2 stop
/etc/init.d/tomcat restart
/etc/init.d/apache2 start

7. Создаём виртуальный хост на Tomcat и привязываем его к выбранному виртуальному хосту на Apache

добавляем в /opt/tomcat/conf/server.xml
<host name="www.testsrv.local" appBase="/var/www/vhost1"
unpackWARs="true" autoDeploy="true">
<context path="" docBase="htdocs" debug="0" reloadable="true"/>
<valve className="org.apache.catalina.valves.AccessLogValve"
directory="/var/www/vhost1/logs" prefix="tomcat_access_" suffix=".log"
pattern="common" resolveHosts="false"/>
</host>

Пути к директориям указываем соответственно те, где будут лежать наши .jsp

В секцию выбранного витуального хоста Apache в /etc/apache2/apache2.conf добавляем строку:

JkMount /j/*.jsp default

где /j/ - путь к директории, где будут лежать .jsp - страницы относительно корня сайта в Apache.

8. Проверяем:

Создаём файл test.jsp в выбранной директории:

<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
Today is: <%= new java.util.Date().toString() %>
</body>
</html>

и заходим по адресу http://ваш домен/j/test.jsp
наблюдаем работающую .jsp страницу, которую выполнил Tomcat по "поручению" Apache :)