sábado, 8 de setembro de 2012

Apache mascarando porta do Glassfish

Salve galera,

Uma situação muito comum para quem desenvolve aplicações que executam em um container java, como Glassfish ou Tomcat, é a necessidade de "mascarar" a porta do container atrás de um servidor web tradicional. Vou tentar explicar melhor.
Normalmente, subimos nosso container em uma porta diferente da 80, que é a porta web padrão, como por exemplo na porta 8080. Então para o usuário acessar nossa aplicação, ele precisa conectar em http://www.minhaempresa.com.br:8080/MinhaAplicacaoJava. Isso pode gerar alguns problemas, como o usuário não fixar a url do sistema, ou se confundir na hora da digitação, além de se tornar menos profissional, ao meu ver.
O objetivo proposto no artigo, é poder acessar a aplicação no seguinte endereço:
http://www.minhaempresa.com.br/MinhaAplicacaoJava. Sendo que teremos um servidor web apache rodando na porta 80 e um servidor java Glassfish rodando na porta 8080.

Depois de pesquisar um pouco, percebi que a maneira mais simples e transparente para atingir o objetivo, era instalar um módulo no servidor apache para tal funcionalidade. O nome do módulo é mod_jk.

Vamos  a instalação

Ambiente ondo foi implementado:

  • Glassfish 3.1.2.2 (build 5).
  • CentOS Linux release 6.0 (Final)
  • Java 7 build 1.7.0_01-b08
  • Apache 2.2.15
  • Tomcat Connectors 1.2.37

A única dependência que tive que instalar no linux foram gcc-c++ e httpd-devel, pois deu problema na compilação do conector. Caso você tenha o mesmo problema, aqui mostro como instalar no Centos:
$ yum install gcc gcc-c++ autoconf automake
$ yum -y install httpd-devel
Ubuntu
$ sudo apt-get install libapache2-mod-jk


Para fazer o processo no ubuntu, você pode acessar: http://recklessdeveloper.blogspot.com.br/2011/06/apache-e-glassfish-301-com-modjk-no.html

O conector você pode baixar em: http://tomcat.apache.org/connectors-doc/. Como eu baixei o source, então tive que compilar. A complilação é bem simples. Você deve descompactar os fontes do mod_jk, entrar na pasta e executar os seguintes comandos:
cd native/
$ ./configure --with-apxs=/usr/sbin/apxs
$ make
$ make install


Após a compilação e instalação, você deve criar o arquivo de configuração. No meu caso, ele foi criado em:
$ /etc/httpd/conf/workers.properties


Esse arquivo deve ter o seguinte conteúdo:
worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009


Observação: Essa porta não precisa estar liberada externamente caso os dois servidors estejam rodando na mesma maquina.

Agora devemos configurar o httpd.conf:

LoadModule jk_module modules/mod_jk.so

JkWorkersFile conf/workers.properties
JkLogFile /var/log/mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JKMount /MinhaAplicacaoJava/* worker1



Em JkWorkersFile configuramos o arquivo criado anteriormente. Em JKMount configuramos o contexto da nossa aplicação no Glassfish. Você pode adicionar varios pontos de montagem, um para cada aplicação.

Agora precisamos avisar o Glassfish que ele vai ouvir as requisições desse cara. Entre na pasta bin do Glassfish e execute os seguintes comandos:

$ ./asadmin create-http-listener --listenerport 8009 --listeneraddress 0.0.0.0 --defaultvs server jk-connector

$ ./asadmin set configs.config.server-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

$ .asadmin create-jvm-options  -Dcom.sun.enterprise.web.connector.enableJK.propertyFile=domain-dir=/etc/httpd/conf/workers.properties



E pronto. Agora reinicie o Apache e o Glassfish e pode testar. Caso não funcione, verifique o arquivo de logs gerado em /var/log/mod_jk.log.

Até a próxima! vlw

7 comentários:

  1. Ricardo: tudo bem. Ao compilar .. este foi a saida
    Making all in common
    make[1]: Entrando no diretório `/tmp/tomcat-connectors-1.2.37-src/native/common'
    make[1]: Nada a ser feito para `all'.
    make[1]: Saindo do diretório `/tmp/tomcat-connectors-1.2.37-src/native/common'
    Making all in apache-2.0
    make[1]: Entrando no diretório `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0'
    make[1]: Nada a ser feito para `all'.
    make[1]: Saindo do diretório `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0'
    ------------------------------------------
    aqui o make install
    make[1]: Saindo do diretório `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0'
    make[1]: Entrando no diretório `/tmp/tomcat-connectors-1.2.37-src/native'
    make[2]: Entrando no diretório `/tmp/tomcat-connectors-1.2.37-src/native'
    make[2]: Nada a ser feito para `install-exec-am'.
    make[2]: Nada a ser feito para `install-data-am'.
    make[2]: Saindo do diretório `/tmp/tomcat-connectors-1.2.37-src/native'
    make[1]: Saindo do diretório `/tmp/tomcat-connectors-1.2.37-src/native'

    ===========================================
    Aqui quando tento habilitar
    asadmin set -p 8484 configs.config.server-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

    saida --->
    No object matches the specified name "configs.config.server-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled"


    ResponderExcluir
    Respostas
    1. Olá Jonas,

      Que sistema operacional você está usando? O comando para criar o listener executou sem problemas? Parece que o jk-connector não foi criado. Faça o seguinte:

      Entre no console do glassfish (asadmin) e execute o comando list-protocols, e veja se o jk-connector é listado.
      ResponderExcluir

      Excluir
    2. Olá Ricardo, excelente tutorial, parabéns.

      Gostaria de saber se existe a possibilidade de colocar o sistema rodando diretamente no domínio, por exemplo, quando acesso "meusite.com.br", ele chamar a minha aplicação "meusite.com.br:8080/MinhaAplicacaoJava".

      Obrigado desde já.

      Excluir
    3. Olá Rafael,

      Sim, você pode fazer isso. Eu conheço duas formas. Uma delas é você usar virtual hosting, onde você mapeia a requisição de um determinado domínio para uma aplicação. Você pode dar uma olhada aqui:

      http://thierrywasyl.wordpress.com/2009/06/27/virtual-hosting-on-glassfish/

      Nesse caso você pode ter vários hosts em um glassfish.

      Outra maneira mais simples, é fazer o deploy da aplicação e colocar / no context root.

      http://hobione.wordpress.com/2008/01/15/glassfish-docroot-for-%E2%80%9Croot%E2%80%9D-application-in-the-server-so-url-would-be/

      Depois você colocaria o glassfish rodando na porta 80, ou faria o mapeamento com o mod_jk.

      Excluir
    4. Legal Ricardo, estou com um pequeno problema antes disso, segui a configuração de acordo com o seu tutorial, mas quando faço uma requisição para o domínio configurado, ele dispara as seguintes linhas de erro no arquivo de log "mod_jk.log":

      [Tue Nov 27 18:24:47 2012] [2140:2936] [debug] map_uri_to_worker_ext::jk_uri_worker_map.c (1131): Attempting to map URI '/index.php' from 1 maps

      [Tue Nov 27 18:24:47 2012] [2140:2936] [debug] find_match::jk_uri_worker_map.c (945): Attempting to map context URI '/myapp/*=worker1' source 'JkMount'

      [Tue Nov 27 18:24:47 2012] [2140:2936] [debug] jk_map_to_storage::mod_jk.c (3798): no match for /index.php found

      Eu não entendi o porque da busca de index.php.

      Agradeço desde já a ajuda.

      Excluir
    5. O seu apache está configurado funcionando corretamente? Pelo que sei, o mod_jtk intercepta as requisições e verifica se deve fazer alguma coisa, caso não precise fazer nada, elas são devolvidas para o apache.

      Excluir
    6. Então Ricardo, alguns minutos atrás consegui resolver o problema.

      Eu estava utilizando um Virtual Host para tratar a requisição, como no exemplo abaixo:

      VirtualHost *:80

      ServerName localhost

      JkMount /* worker1

      /VirtualHost

      O problema é que, como configuração geral do apache, ele tentava utilizar o mod_jk para todos esses tipos de arquivos quando uma requisição era feita:

      DirectoryIndex index.php index.php3 index.html index.htm

      Por isso na mensagem de erro, dizia que ele não havia conseguido encontrar o /index.php.

      Resolvi esse problema, acrescentando a seguinte linha no meu Virtual Host:

      VirtualHost *:80>

      ServerName localhost

      DirectoryIndex index.html index.htm

      JkMount /* worker1

      /VirtualHost

      Assim ele tenta acessar apenas o arquivo index.html que eu preciso.

      Excluir