Java应用服务器之tomcat会话复制集群配置的示例详解
作者:Linux-1874 发布时间:2022-08-24 07:28:27
会话是识别用户,跟踪用户访问行为的一个手段,通过cookie(存在客户端)或session(存在服务端)来判断本次请求是那个客户端发送过来;常用的会话保持有绑定会话,就是前边我们聊的在代理上通过算法或通过给客户端响应首部加cookie这种方式来保持同一cookie或同一ip地址的请求始终发送到同一后端server进行响应;但是这样的会话绑定的方式存在一个问题,就是当后端某一server宕机,那么之前上面的所有会话信息将消失,那么后续的客户端来请求,代理是否要把请求调度到后端宕机的server呢?如果说调度上去呢,那么用户之前的会话信息又没有了,如果说不调度呢,那么用户将不能够得到服务;所以对于这种情况我们需要把会话都同步到后端所有server上,即便某一台或几台后端server宕机了,不会导致用户的会话信息丢失,同样服务也是可用的;这种冗余的方式保存会话信息,使得用户的会话信息能够在任何一台后端server上都会有;这也意味着只要有用户来请求,前端调度器可以任意把请求调度到后端的某一台server上,然后服务端把本次请求的用户会话信息通过广播的方式,通知给其他后端server,这样一来这个客户端后续来请求,不管调度到后端那一台server上,因为后端server上都有这个客户端之前请求的会话信息,所以不管到那一台都能够识别;对于tomcat来讲,它内部就有一个组件支持这样的功能,它可以基于多播通信的方式,把会话信息同步给后端其他节点,这个组件就是cluster;
示例:使用tomcat cluster组件来定义tomcat的会话复制集群
环境说明
名称 | ip地址 | 端口 |
代理Nginx | 192.168.0.41 | 80 |
应用服务tomcatA | 192.168.0.42 | 8080 |
应用服务tomcatB | 192.168.0.43 | 8080 |
准备测试页面,以及配置tomcatA
提示:以上是myapp里的内容以及文件目录结构
提示:以上配置表示部署一个/myapp的应用,它的文件路径在/webapps/myapp,并且在engine上配置了 jvmRoute=“tomcatA”;
提示:cluster配置需要注意上面打红框的位置,在官方配置文档中,后面的<ClusterListener 的后面没有把标签闭合了,我们在使用时需要给它闭合了,否则会出现语法错,导致tomcat起不来;其次就是我们需要更改 * 的ip地址,默认它是auto,auto表示自动监听本机一个地址,这个地址也可能是127.0.0.1,如果监听在127.0.0.1,那么主机就不能够接收到,其他节点发来的会话信息;说下这个配置文件吧,cluster组件中主要就是定义了DeltaManager的属性,该组件用于处理增量会话的事务,也就是用这个管理的功能实现多节点复制会话信息;其次我们要在其cluster内部定义个chanel,这个组件主要定义集群通信和各成员的一些属性,比如成员关系判定呀, * 和发送器;Membership组件用于定义成员关系判定的,里面主要定义多播地址和端口等属性,如果多播地址相同,那么就是同一集群的成员,否则不是;Receiver主要用于定义 * 的相关属性,比如 * 监听的地址和端口超时时长,最大线程等等;Sender用于指定发送器,发送器我们这里不需要认为手动定义,用官方给定的示例即可;后面的Interceptor主要定义了tcp报文的检查以及消息摘要,后面两台哦Interceptor主要作用是保证tcp报文的完整和正确性;Deployer主要用于定义部署应用相关属性,它的主要作用是如果我们定义了集群,我们可以在集群成员中的一台server上部署好应用,然后其他成员可以通过网络自动部署;通常我们建议使用这个自动部署的功能;
完整的server.xml配置
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<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="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
<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" />
<Context path="/myapp" docBase="/webapps/myapp" reloadable=""/>
<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="192.168.0.42"
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"/>
<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.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
</Host>
</Engine>
</Service>
</Server>
给我们定义的应用修改器web.xml 在其中加上<distributable/>元素
提示:对于web.xml配置文件,我们可以从/etc/tomcat/中复制一份到自己的应用目录结构里,然后在非注释掉位置加上<distributable/>元素即可
对于tomcatB来说,我们也需要准备好同样的文件,为了区分,我们把index.jsp修改成tomcatB ,在配置文件中我们需要修改 * 的监听地址,以及jvmRoute的值,其他的都可以不变
到此tomcat会话复制集群就配置好了;其实从上面的配置文件可以看大,tomcat的会话复制集群就是利用多播地址通信,一个请求不管到集群那个基点,它都会通过多播通信,把会话信息以组播的方式发送给其他成员;这里建议把 * 的地址专门用张网卡配置好地址;接下来我们启动下tomcatA,tomcatB,然后看看日志是否初始集群成功,并接收到集群成员 * 的地址;
提示:这里注意一点如果tomcat启动特别慢,就是8005端口要等很久才起来,可以尝试安装rng-tools,并启动rngd,这样可以加快tomcat启动
提示:如果在tomcatA的日志中能够看到tomcatB的 * 地址和端口,那么就表示tomcatA已经识别到tomcatB,并把tomcatB当作集群成员加入到集群;同样在tomcatB的日志中能够看到tomcatA的 * 地址和端口,表示tomcatB已经识别tomcatA并把它加入到集群;
配置nginx负载均衡后端两台tomcat server
提示:这里需要主要反代时需要把反代的URI和后面proxy_pass后面的URI相同,否则代理后,会话复制集群不会生效;
验证:检查nginx的配置文件语法,启动nginx访问192.168.0.41/myapp看看有什么变化
提示:可以看到访问192.168.0.41/myapp时sessionid始终没有发生变化,变化的只有后面的jvmRoute的值和页面的值;这说明我们访问nginx时,nginx也基于自己的轮询算法把请求调度到后端去了,第一次访问时,后端server会响应一个set-cookie的首部,把当前访问的页面的session信息响应给客户端,第二次访问客户端就会把上一次访问相应的cookie带上去访问,这时后端server接受到客户端发送过来的cookie,然后就在自己内存里找对应的session信息;由于后端server是把session信息基于多播通信的方式共享给集群其他节点,所以第二次不管调度到那台server上,对应server都会有该客户端第一次访问服务端的session信息;所以我们第二次访问时,sessionid还是第一次访问服务器的sessionid,后面的tomcatB表示由tomcatB这个jvmRoute处理的这次请求;
来源:https://www.cnblogs.com/qiuhom-1874/p/13363590.html
猜你喜欢
- 一、代理模式 代理模式是常用的java设计模式,特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委
- 周末了,觉得我还有很多作业没有写,针对目前大家对OOM的类型不太熟悉,那么我们来总结一下各种OOM出现的情况以及解决方法。我们把各种OOM的
- Java停止线程的逻辑(协同、通知)在Java程序中,我们想要停止一个线程可以通过interrupt方法进行停止。但是当我们调用interr
- 1、输出矩形以此矩形案例(4行,9列的矩形)为例public static void main(String[] args) {  
- Spring MVC高级技术包括但不限于web.xml配置、异常处理、跨重定向请求传递数据1、web.xml文件的配置<!DOCTYP
- 1.jsch官方API查看地址(附件为需要的jar) http://www.jcraft.com/jsch/2.jsch简介 JSch(Ja
- 本文介绍了Spring Boot Admin监控服务上下线邮件通知,分享给大家,具体如下:微服务架构下,服务的数量少则几十,多则上百,对服务
- 博主在初学注解的时候看到网上的介绍大部分都是直接介绍用法或者功能,没有实际的应用场景,篇幅又很长导致学习的时候难以理解其意图,而且学完就忘Q
- 1、在java的构造方法中提供了 异常链.. 也就是我们可以通过构造方法不断的将 异常串联成一个异常链... 之所以需
- 1、什么是GradleGradle是一种结合了Ant和Maven两者优势的下一代构建工具,既有Ant构建灵活性的优点,也保留Maven约定优
- 比较适合新手。逻辑上仍然有点问题。可以用于学习java文件操作下载地址:http://yun.baidu.com/share/link?sh
- 目录背景解决方案1、设置热点数据永远不过期。2、加互斥锁,互斥锁参考代码如下:总结说明1、缓存中有数据,直接走下述代码就返回结果了2、缓存中
- Activiti项目是一项新的基于Apache许可的开源BPM平台,本文就来简述一下Activiti常用类。具体如下:一、为什么要使用工作流
- 1、右值1.1 简介首先区分一下左右值:左值是指存储在内存中、有明确存储地址(可取地址)的数据;右值是指可以提供数据值的数据(不可取地址)如
- IDEA service层跳转实现类的快捷图标消失了,但别人IDEA同样的代码可以正常看到跳转图标。。(暗示:这只是你的IDEA 编译器的b
- 在项目中使用Maven管理jar包依赖,往往会出现以下状况:1、国内访问maven默认远程中央镜像特别慢;2、使用阿里的镜像替代远程中央镜像
- JavaFx中其实也可以直接使用字体图标iconfont的,只需要加载ttf字体文件,之后设置unicode即可,具体可以看我给出的代码既然
- 使用例子如下,用JAVA 运行Sort1, 输入你要排序的文件路径 , 如 例子是对H:\下的文件和它所有子文件夹下的文件进行排序2, 输入
- 1.概述注解可以定义到方法上,类上,一个注解相当与一个类,就相当于实例了一个对象,加上了注解,就相当于加了一个标志。常用的注解:@Overr
- 当我们在项目中登录使用验证码的时候,不妨试试Kaptcha生成验证码,非常简单1、首先,我们在pom.xml文件中引入kaptcha的mav