SSE Emitter:管理超时和完成()
Posted
技术标签:
【中文标题】SSE Emitter:管理超时和完成()【英文标题】:SSE Emitter : Manage timeouts and complete() 【发布时间】:2016-11-07 10:20:56 【问题描述】:我正在编写一个 Web 应用程序,其中多个侦听器(Evcentsource SSE 客户端 JS)将连接到我的服务器。我想做的是
-
为每个连接的侦听器存储 SSE 发射器:可以通过为每个客户端分配 id 在内存或任何其他方式中完成,到目前为止我能够实现这一点
现在的问题;如何向连接到我的 Web 应用程序的特定客户端发送响应/事件?在执行此操作时,存储的 SSEEmmiters 要么完成,要么超时。我该如何防止这种情况?如何让 sseEmmiter 无限期开放(直到客户端关闭)并有选择地发送事件。
【问题讨论】:
您使用的是哪种服务器端语言(以及任何库)?可以加标签吗? 【参考方案1】:您需要在 SseEmitter 上设置超时。默认超时时间很短。
SseEmitter timeout 以毫秒为单位。这是一个会话超时,不受会话活动的影响。
超时需要设置为会话的预期持续时间,以毫秒为单位。所以,86400000(或更多)是完全合适的。
【讨论】:
我不知道它如何与反应式方法一起工作,但在标准线程每个请求的情况下,这将导致内存泄漏。即使客户端终止了连接,容器也会使用 DeferredResult 跟踪连接。在 ServletAPI Spec #44 中有一个未解决的错误【参考方案2】:如果您希望 sseEmiter 可以无限打开,您可以简单地将超时设置为 -1L
并有选择地发送事件将所有 sseEmmiter 放在一个带有特定键的地图中,以便在您想要发送事件时使用它 就像我在这段代码中所做的那样。
@Controller
@RequestMapping(path = "api/person")
public class PersonController
@Autowired
private PersonRepository personRepository;
private Map<String, SseEmitter> onPersonAddedSseEmitters = new ConcurrentHashMap<>();
@PostMapping(path = "/add")
public @ResponseBody
String addPerson(@RequestBody Person person)
person.setId(new Random().nextLong());
personRepository.save(person);
onPersonAddedSseEmitters.forEach((key, sseEmitter) ->
try
if (person.getName().startsWith(key.split("-")[0]))
sseEmitter.send(person);
catch (Exception ignored)
sseEmitter.complete();
onPersonAddedSseEmitters.remove(key);
);
return "Saved";
@GetMapping(path = "/onPersonAdded/prefix")
public SseEmitter onPersonAdded(@PathVariable String prefix)
SseEmitter sseEmitter = new SseEmitter(-1L);
onPersonAddedSseEmitters.put(prefix + "-" + new Random().nextLong(), sseEmitter);
return sseEmitter;
【讨论】:
【参考方案3】:有关如何设置适当超时的详细信息。使用 Spring 的 2 种方法
-
使用SseEmitter 构造函数
SseEmitter emitter = new SseEmitter(15000L); // Example for 15s
-
使用 Spring 属性
spring.mvc.async.request-timeout: 15000
引用自文档
默认不设置,这种情况下默认在MVC中配置 使用 Java Config 或 MVC 命名空间,或者如果未设置,则 超时取决于底层服务器的默认值。
【讨论】:
我知道这已经很长时间了,但是有没有办法知道 SseEmitter 何时超时。当 sseEmitter 超时时,我在“eventSource.onerror”事件侦听器中收到消息。有什么方法可以区分其他错误和超时吗? @AmitPokhrel 在服务器端,您可以使用 SseEmitter.onTimeout() 和 SseEmitter.onError() 来检测这些事件并做出反应.例如。emitter.onTimeout(() -> System.out.println("Timeout detected")
【参考方案4】:
为了解决超时问题,我们使用Long.MAX_VALUE
作为超时,它工作得非常好。
【讨论】:
以上是关于SSE Emitter:管理超时和完成()的主要内容,如果未能解决你的问题,请参考以下文章
SSE 2005 存储过程在管理工作室中工作,但不在 C# DAL 中