Java 我可以限制分布式应用程序发出的请求吗?

Java 我可以限制分布式应用程序发出的请求吗?,java,jakarta-ee,throttling,Java,Jakarta Ee,Throttling,我的应用程序发出Web服务请求;提供商将处理的请求有一个最大速率,因此我需要限制它们 当应用程序在一台服务器上运行时,我习惯于在应用程序级别上运行:一个跟踪到目前为止发出了多少请求的对象,并在当前请求超出允许的最大负载时等待 现在,我们正在从单个服务器迁移到集群,因此有两个应用程序副本正在运行 我无法继续检查应用程序代码的最大负载,因为两个节点的组合可能超过允许的负载 我不能简单地减少每台服务器上的负载,因为如果另一个节点空闲,第一个节点可以发送更多的请求 这是一个JavaEE5环境。限制应

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

当应用程序在一台服务器上运行时,我习惯于在应用程序级别上运行:一个跟踪到目前为止发出了多少请求的对象,并在当前请求超出允许的最大负载时等待

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

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

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

很多方法:您可能有一个“协调代理”,负责向服务器传递“令牌”。每个“令牌”表示执行任务等的权限。每个应用程序需要请求“令牌”才能进行调用

一旦应用程序耗尽了它的令牌,它必须在继续再次访问Web服务之前请求更多令牌

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


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

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

  • 广播:每个节点将向其他所有节点广播它正在呼叫,所有其他节点将考虑这一点。节点是相等的,并保持单独的全局计数(每个节点都知道其他每个节点的呼叫)
  • 主节点:一个节点是特殊的,它是主节点,所有其他节点在进行呼叫之前都需要获得主节点的许可。主机是唯一知道全局计数的主机
  • 专用主服务器:与主服务器相同,但“主服务器”不在其LEF上进行呼叫,只是一种跟踪呼叫的服务
根据您预期的后期扩展程度,一种或另一种策略可能是最好的。对于2个节点,最简单的一个是广播,但随着节点数量的增加,问题开始增多(您将花费更多的时间广播和响应broadcats,而不是实际执行WS请求)


节点如何通信取决于您。您可以打开一个TCP管道,您可以使用broadcats UDP,您可以单独为此做一个完全成熟的WS,您可以使用文件共享协议。无论您做什么,您现在都不再在流程中,因此所有的请求都将被应用。

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

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


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

这是一个有趣的问题,解决方案的难度在一定程度上取决于您对节流的严格程度

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


JBossCache通常用于重载分布式缓存,但我也比较喜欢用于这些较轻的工作。它是纯java,不需要与JVM打交道(与Terracotta不同)。

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

的设计与您所描述的场景基本相同。您可以为每个服务定义线程池大小,以便设置最大并发请求数,并在池满时对请求进行排队。您还可以为每个服务定义一个超时,当服务开始超过其超时时,Hystrix将在短时间内拒绝对该服务的进一步请求,以使该服务有机会重新开始。还可以通过对整个集群进行实时监控。

只是好奇,您是否使用了Terracota这样的特殊框架?@Pablo:不。我们正在从专用服务器上的一台JBoss服务器迁移到一台配置了两个节点的托管WebLogic 10.3。+1因为我不知道RabbitMQ也有.net绑定。是的,因为我已经使用了JavaEE环境,所以JavaEE队列是最简单的解决方案,我不需要添加任何其他依赖项。