2

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

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

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

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

我的基础设施是 Java 和 RabbitMQ over MongoDB over Linux。

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

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

  2. 引入 nginx(例如ngx_http_limit_req_module)、HAProxy(链接)或其他代理软件(作为反向代理?),让他们通过一些配置魔法来处理节流。优点是我不必更改代码。缺点是它使用了更多技术,而且我以前没有使用过,因此错误配置某些东西的可能性非常高。根据外部服务器负载进行动态限制,或将实时请求优先于批处理请求,或获取限制如何进行的统计数据也可能并不容易。此外,大多数文档和示例可能会限制传入请求,而不是传出请求。

  3. 做一个纯Java 解决方案(例如,漏桶实现)。从“只是代码”的意义上说,这很简单,但魔鬼在细节中;调试所有的死锁、饥饿和竞争条件并不总是很有趣。

我在这里想念什么?

在这种情况下,哪个是最好的解决方案?

PS有点相关的问题-记录所有外部系统调用的正确方法是什么,以便收集有关我调用它们的频率以及成功率的统计信息?

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

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

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

4

1 回答 1

1

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

于 2013-09-09T09:16:39.403 回答