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(() -&gt; System.out.println("Timeout detected") 【参考方案4】:

为了解决超时问题,我们使用Long.MAX_VALUE 作为超时,它工作得非常好。

【讨论】:

以上是关于SSE Emitter:管理超时和完成()的主要内容,如果未能解决你的问题,请参考以下文章

SSE 2005 存储过程在管理工作室中工作,但不在 C# DAL 中

软件行业的,SE、SSE啥的是啥啊?

Angular会话超时和管理[重复]

常规会话管理和常见超时

Akka(43): Http:SSE-Server Sent Event - 服务端主推消息

Session管理之超时设置和强制下线