12

我的应用程序发出 Web 服务请求;提供者将处理请求的最大速率,因此我需要限制它们。

当应用程序在单个服务器上运行时,我曾经在应用程序级别执行此操作:一个跟踪到目前为止已发出多少请求的对象,并在当前请求使其超过最大允许负载时等待。

现在,我们正在从单个服务器迁移到集群,因此有两个应用程序副本正在运行。

  • 我无法继续检查应用程序代码的最大负载,因为两个节点的组合可能超过允许的负载。
  • 我不能简单地减少每台服务器的负载,因为如果另一个节点空闲,第一个节点可以发出更多请求。

这是一个 JavaEE 5 环境。限制应用程序发出的请求的最佳方法是什么?

4

6 回答 6

6

由于您已经处于 Java EE 环境中,因此您可以创建一个 MDB 来处理基于 JMS 队列的 Web 服务的所有请求。应用程序的实例可以简单地将它们的请求发布到队列中,MDB 将接收它们并调用 Web 服务。

队列实际上可以配置适当数量的会话,这将限制对您的 Web 服务的并发访问,因此您的限制是通过队列配置处理的。

结果可以通过另一个队列(甚至每个应用程序实例的队列)返回。

于 2010-02-24T21:47:30.963 回答
2

这样做的方法很多:您可能有一个“协调代理”,负责将“令牌”交给服务器。每个“令牌”代表执行任务等的权限。每个应用程序都需要请求“令牌”才能发出呼叫。

一旦应用程序耗尽其令牌,它必须在再次访问 Web 服务之前要求更多。

当然,当每个应用程序由于对 Web 服务的并发性而对每个调用的时间有要求时,这一切都会变得复杂。

您可以依赖RabbitMQ作为消息传递框架:Java 绑定可用。

于 2010-02-24T21:22:46.677 回答
2

N 个节点需要通信。有多种策略:

  • 广播:每个节点都会向其他人广播它正在拨打电话,所有其他节点都会考虑到这一点。节点是平等的,并保持单独的全局计数(每个节点都知道每个其他节点的调用)。
  • 主节点:一个节点是特殊的,它的主节点和所有其他节点在调用之前都请求主节点的许可。主人是唯一知道全局计数的人。
  • 专用主控:与主控相同,但“主控”本身不调用,只是一个跟踪调用的服务。

根据您预计以后扩展的高度,一种或另一种策略可能是最好的。对于 2 个节点,最简单的一个是广播,但随着节点数量的增加,问题开始出现(与实际执行 WS 请求相比,您将花费更多时间广播和响应广播)。

节点如何通信,取决于你。你可以打开一个 TCP 管道,你可以广播 UDP,你可以单独为此目的做一个成熟的 WS,你可以使用文件共享协议。无论您做什么,您现在都不再处于进程中,因此分布式计算的所有谬误都适用。

于 2010-02-24T21:27:26.190 回答
2

我建议使用beanstalkd定期将一组请求(作业)泵入管道(队列),每个请求都有适当的延迟。任何数量的“工作”线程或进程都将等待下一个可用请求,如果工作人员提前完成,它可以接收下一个请求。不利的一面是工作人员之间没有任何明确的负载平衡,但我发现队列外的请求分布已经很好地平衡了。

于 2010-02-25T01:51:07.803 回答
1

这是一个有趣的问题,解决的难度在一定程度上取决于你想对节流有多严格。

我通常的解决方案是JBossCache,部分原因是它与 JBoss AppServer 打包在一起,但也因为它可以很好地处理任务。您可以将其用作一种分布式哈希图,以各种粒度记录使用情况统计信息。它的更新可以异步完成,所以它不会减慢速度。

JBossCache 通常用于重型分布式缓存,但我也更喜欢它用于这些轻量级的工作。它是纯 Java,不需要与 JVM 混为一谈(与 Terracotta 不同)。

于 2010-02-24T23:21:58.587 回答
1

Hystrix几乎是为您描述的确切场景而设计的。您可以为每个服务定义一个线程池大小,以便设置最大并发请求数,并在池已满时将请求排队。您还可以为每个服务定义超时,当服务启动超过其超时时,Hystrix 将在短时间内拒绝对该服务的进一步请求,以便让服务有机会重新站起来。还可以通过Turbine对整个集群进行实时监控。

于 2014-09-25T21:39:02.387 回答