SseEmitter在客户端断开连接时不会抛出IOException。

huangapple go评论146阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年6月6日 07:27:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410574.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定