10

我的页面中有一个区域,当数据库更改时消息会发送到该区域。现在,有些日子数据库会发生如此大的变化,以至于每 10 分钟就会显示一条新消息;其他日子它只会改变几次。我遇到的问题是 EventSource 似乎在 1 小时 22 分钟后超时,并且浏览器将不再收到通知。

我想知道是否有办法让 EventSources 持久化(即,只要浏览器显示页面,EventSource 就处于活动状态)。根据我在 Google 搜索中发现的内容,EventSources 应该保持活动状态,直到选项卡/窗口关闭。不幸的是,我在 Google 搜索中找到的内容似乎很少,对我来说似乎并非如此。

4

2 回答 2

15

你没有说套接字关闭发生在哪里(在浏览器上,客户端机器上的套接字,服务器端上的套接字等),但这并不重要,因为它们的修复都是相同的:send keep - 活着的消息。

服务器应该发送一个保持活动的消息。或者每 15 秒一次;或仅在 15 秒不活动后。(对于您而言,服务器端哪个更容易编码。)它可以像 SSE 注释一样简单:“:\n\n”(以冒号开头的行被忽略)。我更喜欢发送实际数据,因为:

  • 您会看到一条消息,允许客户端保持活动检查(见下文)
  • 您一定要发送一些有用的东西,例如时间戳(用于检查客户端/服务器时钟是否同步)或指标等。

在客户端,运行一个setTimeout()设置为 20 秒的计时器。每次您从服务器收到任何数据(无论是真实数据,还是您的保活数据)时,终止计时器,然后重新启动它。因此,唯一会调用超时函数的情况是,如果您的服务器超过 20 秒而没有向您发送任何内容。发生这种情况时,终止连接并重新连接。

以上假设问题出在套接字级别。问题可能是浏览器正在崩溃:也许它已经耗尽了内存。在这种情况下,我要做的修复是一个每小时一次的计时器(setTimeout()在 JavaScript 中),用于手动关闭和重新打开EventSource连接。或者清除一些您可能正在使用的内存缓冲区。使用 FireBug 或 Chrome 工具进行一些分析会告诉您是否有内存问题。

Plug:在我即将出版的 SSE 书籍中,“让我们的应用程序生产质量”一章中超过一半是关于保持活动状态和在重新连接时使用 LastId。出来的时候请买:-)

于 2013-11-18T23:56:07.763 回答
7

Chrome 每两分钟报告一次“net::ERR_SPDY_PROTOCOL_ERROR 200”时遇到了同样的问题。

每分钟发送一次 SSE 评论为我解决了这个问题。请参阅下面的示例 Nodejs / Express 代码。

exports.addWebServices = function(app) {
  app.get('/ws/clientEvent', function(req, res) {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    })

    /* Event handlers for SSE here */

    let keepAliveMS = 60 * 1000;

    function keepAlive() {
      // SSE comment for keep alive. Chrome times out after two minutes.
      res.write(':\n\n');
      setTimeout(keepAlive, keepAliveMS);
    } 

    setTimeout(keepAlive, keepAliveMS);
  }

}
于 2018-12-29T03:39:20.100 回答