英文:
SseEmitter does not throw IOException on client disconnect
问题
根据文档:
Servlet API 在远程客户端断开连接时不提供任何通知。因此,在通过SseEmitter或响应式类型进行响应流时,重要的是定期发送数据,因为如果客户端断开连接,则写入会失败。
根据文档,当调用SseEmitter::send()
方法时,预期会抛出IOException
异常,但我正在使用Spring + 嵌入式Tomcat 9.0.64,却从未抛出此异常,因此无法清理未使用的发射器。
我正在使用以下代码:
try {
emitter.send(SseEmitter.event()
.id(event.getId().toString())
.name("update")
.data(data)
);
} catch (Exception e) {
logger.info("检测到无效的发射器。正在移除...");
deadEmitters.add(emitter);
}
在这种情况下,异常从未触发。我是否做错了什么?
根据文档,我期望会抛出异常。另一个问题提出了类似的问题,但在这种情况下,似乎文档中提到的解决方案根本不起作用。
英文:
According to the documentation:
> The Servlet API does not provide any notification when a remote client goes away. Therefore, while streaming to the response, whether through SseEmitter or reactive types, it is important to send data periodically, since the write fails if the client has disconnected.
This is supposed to manifest as an IOException
when calling the SseEmitter::send()
method, however I am using Spring + Embedded Tomcat 9.0.64 and this exception is never thrown and therefore cleaning up unused emitters is not possible.
I am using the following code:
try {
emitter.send(SseEmitter.event()
.id(event.getId().toString())
.name("update")
.data(data)
);
} catch (Exception e) {
logger.info("Dead emitter detected. Removing...");
deadEmitters.add(emitter);
}
In this case the exception is never triggered. Am I doing something wrong?
I am expecting an exception to be thrown as per the documentation.
Another question has asked something similar, but in this case it seems the documented solution simply does not work.
答案1
得分: 1
以下是您要翻译的内容:
将此内容发布以备将来参考,因为关于这个主题似乎很少有明确的文字记录:
SSE 不提供客户端告知服务器已断开连接的机制,TCP 也不包括此信息。为了保证正确,服务器必须发送响应,尽可能长时间地发送(即直到服务器超时)。
正确的解决方案是在每隔 X 秒在客户端执行一个“心跳”调用,告诉服务器“是的,我还在这里”,然后清理掉那些未能及时报告的连接。
WebSocket 不需要这样做,因为它们默认提供了心跳(PING/PONG)的机制。
英文:
Posting this for posterity as there seems to be little explicitly written about the topic:
SSE doesn't provide a mechanism for the client to tell the server about the fact that it has disconnected and TCP doesn't include this information either. In order to be correct, the server must send responses so long as can (i.e. until a server timeout).
The correct solution is to perform a 'heartbeat' call on the client every X seconds to tell the server "Yes I'm still here" and then sweep up connections that have failed to report back in time.
Websockets do not need this as they provide a mechanism to provide heartbeats (PING/PONG) by default.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论