对 Web 应用程序进行负载平衡

2022-09-03 00:44:05

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

在为基于j2ee(struts)的Web应用程序编写代码时,我们如何解决这个问题?


答案 1

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

Tomcat 群集文档说明了应用程序成功复制其会话的两个重要要求:

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

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

(实际上,无论您使用哪个 servlet 容器,我相信这些要点都适用。

更新:为了解决评论中关于为什么在多个服务器之间平衡负载时使用粘性会话的一些问题,我认为用一个例子来解释这一点最容易。

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

拥有一个将数据保留在会话中但没有粘性会话的环境将打开一个令人头疼的世界。

假设更新了特定会话属性中的某个值,并且碰巧读取了相同的会话属性。您可以将 Tomcat 设置为将会话数据复制到群集中的所有服务器,但此复制不会立即发生。如果 的初始请求由 处理,并且在完成一纳秒后,同一访问者向 发出请求,在您的非粘性环境中由 处理,该怎么办?由于复制不是即时的,您是否有办法知道是否正在读取最新的会话数据?是否必须添加某种逻辑才能跨群集同步读取?这将变成巨大的痛苦。first.jspsecond.jspfirst.jspserver1second.jspserver2

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

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

另一种方法是将节点的数据仅复制到群集中的几个“伙伴”,以便在节点发生故障时,其数据可以在其他地方使用,但不必每个节点都有副本。在此方案中,您将配置群集,以便节点 1 将其数据复制到节点 2 和 3,节点 2 将其数据复制到节点 3 和 4,依此类推,形成一个链。在此方案中,向群集添加其他节点不会导致节点之间的通信量像在“全对全”方案中那样迅速增加。


答案 2

推荐