检测 HttpServlet 中中止的请求
有没有办法确定 HttpServletRequest 是否被中止?
我正在编写一个即时浏览器应用程序(某种聊天):客户端使用 AJAX-HTTP-Requests 循环请求新事件。服务器 (Tomcat) 在 HttpServlet 中处理请求。如果该客户端没有新事件,服务器将延迟回复,直到新事件到达或发生超时(30 秒)。
现在我想确定不再进行轮询的客户端。因此,我在请求结束时启动一个踢定时器,当新请求到达时该定时器停止。如果客户端关闭浏览器窗口,则 TCP 连接将关闭并且 HTTP 请求将中止。
问题:客户端不会遇到踢超时,因为 Servlet 仍然处理事件请求 - 休眠并等待事件或超时。
如果我能够以某种方式侦听连接中止事件,然后通知等待的请求以停止它,那就太好了。但我在 HttpServletRequest 或 HttpServletResponse 中找不到类似的东西......
Is there a way to find out if a HttpServletRequest is aborted?
I'm writing an instant browser application (some kind of chat): The clients asks for new events in a loop using AJAX-HTTP-Requests. The server (Tomcat) handles the requests in a HttpServlet. If there are no new events for this client, the server delays the reply until a new event arrives or a timeout occurs (30sec).
Now I want to identify clients that are no longer polling. Therefore, I start a kick-Timer at the end of a request which is stopped when a new request arrives. If the client closes the browser window the TCP-Connection is closed and the HTTP-Request is aborted.
Problem: The client does not run into the kick-Timeout because the Servlet still handles the event request - sleeping and waiting for an event or timeout.
It would be great if I could somehow listen for connection abort events and then notify the waiting request in order to stop it. But I couldn't find anything like that in the HttpServletRequest or HttpServletResponse...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可能不再对OP有任何帮助,但它可能会帮助其他人尝试检测 HttpServlet 中中止的 HTTP 连接,因为我遇到了类似的问题并最终找到了答案。
关键是,当客户端取消请求时,通常服务器发现的唯一方法是将一些数据发送回客户端,在这种情况下这将失败。我想检测客户端何时停止等待服务器上的长时间计算,因此我最终通过 HttpServletResponse 的编写器定期向响应正文写入单个字符。要强制将数据发送到客户端,您必须调用
HttpServletResponse.flushBuffer()
,如果连接中止,它将抛出ClientAbortException
。This probably won't help the OP any more, but it might help others trying to detect aborted HTTP connections in HttpServlet in general, as I was having a similar problem and finally found an answer.
The key is that when the client cancels the request, normally the only way for the server to find out is to send some data back to the client, which will fail in that case. I wanted to detect when a client stops waiting for a long computation on server, so I ended up periodically writing a single character to response body through
HttpServletResponse
's writer. To force sending the data to the client, you must callHttpServletResponse.flushBuffer()
, which throwsClientAbortException
if the connection is aborted.您可能正在使用某种线程通知(信号量或 Object.wait)来保留和释放 Servlet 线程。如何在等待中添加一个超时(~10 秒),然后以某种方式检查连接是否仍然存在,如果连接仍然存在,则继续等待另外 10 秒。
我不知道是否有可靠的方法来轮询连接的“活跃度”(例如 resp.getOutputStream 不抛出异常),如果有,哪种方法是最好的(最可靠,CPU 强度最小)。
You are probably using some sort of thread-notification (Semaphores or Object.wait) to hold and release the Servlet threads. How about adding a timeout (~10s) to the wait, then somehow checking whether the connection is still alive and then continuing the wait for another 10s, if the connection is still there.
I don't know whether there are reliable ways to poll the "liveness" of the connection (e.g. resp.getOutputStream not throwing an Exception) and if so, which way is the best (most reliable, least CPU intense).
等待请求似乎会很快降低系统的性能。如果请求保持打开状态,响应请求的线程将很快耗尽。您可以尝试完成所有请求(如果没有消息,则向客户端返回“null”),并在后端有一个线程来跟踪客户端轮询以来已经过了多长时间。该线程可以将客户端标记为不活动。
It seems like having waiting requests could degrade the performance of your system pretty quickly. The threads that respond to requests would get used up fast if requests are held open. You could try completing all requests (and returning "null" to your clients if there is no message), and having a thread on the back-end that keeps track of how long it's been since clients have polled. The thread could mark a client as being inactive.