对J2EE集群不太了解的人首先可以看看附件里面的《解开J2EE集群的神秘面纱》, 讲的挺好的。
J2EE的服务器集群主要的就是负载均衡
和失败转移
这些。
负载均衡这个话题都烂大街了,随处可以找到相关的帖子或博文,我也就不谈了。
但是这些帖子中大部分都只谈了负载均衡,顶多再说一下 Tomcat 的 HttpSession 复制(失败转移的一种解决方案吧)。更有甚者,直接决定“集群中服务器节点宕机丢失的部分 HttpSession 不碍事”。。。
我的感觉就是,
像 Tomcat 的 HttpSession 交叉复制,如果集群中服务器过多对性能的影响肯定非常之大。
像 JBoss、WebLogic 等的服务器链式 HttpSession 复制,如果一个服务器节点宕机,此节点的下一个服务器节点就得负责两个服务器的用户请求。是不是有点怕人奥。
至于“集群中某个节点宕机就宕机, HttpSession 丢失无所谓”这样的观点也是挺匪夷所思的,毕竟后台中2000个 HttpSession 同时丢失的后果不是那么容易承担的。
为了解决上面这些问题,我自己琢磨了一套方案,感觉挺不错的(不知道网上是不是有类似“轮子”,反正我是没有搜索到)。 就发出来共享一下,嘿嘿
我想到的是缓存服务器和Web服务器双向备份HttpSession
,这个。。。。咱语文挺烂的,表达的不好。
双向备份就是集群中多个Web服务器分散保存 HttpSession ,同时在缓存服务器中也分散保存这些 HttpSession (每个 HttpSession 正常情况下只需要复制一次),至于怎么分散各位且听我慢慢说来。
我使用了三个缓存服务器(Memcached),三个Web服务器(Tomcat)进行思路实现和测试。
先说说思路吧: 三个缓存服务器和三个Web服务器如下分布
Tomcat_A
|
Tomcat_B
|
Tomcat_C
|
Memcached_A
|
Memcached_B
|
Memcached_C
|
Tomcat_A
的 HttpSession 分布备份在Memcached_B
和 Memcached_C
中
Tomcat_B
的 HttpSession 分布备份在Memcached_A
和 Memcached_C
中
Tomcat_C
的 HttpSession 分布备份在Memcached_A
和 Memcached_B
中
我的构思就是这样: 在服务器正常运行情况下,使用 Stick-Session 方式,同一个 HttpSession 由负载均衡器判断 HttpSession 归属交给同一个服务器执行,这样一来,正常情况下,服务器节点的运行就是完全独立的、就好像是单台服务器运行一样。 HttpSession 复制备份也是隐式的,通过哈希码将这个 HttpSession 隐式备份在相应哈希码分布的 Memcached 上。
假设运行中 Tomcat_A
突然宕机了(我咔嚓关了Tomcat_A,嘿嘿),那么负载均衡器就会无法将请求分发给 Request 相对应的 Tomcat_A
,负载均衡器便会把请求分发给其他的Tomcat_B
或 Tomcat_C
,这两台服务器会接收到原属于绑定在 Tomcat_A
上的请求
,他们没有相应的 HttpSession 啊, 然后他们就主动从 Memcached 集群中寻找这个 HttpSession 。如果找到的话,他们便主动把这个 HttpSession “收录”为自己的, 即将 JSESSIONID 修改为自己的。这样一来,原属于 Tomcat_A
的 HttpSession 会随机分布给其他没有宕机的服务器节点。
这是服务器节点宕机的情况、
如果缓存器节点宕机了怎么办?
假设 Memcached_A
宕机,那么整个集群中保存在 Memcached_A
中的Session备份就丢失,那么 Tomcat_B
和 Tomcat_C
中的Session就没有了备份。 如果这时这两台服务器再挂断的话,Session就真的丢失了(用户感情伤不起啊)。为了保证 “整个集群中随时都存有同一个Session的备份
”, Tomcat_B
和 Tomcat_C
应该为自身的Session负责。他们应该主动把自己的 Session 再备份一次(可以采用临时新建线程的方式, 毕竟宕机不是频繁的么。属于特殊情况),再次备份到其他的可用 Memcached 节点中。
这样,整个程序中可以完全无视
单台机器的突然宕机, 一分钟内整个集群应该能把宕机服务器的 Session 再备份一次吧!
关于这个想法,网上有一个开源项目叫做 memcached-session-manager
。 我试过它,感觉不怎么好用。它只能说实现了部分我的想法吧,没有完全实现。测试中,仍然存在 HttpSession 丢失的情况。并且它有着令人发指的效率问题!
我测试了一下, 普通的 JSP 页面处理只耗费 62.3ms
(机子挫)。而添加上这个插件之后,普通的 JSP 页面处理需要消耗 2.18s
!!!这真是令人发指的效率!
靠人不如靠自己、我便自己实现了自己的思路。
使用的缓存程序就是 Memcached 2.6, 我添加在附件里了。
我使用的 Memcached 客户端是 XMemcached (国产)、支持国产么,并且它的效率据某公司测试证明,比 SynMemcached 略高一点点。
下载地址:XMemcached
我就是通过替换了 Tomcat 原有的 StandardManager(MemcachedManager替换)、StandardSession(MemcachedSession替换) 来实现的, 然后加入了隐式的 HttpSession 备份操作。如果需要的话,还会从缓存程序中尝试获取 HttpSession。
我还通过在 MemcachedManager 中向 Context 中加入阀门(Valve)在每次请求之后再根据 MemcachedSession 的属性是否被修改来判断是否更新缓存(事务一致性么,整个请求处理过程是一个原子)。 不涉及setAttrubute、removeAttribute的操作是不会触发缓存更新的,并且 setAttribute 如果设置重复值也是不会引起缓存更新的。
在 XMemcached 中我添加了DisConnect 事件的监听器、 如果某条连接断开(Memcached服务器节点宕机)的话,会触发Web服务器将 Session 再次更新入其他未断开的Memcached服务器节点中。
整个过程实现其实挺简单的、 jar 包我也放在附件中。
最后就说说我实现的这个“无名”插件的效率、 测试中我挺费解的, 添加了这个插件的 Tomcat 居然比正常的 Tomcat 处理JSP页面还快。使用它之后,处理一个正常同样JSP页面只需要 了 57.5ms
,嘿嘿,快了几毫秒(应该是测试数据误差)。
使用这个“无名”插件挺简单的、 就是修改 context.xml ,添加一个:
<Manager className="net.sulin.mem.MemcachedManager"
queueSize="300"
addr="127.0.0.1:11211 127.0.0.1:11212 127.0.0.1:11213"
poolSize="3"
protocol="text"
maxInactiveInterval="30"/>
<!--
className : 替换的Manager
queueSize : 我采用了异步队列更新 HttpSession 缓存,队列用于存储需要更新的HttpSession对象,如果值太小的话。队列空间不够用
addr : 就是 Memcached 的服务器地址和端口了,每个之间用空格隔开(XMemcached就是这样处理的,我不想费事)
poolSize : XMemcached 客户端与 Memcached 服务器的连接池,据XMemcached 作者说即便是高并发也 30 之内吧,因为这是用NIO处理的,不需要太多连接。
protocol : XMemcached 客户端与 Memcached 服务器之间的数据传输协议,可以是“text”也可以是“binary”, binary 的话它可以使用 XMemcached 的touch方法等, 但是需要 1.4 以上版本的XMemcached。 我没使用
maxInactiveInterval :HttpSession过期时间, 分钟为单位
-->
在测试中,我胡乱关闭Web服务器和Memcached服务器, 每次请求的 HttpSession 都没有遇见丢失的情况,嘿嘿,感觉挺不错的。性能上也是毫无影响。 但是这是没有经受过任何生产考研的!
有想法的人可以试试,源码就在jar包中。如果有什么优化想法咱欢迎交流!
分享到:
相关推荐
5. 失效转移(Failover):当集群中的某个节点失效时,失效转移机制会将工作负载转移至其他健康节点,确保服务不会中断。 6. 等幂方法(Idempotent Methods):等幂方法是指无论执行多少次,结果都相同的方法。这在...
随着互联网技术的快速发展,J2EE(Java 2 Platform, Enterprise Edition)作为企业级应用开发的标准平台之一,在金融、电商等领域得到了广泛的应用。为了确保关键业务系统的稳定运行,J2EE集群技术应运而生。本文将...
《J2EE集群技术揭秘》一文由Sun中国工程研究院的王昱撰写,深入探讨了J2EE集群技术的关键概念、实现原理以及常见误区。文章不仅涵盖了基础理论,还涉及了具体的实现策略和技术细节,为读者提供了全面而深入的理解。 ...
J2EE(Java 2 Platform, Enterprise Edition,现称为Java EE)作为企业级应用开发的主要框架之一,其集群技术成为了提升系统高可用性和伸缩性的关键。然而,由于J2EE规范本身并未明确规定集群的实现细节,导致不同...
标题“Java集群与负载均衡”涉及的关键知识点包含J2EE集群的概念、原理、术语定义、实施中遇到的问题以及如何解决这些问题。下面详细解释: ### J2EE集群概念 J2EE(Java 2 Platform, Enterprise Edition)是Java...
J2EE(Java 2, Enterprise Edition)规范虽然没有直接提供集群支持,但各供应商通过不同的实现方式提供了集群功能,这也给开发者带来了挑战。以下是对Java集群核心概念的详细解释: 1. **伸缩性(Scalability)**:指...
根据描述,“Oracle RAC Failover 详解”主要关注 Oracle RAC 集群中 Failover 的几种不同形式及其配置方法。下面将详细介绍这三种 Failover 方式: 1. **Client-Side Connect-time Failover** 2. **TAF ...
2. **安装和配置**:在所有服务器上安装Failover软件,配置心跳检测、资源管理和集群设置。 3. **测试**:进行模拟故障测试,确保故障转移能够正确执行,并验证服务的可用性。 4. **监控和维护**:持续监控系统性能...
如果该任务被标记为守护线程(daemon thread),则当主线程结束时,守护线程也将随之结束,这可能导致连接在尚未完成Failover之前就被中断。 ##### 2.2 解决方案 针对上述问题,可以通过修改ActiveMQ核心代码的...
"SQL Server 2012 failover cluster搭建详解" SQL Server 2012 failover cluster是一种高可用性的解决方案,可以提供数据库的高可用性和灾难恢复能力。本文将详细介绍如何在Windows Server 2008 R2上搭建SQL Server...
jdbc:oracle:thin:@(description=(address_list=(address=(host=10.70.239.76)(protocol=tcp)(port=1521))(address=(host=10.70.239.78)(protocol=tcp)(port=1521))(load_balance=yes)(failover=yes))(connect_data...
【Windows 2008 Failover Cluster 部署详解】 Windows 2008 Failover Cluster 是一种高可用性解决方案,它允许在多台服务器之间实现应用和服务的自动故障转移,以确保在主服务器发生故障时,业务连续性和数据可用性...
例如,jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.151.50.65)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=10.151.50.66)(PORT=1521))) (FAILOVER=yes) (LOAD_BALANCE=yes) ...
### 4G LTE Failover 架构详解 随着信息技术的发展,网络已经成为企业运营不可或缺的一部分。然而,无论是因为天气因素还是过时的铜线网络,企业的广域网(WAN)都可能遭遇中断的情况。为了应对这种风险,确保业务...
Redis是世界上最受欢迎的内存数据存储系统之一,常用于构建高性能、低延迟的数据服务。在分布式系统中,数据的高可用性和容错性至关重要。"failover-manager-master.zip_failover" 提到的“failover”机制正是为了...
配置基于LAN的PIX Failover 的详解
"Redis分布式集群部署安装及细节" 一、Redis集群介绍 Redis集群是一种分布式的NoSQL数据库解决方案,它可以将多个Redis节点组合成一个集群,以提高数据存储和检索的性能和可用性。Redis集群支持自动发现节点、...