Java 负载平衡web应用程序

Java 负载平衡web应用程序,java,tomcat,load-balancing,Java,Tomcat,Load Balancing,有负载平衡的tomcat web服务器。每个请求都可以由不同的tomcat服务器提供服务 在为基于j2ee(struts)的web应用程序编写代码时,我们如何处理这个问题 首先,您需要为会话关联性/粘性会话设置负载平衡器,以便它继续根据JSESSIONID将所有请求转发到同一个Tomcat(只要它已启动) 说明了成功复制应用程序会话的两个重要要求: 所有会话属性都必须实现java.io.Serializable 确保您的web.xml具有元素或设置在您的 如果您开始将不实现Serializa

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


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

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

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

  • 所有会话属性都必须实现
    java.io.Serializable
  • 确保您的web.xml具有
    元素或设置在您的
如果您开始将不实现
Serializable
(或其属性/字段不实现
Serializable
)的对象放入会话,那么您将遇到问题

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

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

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

在一个环境中,您可以将数据保存在会话中,但没有粘性会话,这将带来一个令人头痛的世界

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

设置会话亲和力/粘性会话可消除此问题;通过让同一节点处理来自同一客户机服务器的所有请求,您不必担心“该节点在处理请求时是否是最新的?”当该节点出现故障时,客户机仍然可以故障切换到群集中的另一个节点,该节点具有其会话数据的副本,但对于棘手的会议,这成为罕见的情况,而不是常态

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


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

在您的第一句话中,您的意思是当选择Tomcat来处理第一个请求时,必须使用同一个Tomcat来处理来自该浏览器的以下请求吗。在这种情况下,如果同一个tomcat服务器为所有请求提供服务,那么负载平衡有什么帮助呢?我认为负载平衡的主要思想是使用多个服务器为多个客户端提供服务。这并不意味着来自同一客户机的所有请求都应该分发到多个服务器。只是一个想法,不确定。Struts在这种情况下没有任何不同。坚持马特提供的建议+1@vicky21:这就是为什么在没有负载的情况下分配负载。因此,不,它不像同一台服务器会为来自特定会话的所有请求提供服务。否则,就不需要会话复制。我希望它能说清楚。但也不是每一个请求都由不同的服务器来处理,甚至几年后,我发现这是一个惊人的答案。谢谢你的信息,@mattb