有负载平衡的tomcat Web服务器.每个请求都可以由不同的tomcat服务器提供.
在为基于j2ee(struts)的Web应用程序编写代码时,我们如何处理这个问题?
首先,您需要为会话关联/粘性会话设置负载均衡器,以便它继续基于JSESSIONID将所有请求转发到同一个Tomcat(只要它已启动).
Tomcat集群文档说明了应用程序成功完成会话复制的两个重要要求:
您的所有会话属性都必须实现 java.io.Serializable
确保您的web.xml包含
元素或设置
如果您开始将对象放入未实现的会话Serializable
(或者具有未实现的属性/字段Serializable
),那么您将遇到问题.
(实际上,无论你使用哪个servlet容器,这些都适用.我相信.)
更新:为了解决为什么在平衡多个服务器之间的负载时使用粘性会话的注释中的一些问题,我认为用一个例子解释这个问题是最容易的.
首先,只有当您的应用程序在会话中保留某种数据时,这才真正重要,这可能不是每个应用程序(尽管可能最多).如果你没有在会话中保存数据,那么你可能不会关心任何这些,你可以在这里停止阅读.
拥有一个环境,您可以将数据保存在会话中,但是您没有粘性会话,这将会让您感到头疼.
假设first.jsp
在特定会话属性中更新某些值,并且second.jsp
恰好读取此相同的会话属性.您可以设置Tomcat以将会话数据复制到群集中的所有服务器,但此复制不会立即发生.如果初始请求first.jsp
由server1
完成后的一个纳秒处理,同一个访问者发出请求second.jsp
,在非粘性环境中处理请求server2
.由于复制不是即时的,您是否有任何方法可以知道您是否正在阅读最新的会话数据?您是否必须添加某种逻辑来同步整个群集中的读取?这将成为巨大的痛苦.
设置会话关联性/粘性会话消除了这种麻烦; 通过同一节点从同一客户端服务器获取所有请求,您不必担心"在处理请求时此节点是最新的吗?" 当节点发生故障时,客户端仍然可以故障转移到群集中的另一个节点,该节点具有其会话数据的副本,但是对于粘性会话,这种情况很少见,而不是常态.
还有另一个需要粘性会话的原因:在群集中的节点之间加载.如果会话中的请求可以由任何节点处理,那么这意味着您在集群中设置了全部复制(意味着node1的会话数据被重新复制到node2,node3,...,节点) N,node2的会话数据被复制到node1,node3,... none N等.当群集变大时,全对会话复制可能变得带宽和资源密集,因为群集的每次添加都意味着另一个需要与群集中的每个其他单个节点通信的节点.
另一种方法是将节点的数据复制到集群中的几个"好友",以便在节点发生故障的情况下,它的数据在别处可用,但每个节点都不必有副本.在这种情况下,您将配置群集,以便node1将其数据复制到节点2和3,节点2将其数据复制到节点3和4等,从而形成链.在这种情况下,向群集添加其他节点不会导致节点之间的通信量快速增加,就像在全向方案中一样.