Load Balancing e Clustering usando mod_proxy_ajp no Apache HTTP Server 2.2.21 e no Tomcat 7.0.23

2

Eu tenho lutado para fazer o balanceamento de carga e o clustering funcionando usando essa combinação:

  • Apache HTTP Server 2.2.21 (httpd-2.2.21-win32-x86-openssl-0.9.8r) usando o mod_proxy_ajp com a sessão fixa ativada.
  • Apache Tomcat 7.0.23 (apache-tomcat-7.0.23-windows-x64)
  • Atualização 2 do JDK 7 (jdk-7u2-windows-x64)
  • Windows 7 64 bits
  • Primavera 3.1

Alguns links que eu li:

Esta é minha configuração:

link

# Required Modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule status_module modules/mod_status.so

# Reverse Proxy
<Proxy balancer://mybalancer>
    BalancerMember ajp://localhost:8301 route=s1
    BalancerMember ajp://localhost:8302 route=s2
    BalancerMember ajp://localhost:8303 route=s3
</Proxy>
ProxyPass / balancer://mybalancer/ stickysession=JSESSIONID|jsessionid

# Forward Proxy
ProxyRequests Off

<Proxy *>
    Order deny,allow
    Deny from none
    Allow from localhost
</Proxy>

# Balancer-manager, for monitoring
<Location /balancer-manager>
    SetHandler balancer-manager

    Order deny,allow
    Deny from none
    Allow from localhost
</Location> 

server.xml para cada tomcat (diferença apenas no número da porta)

<Server port="8001" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JasperListener" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

    <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
            type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved"
            factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>

    <Service name="Catalina">
        <Connector port="8101" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8201" />

        <Connector port="8301" protocol="AJP/1.3" redirectPort="8201" />

        <Engine name="Catalina" defaultHost="localhost" jvmRoute="s1">

            <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
                <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" 
                    notifyListenersOnReplication="true" />
                <Channel className="org.apache.catalina.tribes.group.GroupChannel">
                    <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4" port="45564" frequency="500" dropTime="3000" />
                    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
                        <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
                    </Sender>
                    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                        address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6" />
                    <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
                    <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" />
                </Channel>
                <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter="" />
                <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />
                <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
                <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
            </Cluster> 

            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
            </Realm>
            <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
                <Valve className="org.apache.catalina.valves.AccessLogValve"
                    directory="logs" prefix="localhost_access_log." suffix=".txt"
                    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
            </Host>
        </Engine>
    </Service>

</Server>

numeração de portas (verifique se nenhuma instância usa a mesma porta se implantada no mesmo servidor)

  • 80 - > Porta do Servidor HTTP Apache
  • 80xx - > Porta SHUTDOWN do servidor Tomcat
  • 81xx - > Porta do conector do Tomcat (HTTP)
  • 82xx - > Porta de redirecionamento SSL do Tomcat
  • 83xx - > Porto AJP Tomcat
  • 40xx - > Tomcat tcp recebe porta para o NioReceiver

Controlador de mola

@Controller
@RequestMapping("/login")
public class LoginController {
    @RequestMapping(method=RequestMethod.GET)
    public String show(@ModelAttribute("user") User user, HttpServletRequest request) {
        user.setUsername("YUSUF");

        HttpSession session = request.getSession();
        Integer tambah = (Integer) session.getAttribute("tambah");
        if(tambah == null) tambah = new Integer(1);
        else tambah = new Integer(tambah.intValue() + 1);
        session.setAttribute("tambah", tambah);

        return "login";
    }
}

login.jsp

    <div class="mainFooter">
        Tambah = ${sessionScope.tambah}
        <br>
        ID = ${pageContext.session.id}
    </div>

Até agora, a parte de balanceamento de carga está funcionando, mas a replicação da sessão não está. Basicamente, o que eu quero é que se eu continuar pressionando a página de login, a variável "tambah" será incrementada e mantida na sessão. E se o nó atual do tomcat estiver inativo, a sessão será replicada para o próximo nó do tomcat e os dados não serão perdidos. Mas isso é o que acontece:

Tela de login:

Tambah = 39 
ID = C1D59C8CA5D10EB98C1DE08AC618204D.s1 

Eu retiro o tomcat1 e mantenho o tomcat2 e o tomcat3 rodando, aqui está a tela de login:

Tambah = 1
ID = A83KJFO38FK30FJDL40FLREI39FKDKGD.s2

Parece que o failover não está funcionando, a sessão não é replicada e o aplicativo criou uma nova sessão. Alguém pode me ajudar na direção certa?

Obrigado

EDIT: Eu resolvi a questão, graças a @Shane Madden, esta é a mudança que eu fiz:

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                        address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6" />

Para cada Tomcat, a porta do receptor tcp deve ser diferente (se estiver executando no mesmo servidor), por exemplo, use 4001, 4002, 4003, etc.

    
por Yusuf S 29.12.2011 / 01:17

2 respostas

2

Graças aos comentários do @Shane Madden, reli os documentos do cluster do tomcat no link , especialmente nesta parte - > "Se suas instâncias do Tomcat estiverem em execução na mesma máquina, verifique se o atributo tcpListenPort é exclusivo para cada instância. Na maioria dos casos, o Tomcat é inteligente o suficiente para resolver isso por meio da detecção automática de portas disponíveis no intervalo 4000-4100".

As alterações que fiz estão em cada servidor server.xml da instância do Tomcat, certifico-me de que cada porta seja diferente (por exemplo, 4001, 4002, 4003):

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
  address="auto" port="4001" autoBind="100" 
  selectorTimeout="5000" maxThreads="6" />

E voila! load-balancing e clustering estão funcionando (com a configuração mais básica, é claro). Espero que este post possa ajudar outras pessoas nas configurações iniciais.

    
por 29.12.2011 / 10:46
0

Eu tenho uma pilha de software semelhante (apache 2.2.15 e tomcat 7.0.65), mas todo o Linux e eu nos deparamos com o seguinte problema com a página de status do balanceador: Em vez de entrar na página de status, a diretiva ProxyPass

ProxyPass / balancer://mybalancer/ stickysession=JSESSIONID|jsessionid

estava redirecionando a solicitação / balancer-manager para um dos tomcats (e assim obtendo uma página de erro do tomvat). Eu trabalhei em torno do problema, definindo o ProxyPass para algo mais restritivo do que apenas /

ProxyPass /myapp balancer://mybalancer/myapp stickysession=JSESSIONID|jsessionid

Não tenho certeza se essa é a maneira correta de fazer isso?

    
por 16.06.2016 / 11:06