tomcat源码阅读之BackupManager
一、 配置:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="6">
<Manager className="org.apache.catalina.ha.session.BackupManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"
mapSendOptions="6"/>
<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.106"
port="5000"
selectorTimeout="100"
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"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
与DeltaManager配置的区别就是将manager元素的className由DeltaManager换成了BackupManager;
二、 BackupManager会话管理原理:
1、 DeltaManager会话管理器采用的全节点复制,即每个session的创建、修改和释放都广播到集群中其他所有节点上,当集群节点增加时,网络流量会呈平方趋势增长,因此无法构建较大规模的集群,BackupManager会话管理器采取另一种会话管理方式,每个会话只有一个备份,他会使网络流量随节点数的增加呈线性趋势增长,大大减少了网络流量,可以构建较大规模的集群;
2、 backupManager会话管理器中存在三种类型的节点:源节点、备份节点和代理节点,创建会话时,该会话保存在该节点上,每次对这个会话的访问都被分配到这个节点上,这个节点被称为源节点,会话创建后,会在集群节点中找到一个节点用于存放该会话的备份,这个节点称为备份节点,集群中除了源节点和备份节点外,其他节点都会保存一个该会话的位置信息,这些节点被称之为代理节点;因此每个会话都有一个源节点,一个备份节点和若干个代理节点;
3、 如果某个会话的源节点宕机了,这时他的请求会随机分配到其他任意节点上,有两种情况:
a) 分配到备份节点上:此时仍然能获取到该会话,同时将这个节点上的这个会话标记为源节点,且继续选取一个其他节点作为该会话的备份节点,并将会话信息拷贝到新的备份节点上;
b) 分配到了代理节点上:此时肯定在代理节点上找不到该会话,于是他向集群所有节点查询该会话,该会话的备份节点收到查询请求后,将该会话信息拷贝到代理节点上,此代理节点升级为该会话的源节点,同时告知集群中其他节点,该会话的源节点已经变更;
4、 集群节点列表的维护主要是通过启动时向所有节点广播节点信息以及心跳去维护,如下图所示:n1启动时向其他节点广播自己的信息,其他节点收到信息后将n1添加到自己的列表,而n1则把n2,n3,n4添加到自己的列表,接着按照一定的时间间隔向其他节点发心跳,如下图,假如n2未给n1响应信息,n1则把n2从自己的列表中删除;
5、 backupManager使用Round robin算法用于备份节点的选择,按照顺序依次从集群节点列表中选择节点,代码如下:
三、 UML图:
1、 会话管理器其实就是对会话集操作的封装,从设计角度看,为了改变会话集的操作行为,只需继承ConcurrentHashMap类并重写其中一些方法即可实现,例如put、get、remove等等操作实现跨节点操作。于是tomcat的BackupManager对整个会话集的跨节点操作被封装到一个继承ConcurrentHashMap类的LazyReplicatedMap子类中;
2、 AbstractReplicatedMap类的innerMap成员变量保存了sessionId和MapEntry的映射关系,MapEntry则是对session、源节点成员及备份节点等的封装,从上面的UML图可以看出MapoEntry的成员变量:primary存储了该session的源节点信息,backupNodes存储了备份节点信息,backupNodes虽然是一个数组,但是里面永远只有一个元素,key和value存储了sessionId和session对象,backup是个布尔类型,表示该session节点是否是备份节点,proxy表示是否是代理节点,copy表示是否是copy节点;
3、 要在集群节点之间通信和发消息,需要定义通信协议以及信息载体,而这个协议以及信息载体是在MapMessage中定义的,从上面的UML图中可以看出,MapMessage中包含的信息有:key和value表示sessionId和session对象,keydata和valuedata表示sessionId和session对象序列化为字节流后的数据,primary表示该会话的源节点,nodes表示该会话的备份节点,msgtype表示操作类型,其定义如下:
这里每个值都代表一个语义,例如MSG_BACKUP表示让接收方把接收到的会话对象进行备份、MSG_REMOVE则表示让接收方按照接收到的会话id把对应的会话删除等等
比如在备份操作中MapMessage对象就像组成一个句子:“本人会话id为keydata,会话值为valuedata,我的源节点为primary,我现在需要做备份操作”。
4、 AbstractReplicatedMap类实现了map接口,通过实现map接口的相关操作达到会话的跨节点操作,它实现了MembershipListener接口,表示可以支持集群节点的添加和删除时,可以相应的更新本集群节点上的session集合;它实现了ChannelListener,可以在接收到集群消息时更新session集合;它实现了RpcCallback,可以在对rpc调用时根据消息操作类型更新session集合;
5、 AbstractReplicatedMap.mapMembers存储了集群成员和他最近一次心跳成功的时间,对于超过指定时间(这个值默认是5秒)之内没有心跳成功的集群节点,将会从集群节点中删除,代码如下:
6、 AbstractReplicatedMap也是基于Tribes组件的,因此包含了成员变量channel,而rpcChannel则是用于rpc调用时的组件,也可以在接收到其他节点的rpc调用时进行相应的处理;currentNode是用于选取会话的备份节点时用的变量,表示上一次刚刚选取的备份节点的序号,选取备份节点时的代码如下:
7、 backupmanager在每次请求结束时,都会调用AbstractReplicatedMap的replicate方法将当前会话的变更信息复制到备份节点,发送的消息是一个MapMessage对象,分为3类消息:新会话、会话更新和会话访问,此外,Map的移除也会向备份节点发送MapMessage消息;AbstractReplicatedMap类的replyRequest、leftOver、messageReceived方法中针对不同类型的消息作出不同的响应,比如说MSG_START类型的消息,是一个集群节点在启动后广播给集群中其他节点的消息,在replyRequest、leftOver、messageReceived方法中分别针对这个类型的调用mapMemberAdded方法,mapMemberAdded的职责就是更新mapMembers中指定集群节点上次心跳成功的时间值和对会话列表中没有备份节点的的会话重新选取一个备份节点;代码如下:
8、 LazyReplicatedMap.publishEntryInfo的职责是给会话选择一个备份节点,并给备份节点发送一个MSG_BACKUP的消息和给代理节点发送一个MSG_PROXY的消息,代码如下:
9、 BackupManager的实现相对比较简单,在startInternal中创建LazyReplicatedMap的对象,并使用这个对象管理会话:
10、 AbstractReplicatedMap.put方法将会话存入innerMap中,流程如下:
a) 实例化MapEntry,将key和value传入,并设置源节点为目前节点。
b) 判断本地内存是否已包含key,如是则不仅要本地remove掉,还要跨节点remove。
c) 通过Round robin算法从MapMember中选择一个作为备份节点。
d) 实例化一个包含MSG_BACKUP标识的MapMessage对象并发送给备份节点。
e) 实例化一个包含MSG_PROXY标识的MapMessage对象并发送给除了备份节点外的其他(代理)节点。
f) put进本地innerMap缓存。
代码如下:
11、 AbstractReplicatedMap.get在指定节点上获取会话,流程如下:
a) 获取本地的MapEntry对象,它或许直接包含了会话对象,或许包含了会话对象的存放位置信息。
b) 判断本节点是否属于源节点,如为源节点则直接获取MapEntry对象里面的会话对象并返回。
c) 判断本节点是否属于备份节点,若为备份节点则直接获取MapEntry对象里面的会话对象作为返回对象,并且还要将本节点升为源节点、重新选取一个新备份节点,把MapEntry对象拷贝到新备份节点。
d) 判断本节点是否属于代理节点,若为代理节点则向其他节点发送会话对象拷贝请求,“集群中谁有此会话对象请发送给我”,把接收到的会话对象放到本节点并作为返回对象,最后将本节点升为源节点。
代码如下:
12、 AbstractReplicatedMap.remove删除会话对象,流程如下:
a) 删除本地此MapEntry对象。
b) 广播其他节点删除此MapEntry对象。
代码如下:
tomcat源码阅读之BackupManager的更多相关文章
- Tomcat源码阅读(二)初始化
近来,我开始阅读tomcat的源码,感觉还挺清晰易懂:为了方便理解,我参考了网上的一些文章,把tomcat的组成归纳一下:整个tomcat的组成如下图所示: Tomcat在接收到用户请求时,将会通过以 ...
- tomcat源码阅读
1 工具准备 需要SVN.Maven.JDK.Eclipse.Eclipse M2插件 2 下载源码及发布包 源码在这里:http://svn.apache.org/repos/a ...
- tomcat源码阅读之过滤器
一.Servlet过滤器: 1.介绍: Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用. Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request ...
- tomcat源码阅读之SingleThreadModel
一.接口简介: 实现了SingleThreadModel接口的servlet类只能保证在同一时刻,只有一个线程执行该servlet实例的service方法,在tomcat实现中会创建多个servlet ...
- tomcat源码阅读之载入器(Loader)
一.Java类的载入器: 双亲委派模型: 1.JVM提供了三种类型的类加载器:引导类载入器(bootstrap class loader).扩展类载入器(extension class loader) ...
- tomcat源码阅读之集群
一. 配置: 在tomcat目录下的conf/Server.xml配置文件中增加如下配置: <!-- Cluster(集群,族) 节点,如果你要配置tomcat集群,则需要使用此节点. clas ...
- tomcat源码阅读之安全机制
一.领域(Realm): 1.Principal接口代表角色信息,包含了三个成员:用户名.密码.role列表(以逗号分隔),对应了tomcat-users.xml文件中一行user信息: Generi ...
- tomcat源码阅读之默认连接器
默认连接器 一.UML图: 1.所有的连接器都要实现Connector接口,必须创建Request对象和Response对象,httpConnector作为默认连接器,肯定也是要实现Connector ...
- tomcat源码阅读之部署器
我们知道web应用是用Context实例表示的,而Context是部署到Host实例中的,因此tomcat的部署器是关联的Host实例.Context实例可以用WAR文件部署,也可以把整个web应用的 ...
随机推荐
- points from ZhiQIng Hu
1,The errors in vertical direction are about 3 times horizontal errors of GPS data. But the precisio ...
- 2019-03-08 RF 调试Zibee 数据
- 中文字符utf-8编码原则
UTF-8是一种变长字节编码方式.对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0:如果是 多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字 ...
- 3--Python入门--Python数据集合类型--元组
在基础数据类型的基础上,Python有6中数据集合的类型: 列表list,最常用的数据类型,以[]为标识 元组tuple,和list很相似,但是不能二次赋值,用()标识 集合set,和list类似,但 ...
- 堆&栈
Java内存分为两种:堆内存和栈内存. 一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间.堆内存用于存放由new创建的对象和 ...
- linux 命令使用方法(随时更新)
1.hexdump 命令简介:hexdump是Linux下的一个二进制文件查看工具,它可以将二进制文件转换为ASCII.八进制.十进制.十六进制格式进行查看. 命令语法:hexdump: [-bcCd ...
- Spring Boot 揭秘与实战(二) 数据缓存篇 - Redis Cache
文章目录 1. Redis Cache 集成 2. 源代码 本文,讲解 Spring Boot 如何集成 Redis Cache,实现缓存. 在阅读「Spring Boot 揭秘与实战(二) 数据缓存 ...
- 查看Windows端口及端口关闭方法
一.查看已开放的端口: 1.借助系统自带MS-DOS命令查看开放的端口(Win2000/XP/server2003) 在开始-运行-输入cmd,打入netstat -an(注意-前有个小空格),在IP ...
- ldd 查看程序依赖库
ldd 查看程序依赖库 https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/ldd.html
- SLES 12 sp2开启SuSEfirewall2 防火墙后,放行VRRP协议 (用于keepalived搭建高可用规则)
centos 6下面修改防火墙vi /etc/sysconfig/iptables 增加这个-A INPUT -p 112 -d 224.0.0.0/32 -j ACCEPT #-p 112指定协议为 ...