如何正确地限制Web请求到外部系统?

时间:2013-08-23 08:02:49

标签: java nginx rabbitmq throttling

我的Java Web应用程序从我的应用程序的用户请求它和批处理(每晚没有用户请求它的情况下每晚更新)时,从外部系统(JSON over HTTP)中提取一些数据。数据发生变化,因此缓存选项可能会耗尽。

外部系统有一些限制,其中我不知道的确切参数,可能会根据系统负载而变化(例如,峰值时间从一个IP地址每秒10个请求,非高峰时间100来自开放IP地址的每秒请求数)。如果请求过于频繁,则会超时或返回HTTP 503。

现在我正在尝试请求5次,每次之间有2000ms的延迟,如果每次都收到错误就会放弃。这不是最佳的,因为有时在高峰时间几乎所有请求都会失败;我可以避免提出这些要求,也许至少会有一些要成功。

我的目标是拥有一个简单,可靠的设计和足够的灵活性,以便我可以从调节器中提取一些指标,以了解外部系统的响应程度(从而调整它们被调用的频率),以及自动调整我调用它们的间隔(每个系统单独),以便在非高峰时段和高峰时段都是最佳的。

我的基础架构是使用RabbitMQ的Java而不是Linux上的MongoDB。

我正在考虑三个主要选择:

  1. 由于我已经将RabbitMQ用于批处理,我可以引入一个队列,Web进程将向外部系统发送请求,然后工作进程将从该队列中读取,根据需要自行调整,并返回结果。如果需要,这将允许在更多服务器上运行多个并行工作进程。我主要担心的是,这不是一个非常简单的解决方案,以及如何管理高峰时段的吞吐量较低,因此Web流程需要等待很长时间。这也将我的RabbitMQ转换为关键的单一故障点;如果它死了整个系统停止(而不是夜间批处理过程不再运行,这不太重要)。我认为rpc是RabbitMQ使用的正确模式,但不确定。编辑 - 我发布了一个关于如何实现此问题的相关问题How to properly implement RabbitMQ RPC from Java servlet web container?

  2. 介绍nginx(例如ngx_http_limit_req_module),HAProxy(link)或其他代理软件(作为反向代理吗?),让他们通过一些配置魔术来处理限制。专家是我不必更改代码。可以理解的是,它使用的技术更多,而且之前我没有使用过,所以错误配置的可能性非常高。根据外部服务器负载,或者通过批量请求确定实时请求的优先级,或获取限制执行方式的统计信息,进行动态限制也可能并不容易。此外,大多数文档和示例可能会限制传入的请求,而不是传出请求。

  3. 执行纯Java解决方案(例如,漏桶实现)。从某种意义上来说它只是“只是代码”,但是魔鬼在于细节;调试所有的死锁,星球和竞争条件并不总是很有趣。

  4. 我在这里缺少什么?

    在这种情况下哪个是最佳解决方案?

    P.S。一些相关的问题 - 记录所有外部系统调用的正确方法是什么,以便收集关于我调用它们的频率以及成功率是什么的统计数据?

    例如,在每次调用之后,我会调用类似.logExternalSystemInvocation(externalSystemName,wasSuccessful,elapsedTimeMills)之类的东西,然后在需要时从中获取一些聚合数据。

    是否有标准的库/工具可供使用,还是我必须自己动手?

    如果我使用RabbitMQ的选项1.有没有办法组织流程,以便我从RabbitMQ控制台开箱即用?我不想将所有失败的消息发送到毒性队列,但它会填满太快,在大多数情况下,由于用户已经遗憾地继续进行,因此无需重新处理这些失败的请求。

1 个答案:

答案 0 :(得分:1)

也许这个开源系统可以帮到你一点:http://code.google.com/p/valogato/