java 负载平衡 Web 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/855841/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:05:09  来源:igfitidea点击:

Load balance web application

javatomcatload-balancing

提问by user32262

There are load balanced tomcat web servers. Every request could be served by different tomcat server.

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

How could we take care of this while writing code for the j2ee (struts) based web application?

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

回答by matt b

First of all, you'll want to set up your load balancer for session affinity/sticky sessions, so that it continues forwarding all requests to the same Tomcat (as long as it is up) based on JSESSIONID.

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

The Tomcat clustering docstates two important requirements for your application to successfully have it's sessions replicated:

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

  • All your session attributes must implement java.io.Serializable
  • Make sure your web.xml has the <distributable/>element or set at your <Context distributable="true" />
  • 您的所有会话属性都必须实现 java.io.Serializable
  • 确保您的 web.xml 具有<distributable/>元素或设置在您的<Context distributable="true" />

If you start putting Objects into Session which don't implement Serializable(or which have properties/fields that don't implement Serializable), then you're going to have problems.

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

(Actually these points all apply regardless of which servlet container you are using, I believe.)

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

Update:To address some of the questions in the comments about why use sticky sessions when you are balancing the load between multiple servers, I think it's easiest to explain this with an example.

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

First of all, this only really matters if your application keeps some sort of data in-session, which may not be every single application (although it's probably most). If you don't keep data in-session then you probably won't care about any of this and you can just stop reading here.

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

Having an environment where you keep data in session but you do nothave sticky session would open up a world of headaches.

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

Let's say first.jspupdates some value in a particular session attribute, and second.jsphappens to read this same session attribute. You can set up Tomcat to replicate session data to all servers in the cluster, but this replication does not occur instantly. What if the initial request for first.jspis handled by server1and one nanosecond after it completes, the same visitor makes a request to second.jsp, which in your non-sticky environment gets handled by server2. Since replication is not instantaneous, do you have any way of knowing if you are reading the most up-to-date session data? Do you have to add some sort of logic to synchronize your reads across the cluster? This would become giant pain.

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

Setting up session affinity/sticky sessions removes this headache; by having all requests from the same client server by the same node, you don't have to worry about "is this node up to date by the time it handles the request?" When the node fails, the client can still failover to another node in the cluster, which has a copy of it's session data, but with sticky sessions this becomes the rare case and not the norm.

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

There is another reason to want sticky sessions: load between the nodes in the cluster. If a request in a session could be handled by any node, then that would imply that you have all-to-all replication set up in the cluster (meaning the session data of node1 is replcated to node2, node3, ..., node N, the session data of node2 is replicated to node1, node3, ... none N, etc). All-to-all session replication can become bandwidth and resource intensive when the cluster gets larger, because each addition to the cluster means yet another node that needs to communicate with every other single node in the cluster.

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

An alternative to this is have a node's data replicated to only a few "buddies" in the cluster, so that in case the node fails it's data is available elsewhere but without every single node having to have a copy. In this scenario, you would configure the cluster so that node1 has it's data replicated to nodes 2 and 3, node 2 has it's data replicated to nodes 3 and 4, etc., forming a chain. In this scenario, adding additional nodes to the cluster does not cause the amount of communication between nodes to increase rapidly as it does in an all-to-all scheme.

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