【问题标题】:Persistent push with comet long-polling on Jetty?Jetty 上的彗星长轮询持续推动?
【发布时间】:2011-11-16 08:17:48
【问题描述】:

我正在尝试创建一个 Jetty servlet,它允许客户端(网络浏览器、Java 客户端等)从网络服务器获取广播通知。

通知应以 JSON 格式发送。

我的第一个想法是让客户端发送一个长轮询请求,服务器在通知可用时使用 Jetty 的 Continuation API 进行响应,然后重复。

这种方法的问题是我错过了 2 个请求之间发生的所有通知。

我为此找到的唯一解决方案是在服务器上缓冲事件并使用时间戳机制来重新传输错过的通知,这很有效,但它的作用似乎很重......

知道如何更优雅地解决这个问题吗?

谢谢!

【问题讨论】:

    标签: java servlets jetty comet long-polling


    【解决方案1】:

    您可能想检查他们如何在 CometD 中实现这一点:http://cometd.org。 或者您甚至可以考虑使用该工具,而无需重新发明轮子。

    【讨论】:

      【解决方案2】:

      在通过 Atmosphere 框架使用 Http Streaming 之前,我已经完成了这项工作,并且效果很好。

      访问Comet, Streaming

      如果你看到他们给出了多个例子的气氛教程

      【讨论】:

        【解决方案3】:

        HTTP Streaming 绝对是比 HTTP 长轮询更好的解决方案。 WebSockets 是一个更好的解决方案。

        WebSockets 提供了第一个标准化的双向全双工解决方案,用于在 任何 客户端(不必是 Web 浏览器)和服务器之间在 Web 上进行实时通信。恕我直言,WebSockets 是要走的路,因为它们是一种将继续被开发、支持和需求的技术,并且只会在使用和普及方面增长。他们也超级酷:)

        似乎有a few WebSocket clients for Java 和Jetty also supports WebSockets。

        【讨论】:

        • @leggeter:我同意 WebSockets 对这项工作来说是完美的,不幸的是,我目前无法承受他们有限的浏览器支持。不过,我会看看 HTTP Streaming。谢谢!
        • 我强烈建议您阅读@katana 关于WebSocket readiness 的出色回答。带有后备功能的 WebSockets 意味着 99% 的 Web 浏览器可以使用 WebSocket 连接。
        • 代理不能很好地支持 Web 套接字。如果您的客户端和服务器之间有代理,您可能需要一个备用方法。
        • 如果您使用 SSL (wss://) WebSocket 连接,那么根据我处理大量 Pusher 支持调用的经验,连接将被建立。我认为 WebSockets 不能很好地与代理一起工作的主要原因是因为开发人员在开发时不使用 SSL 连接,因此不检查它是否能解决问题。不幸的是,我还不能证明这一点。
        【解决方案4】:

        对不起,我把这个问题搞砸了,但我相信很多人会遇到这个帖子,并且接受的答案,恕我直言,至少已经过时了,更不用说误导了。

        按照优先级排序如下:

        1) WebSockets 是当今的解决方案。我个人有在面向企业的应用程序中引入 WebSockets 的经验。所有主要浏览器(Chrome、Firefox、IE - 按字母顺序排列:))都支持WebSockets。所有主要的服务器/servlet(IIS、Tomcat、Jetty)都是相同的,并且有相当多的 Java 框架实现了JSR 356 API。代理存在问题,尤其是在云部署中。然而,人们对 WebSockets 的要求有很高的认识,所以 NginX 早在 1.5 年前就已经支持它们了。无论如何,安全的“wss”协议解决了 99.9% 的代理问题(为了安全起见,不是 100%,我自己从未经历过)。

        2) Long Polling 可能是第二好的解决方案,而“可能”部分是由于“短轮询”替代方案。当谈到长轮询时,我的意思是从客户端到服务器的重复请求,一旦有任何数据可用,它就会响应。因此,一个轮询可以在几毫秒内完成,另一个轮询 - 直到最大等待时间。 确保将轮询时间限制在 2 分钟以内,否则通常需要在客户端管理超时错误。我建议将轮询时间限制为几十秒。 可以肯定的是,一旦轮询完成(及时或在此之前),它会立即重复(但最好建立一些简单的协议并让您的服务器有机会对客户端说 - '暂停')。 长轮询的缺点(恕我直言)证明列表的延续是合理的,它拥有少数几个(4、8 个?仍然不是那么多)允许的连接之一,该浏览器允许每个页面建立到服务器。因此,这可能会占用您网站的客户端流量资源的 ~12% 到 ~25%。

        3) Short polling 不是很多人喜欢的,但有时我更喜欢它。这个的主要缺点当然是在建立新连接时浏览器和服务器上的高负载。然而,我相信,如果正确使用连接池,那么开销会比乍看之下要少得多。

        4) HTTP 流式传输,无论是通过 IFrame 的页面流式传输还是 XHR 流式传输,恕我直言,非常糟糕解决方案,因为它就像所有缺点的累积休息等等:

        • 您将保持打开的连接(浏览器和服务器的资源);

        • 您仍然会从总可用客户端流量限制中吃光;

        • 最邪恶:您需要设计/实现(或重复使用设计/实现)实际的内容交付,以便能够将 新 内容与 区分开来旧的 一个(无论是在推送脚本中,哦,我的!或跟踪累积内容的长度)。请不要这样做。

        更新(2019 年 2 月 20 日)

        如果 WebSockets 不是一个选项 - Server Sent Events 是第二个最佳选项恕我直言 - 有效的浏览器在较低级别为您实现了 HTTP 流。

        【讨论】:

        • 我不明白你对HTTP Streaming 的回答。您能否更明确地说明此选项的赞成/反对案例?它似乎相当于单个长轮询连接(相对于多个连接),所以如果有的话,它听起来比长轮询更好。
        • HTTP流,大致如下:从客户端打开一些GET请求,在服务器中保存一个响应的输出流,然后不时写入。它对客户端的看法:您将正在侦听和处理进度事件。每次有进展时,您都想知道新数据是什么。不可能直接问这个问题,但您需要保存到目前为止的所有数据(您也无法清理),并且每个进度事件都会计算数据的最后状态和当前状态之间的差异。有时您需要全部重置以清理内存。
        • 在长轮询风格中,没有并发的多个连接,但是是的,您在每次服务器端消息迭代时都重新打开连接(如果您愿意,每次连接已被“消耗”它)。尽管如此,在代码清洁度和可维护性方面,从客户端和服务器的角度来看,对我来说看起来都更干净。顺便说一句,如果 WebSockets 不是一个选项 - 服务器发送事件是第二个最佳选项恕我直言 - 有效的浏览器在较低级别为您实现了 HTTP 流。
        • 这听起来不像 HTTP 流(分块编码)必须按照您描述的方式实现。您可以在其之上实现幂等协议,以便您收到的任何事件都包含绝对值。这样您就不必保留任何状态并计算数据的最后状态和当前状态之间的差异。
        • 如果你的意思是你的“在它之上”,那可以给你自己写一些低级库抽象意识整个'从一开始就得到完整的身体,从中删除以前已知的数据并给出只有差异' - 很好。然而,你仍然会在某个地方写这些东西。如果你的意思是它可能会以完全不同的方式实现 - 欢迎你来破解并启发我和可能其他人如何做到这一点:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-11
        • 2011-06-18
        • 1970-01-01
        • 2015-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多