本文转载自:http://blog.csdn.net/wangyangzhizhou。
如有侵权,请联系处理!
简介
每个节点都要维护一份集群节点信息列表,集群组通知的默认实现是在使用 UDP 数据包发送组播心跳到组播IP地址的基础上构建的。心跳包中含有 Tomcat 节点的 IP 地址,以及 Tomcat 用来侦听会话复制的 TCP 端口。集群成员通过使用相同的多播地址/端口组合组合在一起,每个成员定时发送用于动态发现组成员的心跳包。如果在一个 dropTime 时间内没有收到某个心跳包,那么这个心跳包所属节点就会从当前节点维护的节点列表删除。
其他信息机比如会话复制和更新等通过TCP 在节点间直连和传输,建立 TCP 的信息来源于心跳包。有同步和异步两种模式。在同步模式下,对客户端的响应必须在Session拷贝到其他节点完成后进行。异步模式无需等待Session拷贝完成就可响应。异步模式更高效,但是同步模式可靠性更高。同步异步模式由channelSendOptions参数控制,默认值是8,为异步模式,4是同步模式。在异步模式下,可以通过加上拷贝确认来提高可靠性,此时channelSendOptions设为10。
如果说一个 web 应用不涉及会话的话,那么做集群是相当简单的,因为节点都是无状态的,集群内各个节点无需互相通信,只需要将各个请求均匀分配到集群节点即可。但基本所有 web 应用都会使用会话机制,所以做 web 应用集群时整个难点在于会话数据的同步。
当然你可以通过一些策略规避复杂的额数据同步操作,例如前面说到的把会话信息保存在分布式缓存或数据库中统一集中管理,如下图,每个tomcat实例只需去写入或读取数据库即可,避免了 tomcat 集群之间的通信。但这种方式也有不足,要额外引入数据库或缓存服务,同时也要保证它们的高可用性,增加了机器和维护成本。
增量会话管理器
Tomcat 默认的集群会话管理器是 DeltaManager,它主要用于集群中各个节点之间会话状态的同步维护。DeltaManager 的职责是将某节点的会话该变同步到集群内其他成员节点上,它属于全节点复制模式,所谓全节点复制是指集群中某个节点的状态变化后需要同步到集群中剩余的节点,甚至包括那些根本没有部署该应用的节点。在集群中全节点会话复制的一个大致步骤如下图所示,客户端发起一个请求,假设通过一定的负载均衡设备分发策略分到其中一个结点 node1,如果还未存在 session 对象的话 web 容器将会创建一个会话对象,接着执行一些逻辑处理,在对客户端响应之前有个重要的事情是要把 session 对象同步到集群中其他节点上,最后再响应客户端。当客户端第二次发起请求时,假如分发到 node3 节点上,由于同步了 node1 的 session 会话,所以在执行逻辑时并不会取不到 session 的值。如果删除某个会话对象则要同时通知其他节点把相应会话删除,如果修改了某个会话的某些属性也同样要更新到其他节点的会话中。
除了具备上面提到的全节点复制外,它还有具有只复制会话增量的特性,增量是以一个完整请求为周期,即会将一个请求过程中所有会话修改量在响应前进行集群同步。往下看 Tomcat 具体实现方案。为区分不同的动作必须要先定义好各种事件,例如会话创建事件、会话访问事件、会话失效事件、获取所有会话事件、会话增量事件、会话ID改变事件等等,实际上 tomcat 集群会有9种事件,集群根据这些不同的事件就可以彼此进行通信,接收方对不同事件做不同的操作。例如 node1 节点创建完一个会话后,即向其他三个节点发送 EVT_SESSION_CREATED 事件,其他三个节点接收到此事件后则各自在自己本地创建一个会话,会话包含了两个很重要的属性——会话 ID 和创建时间,这两个属性都必须由 node1 节点跟着 EVT_SESSION_CREATED 一起发送出去,本地会话创建成功后即完成了会话创建同步工作,此时你通过会话ID查找集群中任意一个节点都可以找到对应的会话。同样对于会话访问事件,node1 向其他节点发送 EVT_SESSION_ACCESSED 事件及会话 ID,其他节点根据会话 ID 找到对应会话并更新会话最后访问时间,以免被认为是过期会话而被清理。类似的还有会话失效事件(同步集群销毁某会话)、会话 ID 改变事件(同步集群更改会话 ID )等等操作。
备份会话管理器
全节点复制的网络流量随节点数量增加呈平方趋势增长,也正是因为这个因素导致无法构建较大规模的集群,为了使集群节点能更加大,首要解决的就是数据复制时流量增长的问题,于是 tomcat 提出了另外一种会话管理方式,每个会话只会有一个备份节点,备份节点一定是已经部署了相同应用的。它使会话备份的网络流量随节点数量的增加呈线性趋势增长,大大减少了网络流量和逻辑操作,可构建较大的集群。
正常情况下为了支持高效的并发操作,tomcat 的所有会话集使用 ConcurrentHashMap<String, MapEntry> 结构保存,String 类型是指会话 ID,MapEntry 则是对会话信息、源节点及备份节点等的封装,一般会话对象由哪个节点生成则哪个节点为源节点,备份节点则为集群中其他任意一节点。MapMessage 对象是节点间信息传递时会话信息等的载体,它还包含一些定义好的语义如 MSG_BACKUP、MSG_RETRIEVE_BACKUP、MSG_PROXY、MSG_REMOVE 等。
每个会话只有一个源节点,一个备份节点,若干个代理节点。node1 为源节点,表示会话对象由它创建,保存的是会话对象的原件;node3 为备份节点,保存的是会话对象的备份件;node2 和 node4 为代理节点,它们保存的仅仅是会话位置信息,例如备份节点的位置等。这样分类是为了提供failover能力,假如刚好源节点宕掉,请求落到备份节点则能获取到会话对象,此时备份节点变为源节点,再从 node2、node4 中选一个作为备份节点,并且把会话对象拷贝到新备份节点上;假如备份节点宕掉了,请求一样能从源节点获取到会话对象,但此时会从 node2、node4 中选一个新备份节点,并把会话对象拷贝到新备份节点上;假如代理节点宕掉了,一切没影响,正常工作。
创建会话的基本流程:新建 MapEntry,传入会话ID和会话信息,设置源节点为当前节点;通过 Round robin 算法从 MapMember 中选择一个作为备份节点并设置为 MapEntry 中的备份节点,将 MapEntry 等发送给备份点;组装包含 MSG_BACKUP 标识的 MapMessage 对象发到备份节点告诉它要备份我传过来的这个会话信息;组装包含 MSG_PROXY 标识的 MapMessage 对象发送到除备份节点外的其他节点,告诉它们把此会话的 id、源节点、备份节点等信息记录下。
获取会话的基本流程:获取本地的 MapEntry 对象,它或许直接包含了会话对象,或许包含了会话对象的存放位置信息;判断本节点是否属于源节点,如为源节点则直接获取 MapEntry 对象里面的会话对象并返回;判断本节点是否属于备份节点,若为备份节点则直接获取 MapEntry 对象里面的会话对象作为返回对象,并且还要将本节点升为源节点,重新选取一个新备份节点;判断本节点是否属于代理节点,若为代理节点则向其他节点发送会话对象拷贝请求,把接收到的会话对象放到本节点并作为返回对象,最后将本节点升为源节点。
注意事项
对于因超时引起的某个 session 失效无需通知其他节点,因为其他节点同样知道这个session已经超时。因此对于 tomcat 集群有一点非常重要,所有节点的操作系统时间必须一致!不然会出现某个节点 session 已过期而在另一节点此 session 仍处于活动状态的现象。Linux下同步时间通常采用ntp协议,可以在每个服务器上增加自动运行脚本文件,每天时间服务器自动同步,如/etc/cron.daily下增加脚本,内容为 /usr/sbin/ntpdate -s time.nist.gov 。还要确保 web.xml 含有 <distributable/> 元素。为实现会话复制,所有放在 session 里的对象都要实现java.io.Serializable接口。
以上两种模型都有各自的优缺点,在实际生产上部署应该根据实际情况选择适合的模型。
对于全节点会话同步模型,一旦集群节点数量及访问量大起来,将导致大量的会话信息需要互相复制同步,很容易导致网络阻塞,而且这些同步操作很可能会成为整体性能的瓶颈,根据经验,此种方案在实际生产上推荐的集群节点个数为3-6个,它无法组建更大的集群,而且冗余了大量的数据,利用率较低。使用同一个组播地址和端口的多个节点同属一个子集群,因此通过自定义组播地址和端口就可将一个大的tomcat集群分成多个子集群。
对于会话备份模型,每个会话只会有一个备份,大大减少了网络流量和逻辑操作,此模型可构建较大的集群。生产上可以组成十个以上的节点作为一个集群。使用这种模型也要考虑到,虽然这种模式支持更大的集群,但它只有一个数据备份,假如刚好源数据和备份数据所在的机器同时宕掉了,则没办法恢复数据,不过刚好同时宕机的机率很小很小。
http://blog.csdn.net/wangyangzhizhou
- 结合Apache和Tomcat实现集群和负载均衡
http://fableking.iteye.com/blog/360870 TomcatApacheJSP应用服务器Web 本文基本参考自 轻松实现Apache,Tomcat集群和负载均衡,经由实 ...
- 图文解说:Nginx+tomcat配置集群负载均衡
图文解说:Nginx+tomcat配置集群负载均衡 博客分类: appserver nginxTomcatUbuntuLinux网络应用 作者:niumd Blog:http://ari.iteye ...
- Apache+Tomcat服务器集群配置
在实际应用中,如果网站的访问量很大,为了提高访问速度,可以与多个Tomcat服务器与Apache服务器集成,让他们共同运行servlet/jsp 组件的任务,多个Tomcat服务器构成了一个集群(Cl ...
- nginx+tomcat实现集群,redis实现session共享,软连接实现文件共享:http://blog.csdn.net/hua1586981/article/details/78132710
转载 2017年02月08日 16:52:41 730 相信很多人都听过nginx,这个小巧的东西慢慢地在吞食apache和IIS的份额.那究竟它有什么作用呢?可能很多人未必了解. 说到反向代理,可能 ...
- FineReport如何部署Tomcat服务器集群
环境准备 Tomcat服务器集群中需要进行环境准备: Apache:Apache是http服务器,利用其对Tomcat进行负载均衡,这里使用的版本是Apache HTTP Server2.0.64: ...
- 结合Apache和Tomcat实现集群和负载均衡 JK 方式 2 (转)
本文Apache+Tomcat集群配置 基于最新的Apache和Tomcat,具体是2011年4月20日最新的Tomcat和Apache集群和负载均衡配置. 准备环境 Apache Apa ...
- Tomcat:基于Apache+Tomcat的集群搭建
根据Tomcat的官方文档说明可以知道,使用Tomcat配置集群需要与其它Web Server配合使用才可以完成,典型的有Apache和IIS. 这里就使用Apache+Tomcat方式来完成基于To ...
- 结合Apache和Tomcat实现集群和负载均衡 JK 方式
本文基本参考自 轻松实现Apache,Tomcat集群和负载均衡,经由实操经历记录而成,碰到些出入,以及个别地方依据个人的习惯,所以在一定程度上未能保持原文的完整性,还望原著者海涵. 因原文中有较多的 ...
- apache+tomcat分布式集群搭建
今天搭建apche+tomcat分布式集群,遇到很多问题,在网上找到的很多都不成功,然后和同事一起研究了一下,最终搭建成功了.做个笔记,以备自己以后参考. 1,下载apache.在下载Apache(2 ...
随机推荐
- 专为seo新手准备的百度分享工具教程
http://www.wocaoseo.com/thread-178-1-1.html 百度分享工具是目前seo站长最为常用的工具之一,主要用来让用户分享来提高网站的流量,同时他也有很多实际有效的方式 ...
- cg语言学习&&阳春白雪GPU编程入门学习
虽然所知甚少,但康大的<GPU编程与Cg编程之阳春白雪下里巴人>确实带我入了shader的门,在里面我第一次清晰地知道了“语义”的意思,非常感谢. 入门shader,我觉得可以先读3本书: ...
- ElasticSearch7.6.1 安装及其head插件安装
本来打算写一篇ES和Solr的差别的,后来想想算了简单说说吧, 如果是对已存在数据建立完成索引的情况下,Solr更快 一但进行索引的操作的时候,Solr的IO是阻塞的 对于大数据量的实时检索,还是El ...
- Linux 用户与权限
这些天一直在看Linux的命令但是却没有写文章,因为感觉没有必要,哪些简单的命令,vi cat cd 啥的,是个做开发的就知道,所以就没写; 用户管理 第一个我们知道的用户就是Root 没错哦,这就是 ...
- [Python]在当前目录下创建三个目录
import os os.mkdir("2018-03-16-b018") os.mkdir("2019-03-16-b019") os.mkdir(" ...
- 区块链Fabric 交易流程
1. 提交交易预案 1)应用端首先构建交易的预案,预案的作用是调用通道中的链码来读取或者写入账本的数据.应用端使用 Fabric 的 SDK 打包交易预案,并使用用户的私钥对预案进行签名. 应用打包完 ...
- leetcode刷题-60第k个队列
题目 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123""132& ...
- Java中枚举的用法
public enum Week { DAY1("周一", 0.9), DAY2("周二", 0.9), DAY3("周三", 0.8), ...
- Java的foreach用法
foreach其实就是for的加强版,其语法如下: for(元素类型type 元素变量value : 遍历对象obj) { 引用x的java语句; } 举个例子,比如定义一个数组,使用foreach以 ...
- IDEA创建新空项目
IDEA创建新空项目 File -> New -> Project -> Empty Project -> 然后OK 这个是什么都不能做的,然后我们创建Module. File ...