负载平衡Web应用程序

时间:2009-05-13 02:52:22

标签: java tomcat load-balancing

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

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

1 个答案:

答案 0 :(得分:30)

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

The Tomcat clustering doc说明了应用程序成功完成会话复制的两个重要要求:

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

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

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

更新:为了解决为什么在平衡多台服务器之间的负载时使用粘性会话的注释中的一些问题,我认为最简单的方法是通过示例来解释这一点。

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

拥有一个环境,您可以将数据保存在会话中但具有粘性会话将会让您感到头疼。

假设first.jsp更新特定会话属性中的某些值,second.jsp恰好读取此相同的会话属性。您可以设置Tomcat以将会话数据复制到群集中的所有服务器,但此复制不会立即发生。如果first.jsp的初始请求由server1处理并且在完成后一纳秒,同一访问者向second.jsp发出请求,该请求在非粘性环境中由{处理{ {1}}。由于复制不是即时的,您是否有任何方法可以知道您是否正在阅读最新的会话数据?您是否必须添加某种逻辑来同步整个群集中的读取?这将成为巨大的痛苦。

设置会话亲和力/粘性会话消除了这种麻烦;通过同一节点从同一客户端服务器获取所有请求,您不必担心“在处理请求时此节点是最新的吗?”当节点发生故障时,客户端仍然可以故障转移到群集中的另一个节点,该节点具有会话数据的副本,但是对于粘性会话,这种情况很少见,而不是常态。

还有另一个需要粘性会话的原因:在群集中的节点之间加载。如果会话中的请求可以由任何节点处理,那么这意味着您在集群中设置了全部复制(意味着node1的会话数据被重新复制到node2,node3,...,节点) N,node2的会话数据被复制到node1,node3,... none N等。当群集变大时,全对会话复制可能变得带宽和资源密集,因为群集的每次添加都意味着另一个需要与群集中的每个其他单个节点通信的节点。

另一种方法是将节点的数据复制到集群中的几个“好友”中,以便在节点发生故障的情况下,其数据在其他地方可用,但不是每个节点都必须有副本。在这种情况下,您将配置群集,以便node1将其数据复制到节点2和3,节点2将其数据复制到节点3和4等,形成链。在这种情况下,向群集添加其他节点不会导致节点之间的通信量快速增加,就像在“全部 - 所有”方案中一样。