防止对 java servlet 的重复请求

Preventing duplicate requests to java servlet

我有一个 java serlvet,它访问 hadoop 集群并从 hadoop 集群发送一些数据的可下载 csv 作为响应。

我的问题是这个 servlet 似乎有多个 GET 请求(据我所知,这是针对 chrome + 其他浏览器的),这导致多个连接打开到我的 Hadoop 集群。我不想一次有多个请求。有没有办法拒绝来自同一来源的多个请求,只响应第一个请求?

我不清楚您声称该行为是故意的依据是什么。您在评论中引用的另一个 SO 问题只是提出了相同的主张,而没有引用任何来源。然而,最后,这可能并不重要:如果该行为很常见,而不是与少数 特定的 错误实例相关联,您可以修复,那么您无论如何都可能需要处理它。

话虽如此,GET 请求原则上不应该更改服务器的状态(因此它们应该是幂等的)。这可以被视为各种有趣和烦人的行为的理由。但是,由于没有理由进行类似的重复或抢先 POST 请求,我希望您可以通过禁用相关资源的 GET 方法并强制客户端改为 POST 请求它。我认为客户不会发出重复的请求,除非用户明确指示(例如,通过双击 link / 按钮)。

另一方面,假设您的 Web 应用程序正在执行会话跟踪——在大多数 servlet 容器中默认启用——您可以检测多个并发请求并处理它们。具体来说,您可以在开始处理此类请求时设置会话属性,在完成时清除它,并让 servlet 测试该属性以确定如何处理每个请求。

我在评论中建议您可以 return 重复请求的错误代码,确实可以,但这种行为可能会让客户感到惊讶,因为他们可能希望 GET 请求是幂等的。作为替代方案,您可以考虑延迟对重复请求的服务,直到计算完成,然后根据相同的计算结果为所有请求提供相同的响应。

然而,据我所知,您不能简单地删除重复的请求。在 Servlet API.

的任何地方都没有这样做的机制

解决方法:Nginx代理缓存

你可以把 Nginx in-front 的 java servlet。 Nginx有一个缓存模块和防止雷群的必要机制。

虽然你的问题不涉及高并发,但你仍然可以使用nginx缓存锁定机制,它会在定义的时间段内锁定缓存,只允许一个请求填充缓存。

文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache

proxy_cache_lock on;
proxy_cache_lock_age 5s; # depending on the use case
proxy_cache_lock_timeout 5s;