一、说明
由于我们的服务器操作系统大部分均为CentOS ,原有服务器使用CentOS 6.x,后续新增服务器使用CentOS 7.x,CentOS 6.x和CentOS 7.x命令行操作有比较大区别,本文以CentOS 7.x以基础环境。虽然并不推荐使用Tomcat自带的集群Session共享功能,因为其基于组播的会话数据同步会占用大量的JVM资源和网络,但对于小规模的Tomcat集群来说还是方便的,比如2-4台Tomcat服务器。其简单的实现,可以使用Nginx作负载均衡,反向代理到后方的多台Tomcat服务器。
二、准备环境
序号 | 服务器 | IP地址 | 备注 |
1 | Nginx | 172.16.1.219 80 |
|
2 | Tomcat-1 | 172.16.1.137 8080 |
|
3 | Tomcat-2 | 172.16.1.138 8080 |
|
1、Nginx服务器上下载并安装nginx-1.19.0;
2、Tomcat-1和Tomcat-2下载并安装JDK1.8和Tomcat7.x;
3、测试Web包,Tomcat-1和Tomcat-2使用同一包:
cluster/
------index.jsp
------WEB-INF/
------------web.xml
4、文件index.jsp内容
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<% String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>xx</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
SessionID:<%=session.getId()%>
<BR>
SessionIP:<%=request.getServerName()%>
<BR>
SessionPort:<%=request.getServerPort()%>
<%
//Tomcat-1服务器上的测试包:out.println("This is Tomcat Server 172.16.1.137");
//Tomcat-2服务器上的测试包:out.println("This is Tomcat Server 172.16.1.138");
out.println("This is Tomcat Server 172.16.1.137");
%>
</body>
</html>
5、文件web.xml内容
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<distributable/>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
三、Tomcat配置
在conf/server.xml中找到<Engine name="Catalina" defaultHost="localhost">元素,在其下面添加内容:
<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"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="172.16.1.138" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<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>
Membership的address="228.0.0.4"是组播地址,这是保留IP,默认228.0.0.4就可以,一般不用修改,port="45564"是组播监听端口,在同一群集中的address和port保持一致。
Receiver是配置组播接收者,接收地址address="172.16.1.138"和端口port="4000",我的理解就是这个配置是当前主机自己的信息,以这个信息加入到群集,在其它主机在发生Session更新时,可以过这个地址和端口向当前主机发送同步信息,也就是说这个配置要保证其它Tomcat可以根据address和port能够正确访问到当前主机,所以如果多个Tomcat部署在同一台服务器上时address可以设置为auto(address=”auto”),会默认解析成127.0.0.1,端口port要设置成不同的值,如Tomcat-1的port=”4000”,Tomcat-1的port=”4001”,如果Tomcat部署不同的服务器上时,则address的值应为当前主机的IP地址,port=”4000”即可。
172.16.1.137:
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="172.16.1.137" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
172.16.1.138:
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="172.16.1.138" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
Tomcat-1和Tomcat-2的其它配置基本一致,将前面准备好的cluster发布包放到Tomcat的webapps目录。
四、Nginx配置
修改conf/nginx.conf文件内容:
#user nobody;
worker_processes 10;
events {
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 600;
tcp_nodelay on;
...
upstream tomcat.cluster {
server 172.16.1.137:8080 max_fails=3;
server 172.16.1.138:8080 max_fails=3;
}
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
proxy_pass http://tomcat.cluster;
}
}
}
五、启动服务
分别启动Tomcat-1和Tomcat-2上的Tomcat服务,如果在catalina.out控制台看如下类似的输出就说配置成功了:
Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{172, 16, 1, 138}:4000,{172, 16, 1, 138},4000, alive=1009, securePort=-1, UDP Port=-1, id={127 60 19 -114 49 -45 76 77 -81 -120 -109 -59 27 56 34 123 }, payload={}, command={}, domain={}]
这里需要注意的就是要关闭防火墙,对,说的就是要关闭防火墙,我尝试过打开防火墙开放8080、4000、8005及45564等端口,反正就是无法加入集群,没仔细去研究端口开放是否完全足够和正确,但只要把防火墙关了,一切就很顺利。这时候再启动Nginx就算大功告成了,在浏览器输入访问地址:
看到没,请求被Nginx负载到不同的服务器,但SessionId保持不变。