手机上的服务器发送事件 (SSE) 连接丢失

Posted

技术标签:

【中文标题】手机上的服务器发送事件 (SSE) 连接丢失【英文标题】:Server-sent events (SSE) connection loss on mobile phones 【发布时间】:2017-10-17 21:25:22 【问题描述】:

我正在开发一个使用 SSE(EventSource API)向客户端广播一些事件的网站。在 android 版 Chrome 的移动版上测试我的网站时,我注意到当频道空闲大约五分钟时连接会丢失。

我使用了几款安卓设备,不同的运营商和不同的浏览器,无论屏幕是开还是关,结果都是一样的。桌面 Chrome 似乎可以使连接保持更长时间。

找不到有关此的任何信息,并且在尝试调试问题时,我得到的只是在发送最后一个事件后大约 3 分半钟从电话 IP 地址收到的 TCP“FIN”数据包。

EventSource 的 onerror 事件没有被触发,所以我不知道何时断开连接以启动新连接。

有什么办法可以避免这个问题,还是我应该每 30 秒发送一些假消息来防止连接空闲?

提前致谢

【问题讨论】:

【参考方案1】:

您可以设置retry字段来建立reconnection time的EventSource实例

如果字段名是“重试”

如果字段值仅包含 ASCII 数字,则将字段值解释为以十为底的整数,并设置事件流的 重新连接到该整数的时间。否则,忽略该字段。

【讨论】:

感谢您的回答,客人!不幸的是,发送“重试”没有任何区别:就像客户端断开连接并且再次建立连接一样。 您是否尝试过在不到五分钟的时间内发送消息? 是的,例如,如果我每两分钟发送一次消息,则连接永远不会断开。所以我可以每分钟左右发送一次“保持活动”消息,但我想知道是否有更好的方法来做到这一点。 目前无法在移动 Chrome 上测试代码。不确定该版本的实施是否旨在节省电池?您可以尝试定义一个单独的命名事件以保持连接活动并将与应用程序相关的消息发送到message 事件。您是否提交了描述问题的bug 报告? 我在不同的 Android 设备上进行了尝试,其中一些通过 USB 连接(以防它们处于省电模式),但都表现相同。也有不同的 Chrome 版本。我想在报告错误之前收集一些信息。关于单独的事件,我发现 SSE 将所有以“:”开头的行视为 cmets,因此它看起来是一种发送这些 keepalive 消息的便捷方式。【参考方案2】:

您的连接可能是由“推送代理”获取的,该功能旨在延长手机的电池寿命。

引自“https://html.spec.whatwg.org/multipage/server-sent-events.html”:

在受控环境中运行的用户代理,例如浏览器开启 绑定到特定运营商的手机,可以减轻管理负担 连接到网络上的代理。在这种情况下, 出于一致性目的的用户代理被认为包括 手机软件和网络代理。

例如,移动设备上的浏览器在建立了 连接,可能会检测到它在支持网络上,并且 请求网络上的代理服务器接管 连接。这种情况的时间表可能如下:

    浏览器连接到远程HTTP服务器并请求作者在EventSource构造函数中指定的资源。 服务器偶尔发送消息。 在两条消息之间,浏览器检测到它处于空闲状态,除了保持 TCP 连接处于活动状态的网络活动, 并决定切换到睡眠模式以节省电量。 浏览器与服务器断开连接。 浏览器联系网络上的服务,并请求该服务(一个“推送代理”)来维持连接。 “推送代理”服务联系远程HTTP服务器,请求EventSource中作者指定的资源 构造函数(可能包括Last-Event-ID HTTP 标头等)。 浏览器允许移动设备进入睡眠状态。 服务器发送另一条消息。 “推送代理”服务使用诸如 OMA 推送之类的技术将事件传送到移动设备,移动设备只需唤醒足以 处理事件,然后返回睡眠状态。

这可以减少总数据使用量,因此会导致 节省大量电力。

【讨论】:

以上是关于手机上的服务器发送事件 (SSE) 连接丢失的主要内容,如果未能解决你的问题,请参考以下文章

SSE 服务器发送事件 - 客户端不断发送请求(如池)

Javascript Ajax总结——其他跨域技术之服务器发送事件SSE

通过 Nginx 在 Node.js 上的服务器发送事件连接超时

Spring boot:SSE 服务器发送的事件不起作用

Ktor sse 客户端断开连接

服务器发送事件 - 在几次断开连接后流未重新连接