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 "%r" %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.