一尘不染

负载平衡Web应用程序

tomcat

有负载平衡的tomcat Web服务器。每个请求可以由不同的tomcat服务器处理。

在为基于j2ee(struts)的Web应用程序编写代码时,我们该如何处理?


阅读 226

收藏
2020-06-16

共1个答案

一尘不染

首先,您将需要为会话亲缘关系/粘性会话设置负载均衡器,以便它继续基于JSESSIONID将所有请求转发到同一个Tomcat(只要启动了)。

Tomcat集群文档指出了两个重要要求,以使应用程序成功复制其会话:

  • 您的所有会话属性都必须实现 java.io.Serializable
  • 确保您的web.xml具有<distributable/>元素或在您的位置设置<Context distributable="true" />

如果您开始将未实现的对象Serializable(或具有未实现的属性/字段Serializable)放入会话,那么您将遇到问题。

(实际上,无论您使用哪个servlet容器,这些观点实际上都适用。)

更新: 为了解决注释中有关在平衡多台服务器之间的负载时为什么使用粘性会话的某些问题,我认为用示例进行解释最简单。

首先,只有当您的应用程序在会话中保留某种数据时才真正重要,这可能不是每个单独的应用程序(尽管可能是大多数)。如果您不在会话中保留数据,那么您可能根本不会在意这些,您可以在这里停止阅读。

在一个环境中,您可以在会话中保留数据,但 没有 粘性会话,这会带来很多麻烦。

假设first.jsp更新特定会话属性中的某些值,并且second.jsp碰巧读取了相同的会话属性。您可以设置Tomcat将会话数据复制到群集中的所有服务器,但是这种复制不会立即发生。如果最初的请求first.jsp处理时间为server110毫秒,并且完成后的1纳秒,同一位访问者向发出请求second.jsp,该请求在您的非粘性环境中将由处理server2。由于复制不是瞬时的,因此您是否有任何方式知道您是否正在读取最新的会话数据?您是否需要添加某种逻辑来跨集群同步您的读取?这将成为巨大的痛苦。

设置会话亲和力/粘性会话可以消除这种头痛;通过使来自同一客户端服务器的所有请求都位于同一节点上,您不必担心“该节点在处理请求时是否已更新?”
当节点发生故障时,客户端仍可以故障转移到群集中的另一个节点,该节点具有其会话数据的副本,但是对于粘性会话,这很少见,而不是常规情况。

需要粘性会话的另一个原因是:集群中节点之间的负载。如果会话中的请求可以由任何节点处理,那么这意味着您在集群中设置了所有复制(这意味着node1的会话数据被重复到node2,node3,…,node
N,则将节点2的会话数据复制到节点1,节点3,……无N等)。当集群变大时,所有会话复制可能会占用大量带宽和资源,因为集群中的每一个添加都意味着又一个节点需要与集群中的每个其他单个节点进行通信。

替代方法是将节点的数据仅复制到群集中的几个“伙伴”,这样,万一该节点发生故障,它的数据就可以在其他位置使用,而不必每个节点都拥有一个副本。在这种情况下,您将配置集群,以使node1的数据复制到节点2和3,node
2的数据复制到节点3和4,等等,形成一个链。在这种情况下,向群集添加其他节点不会像在所有方案中那样导致节点之间的通信量快速增加。

2020-06-16