tomcat集群内置session复制
应用程序服务会产生session;通过多播通讯的信道传递给同一个集群中的其余tomcat节点,这样用户的状态信息在当前集群中的所有tomcat上都是存在的,从而追踪到用户的活动;
缺点:当用户访问量较大时,则多播信道很快就会出现大量的多播信息,会造成拥堵,大量延迟;并且每个session数据都会存储在集群内的每个tomcat节点上,则会消耗每个节点的大量内存空间;
调度器向后端发送请求时,每个请求都可以模拟为一个单独的线程发送请求,早期时候想要追踪session,要么基于cookie绑定,要么基于客户端源ip绑定;
session是在服务器内存中被程序使用的,java是纯面向对象的编程语言,所以session对象数据都是放置在java程序运行的内存空间中被程序使用的;但是如果tomcat宕机,则所有session将会全部丢失,所以为了使session能够持久化保存,tomcat默认通过会话管理器组件,自动每隔一段时间将session同步到磁盘,一但tomcat宕机,会在tomcat重新启动后把session载入进来,避免session丢失;
delta manager会话管理组件,是用于tomcat会话集群中的解决方案;会把集群内的tomcat节点上的新session同步到集群内的其余tomcat节点,其余节点的delta manager接收到新的session后,会把新session合并到自己所管理的会话中。delta manager是一个跨节点的会话同步工具,实现了每个tomcat节点都可以写和读;
tomcat集群通过多播方式进行通讯,默认监听地址为228.0.0.4,端口为45564;由于每一个节点都要接收其他节点发送来的会话,因此每一个节点都应该监听在一个套接字上,通过一个TCP套接字接收对方传来的数据,同时本身应该有一个发送器,把自己本身的session内容基于多播信道发送给集群内其余节点;为了避免传输过程中发生错误,需要校验信息的完整性,有探测TCP传输中错误和验证整个报文完整性的各种组件;
实现架构
tomcat集群配置
http://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html #tomcat集群配置官方文档
集群内每个tomcat节点都需要进行配置;
1、catalina.sh stop #修改配置文件前,需要先停止tomcat进程,否则修改完后退出tomcat会报错
2、vim /usr/local/tomcat/conf/server.xml #tomcat集群配置
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA"> #每个tomcat节点都需要指定不同的jvmRoute值
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"#指定使用的会话管理组件为delta manager
expireSessionsOnShutdown="false" #指定当节关闭后会话是不会超时的
notifyListenersOnReplication="true"/> #主要监听资源变动;当session变化时通知监听器
<Channel className="org.apache.catalina.tribes.group.GroupChannel"> #Channel组件定义多播会话通讯信道
<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" #接收器;接收session
address="192.168.39.101" #指定接收器地址;不指定则默认自动绑定一个本机可用地址
port="4000" #接收端口
autoBind="100" #自动绑定间隔时间,单位毫秒
selectorTimeout="5000" #对应地址的超时时间
maxThreads="6"/> #接收session的最大线程数;取决于集群规模
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> #Sender发送器;把自己的会话发送给其余节点;PooledParallelSender轮询并发发送器,获取成员列表,把session轮询逐一发送给成员
<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.MessageDispatchInterceptor"/> #探测器;用于探测传输过程中是否存在传输错误;检查报文完整性
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" #阀门;过滤出和session复制相关的报文
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> #JVM路由绑定器;判断出集群内jvm进程数量(tomcat实例),和engine上jvmRoute标识相关;jvmRoute用于识别出集群中不同的engine
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" #定义部署器
tempDir="/tmp/war-temp/" #同步给其余节点时,指定临时目录
deployDir="/tmp/war-deploy/" #指定所要部署的目标目录
watchDir="/tmp/war-listen/" #监控所要发生变化的目录
watchEnabled="false"/> #是否开启监控功能
#部署器;把一个应用程序的会话部署为集群会话时,当部署应用程序时,只需要把应用程序部署到一个节点上,部署器会自动把应用程序内容同步给其余成员部署;不要开启此功能,会出错误
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> #侦听器;侦听集群中资源内容变化;整个集群内任何一个节点的session发生变化时,侦听器能够侦听资源变动
</Cluster>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="myapp" docBase="/webapps/myapp" reloadable=""/> #给默认虚拟主机做一个location别名,指定资源真实路径;此处可有可无,根据自己意愿进行配置
###注意:
(1)虽然配置了tomcat集群session复制,但是前端调度器最好还是基于cookie做会话绑定;同步session是有延迟的,如果是轮询,则有可能调度的节点session还未进行同步;如果做了cookie绑定,则一个节点故障,则重新调度时,其余节点还会有session;
(2)将cluster组建放置在engine或host组建中即可;放在engine中对所有host生效,放在一个host中,只对当前host生效;
3、mkdir /webapps/myapp/WEB-INF -pv
4、cp /usr/local/tomcat/conf/web.xml /webapps/myapp/WEB-INF/ #web.xml复制到当前应用的WEB-INF目录下,则只对此应用生效,如果修改默认的web.xml则对所有应用生效
5、chown tomcat.tomcat /webapps -R
6、vim /webapps/myapp/WEB-INF/web.xml
<web-app
<distributable/> #集群内每个tomcat节点都需要配置此项;此项配置在web-app下,不要配置在web-app下其他组件内
7、catalina.sh start
nginx配置
1、vim /etc/nginx/nginx.conf
http {
upstream tomcatservers { #配置反向代理
server 192.168.39.101:8080;
server 192.168.39.102:8080;
}
server {
...
location / {
proxy_pass http://tomcatservers; #nginx会重新构建请求报文,访问tomcat默认虚拟主机的指定应用程序
}
2、systemctl restart nginx
3、浏览器访问:http://192.168.39.100/myapp