Comet基于HTTP持久连接服务器推送技术

小夏 科技 更新 2024-02-03

传统上,Web 系统的工作方式是客户端发出请求,服务器响应。 这种方法不能满足许多实际应用的需求,例如:

监控系统:后台硬件热插拔、LED、温度、电压变化; 即时通讯系统:其他用户登录并发送消息; 瞬时**系统:后台数据库内容发生变化; 这些应用程序要求服务器能够实时向客户端提供更新的信息,而无需客户端发出请求。 对于“服务器推送”技术在实际应用中有一些解决方案,本文将这些解决方案分为两类:一类需要在浏览器端安装插件,基于套接字接口传输信息,或者使用RMI和CORBA进行远程调用; 另一种类型不需要浏览器安装任何插件,并且基于HTTP持久连接。

将“服务器推送”应用于 Web 应用程序时,首先要考虑的是如何在功能有限的浏览器端接收和处理信息

客户端如何接收和处理信息,以及是否需要使用套接字或远程调用。 客户端是向用户呈现 HTML 页面还是 J**A 小程序或 Flash 窗口。 如果使用套接字和远程调用,如何结合 j**ascript 修改 HTML 的显示。 客户端和服务器之间传递的信息格式,以及采用什么样的错误处理机制。 客户端是否需要支持不同类型的浏览器,如IE和Firefox,是否需要同时支持Windows和Linux平台。 如果 Web 应用程序的用户接受应用程序只有在安装了 flash 用户时才能运行,那么使用 flash xmlsocket 也是一个可行的解决方案。

实施此类计划的基础是:

Flash 提供 XMLsocket 类。 j**ascript 和 flash 紧密集成:j**ascript 可以直接调用 flash 程序提供的接口。 操作方法如下:在 HTML 页面中嵌入使用 XMLsocket 类的 Flash 程序。 J**AScript 通过调用此闪存程序提供的套接字接口与服务器端套接字进行通信。 J**Ascript 在服务器端接收到 XML 格式传递的信息后,可以轻松控制 HTML 页面内容的显示。

关于如何构建一个充当 J**Ascript 和 Flash XMLase 之间桥梁的 Flash 程序,以及如何调用 J**Ascript 中 Flash 提供的接口的更多信息,我们可以参考 Aflax (Asynchronous Flash and XML) 项目提供的 Socket Demo 和 SocketJS(参见参考资源)。

j**ascript 和 flash 的紧密集成大大增强了客户端的处理能力。 从 Flash v70.从 19 开始,删除了 xmlsocket 端口必须大于 1023 的限制。 Linux 平台还支持 Flash XMLsocket 方案。 但这种情况的缺点是:

客户端必须安装闪存服务器; 由于 xmlsocket 没有 HTTP 隧道功能,因此 xmlsocket 类无法自动通过防火墙; 因为是套接字接口,所以需要设置通信端口,防火墙和服务器也可能限制非HTTP通道端口; 然而,这个解决方案已经广泛地应用在一些在线聊天室和在线互动游戏中。

在客户端使用 j**a 小程序,通过j**a.net.socketj**a.net.datagramsocketj**a.net.multicastsocket与服务器端建立套接字连接,从而实现“服务器推送”。

这种方案最大的缺点是 j**a 小程序在收到服务器返回的信息后,无法通过 j**ascript 更新 html 页面的内容。

作为 Web 应用程序的前景,浏览器的处理能力有限。 浏览器的发展需要客户端对软件进行升级,同时,由于客户端浏览器软件的多样性,从某种意义上说,也影响了浏览器新技术的推广。 在 Web 应用程序中,浏览器的主要工作是发送请求,解析服务器返回的信息,并以不同的样式显示。 AJAX 是浏览器技术发展的结果,它通过在浏览器端发送异步请求来提高单用户操作的响应能力。 但网络本质上是一个多用户系统,对于任何用户来说,服务器都可以被认为是一个不同的用户。 现有 AJAX 技术的发展并不能解决在多用户 Web 应用程序中实时向客户端提供更新信息的问题,因此用户可能会使用“过时”的信息进行操作。 使用 AJAX 可以更频繁地在后台更新数据。

图1传统 Web 应用程序模型与基于 AJAX 的模型的比较。

服务器推送是一种由来已久的技术,主要通过客户端的socket接口或服务端远程调用来实现。 由于浏览器技术的发展比较缓慢,没有为“服务器推送”的实现提供很好的支持,在纯浏览器应用中很难有一个完美的解决方案来实现服务器推送并在商业程序中使用。

近年来,由于AJAX技术的普及,以及将iframe嵌入到“HTMLFILE”的ActiveX组件中可以解决IE的加载和显示问题,一些流行的应用程序如Meebo,Gmail+Gtalk在其实现中使用了这些新技术; 同时,在实际应用中,“服务器推送”确实有很多要求。 由于这些原因,纯浏览器的“服务器推送”技术开始受到关注,Alex Russell(Dojo Toolkit 的项目负责人)将这种不需要在浏览器端安装插件的基于 HTTP 持久连接的服务器推送技术称为 Comet。

已经有一些成熟的COMET应用和各种开源框架; 一些 Web 服务器(如 Jetty)也在进行大量改进,以支持具有大量并发性的长连接。 有关彗星技术的最新发展,请参阅彗星维基。

以下是这两个 Comet 应用程序的实现模型。

如图1所示将传统的 Web 应用程序模型与基于 AJAX 的模型进行比较表明,AJAX 的出现允许 J**Ascript 调用 XMLhttpRequest 对象来发出 HTTP 请求,而 J**Ascript 响应处理程序根据服务器返回的信息更新 HTML 页面的显示。 使用 AJAX 实现“服务器推送”与传统的 AJAX 应用程序的不同之处在于,服务器端会阻止请求,直到出现数据传递或超时。 客户端 j**ascript 响应处理程序在处理服务器返回的信息后,通过发出另一个请求来重新建立连接。 当客户端处理接收到的数据并重新建立连接时,新数据可能会到达服务器端; 此信息将存储在服务器上,直到客户端重新建立连接,并且客户端将立即从当前服务器检索所有信息。 图2基于长轮询的服务器推送模型。

一些应用程序和示例(如“meebo”和“pushlet chat”)使用这种长轮询方法。 这种长轮询方法也可以称为“拉动”,而不是“轮询”。 由于此方案基于 AJAX,因此它具有一些优点:异步发出请求; 无需插件安装; IE 和 Mozilla Firefox 都支持 AJAX。

在这种长轮询模式下,当 xmlhttprequest 的 readystate 为 4(即数据传输结束)时,客户端调用 ** 函数来处理信息。 当 readystate 为 4 时,数据传输结束,连接关闭。 Mozilla Firefox 提供了对 Streaming AJAX 的支持,即当 ReadyState 为 3(数据仍在传输中)时,客户端可以读取数据,从而能够读取和处理服务器返回的信息,而无需关闭连接。 当 IE 为 ReadyState 3 时,无法读取服务器返回的数据,目前 IE 不支持基于 AJAX 的流式处理。

iframe 是一种已经存在了很长时间的 HTML 标记,通过在 HTML 页面中嵌入一个隐藏的框架,然后将这个隐藏框架的 src 属性设置为持久连接的请求,服务器端不断地向客户端提供数据。

图3基于流模式的服务器推送模型。

上一节提到的 AJAX 解决方案是处理 j**ascript 中 XMLhttpRequest 从服务器检索到的数据,然后 j**ascript 可以很容易地控制 html 页面的显示。 同样的想法也适用于 iframe 方案的客户端,其中 iframe 服务器不返回直接显示在页面上的数据,而是返回对客户端的 j**ascript 函数的调用,例如“.”。服务器端将返回的数据作为参数传递给客户端的 j**ascript 函数; 客户端浏览器的 j**ascript 引擎在收到来自服务器的 j**ascript 调用时执行它。

从图 3 中可以看出,并不是每次传输数据时都关闭连接,而是仅在出现通信错误或重建连接时关闭(某些防火墙通常设置为丢弃长连接,服务器可以设置超时来通知客户端重新建立连接并关闭原始连接)。 使用 iframe 请求持久连接有一个明显的缺点:IE 和 Morzilla Firefox 底部的进度条将显示加载未完成,并且 IE 上方的图标将旋转以指示加载正在进行中。 谷歌的天才们使用一个名为“HTMLFILE”的ActiveX来解决IE中的加载显示问题,并将其应用于Gmail+Gtalk产品。 亚历克斯·罗素(Alex Russell)在“还有什么被埋在谷歌惊人的j**ascript的深处?本文介绍了此方法。 Zeitoun **彗星-iframe。tar.GZ,封装了一个基于 iframe 和 htmlfile 的 j**ascript comet 对象,支持 IE 和 Mozilla Firefox 浏览器,可以作为参考。 (见参考文献)。

以上介绍了两种基于 HTTP 持久连接的“服务器推送”体系结构,并详细介绍了客户端处理持久连接的技术。 对于实际应用来说,系统的稳定性和性能非常重要。 在实际应用程序中使用 HTTP 持久连接时,需要考虑许多细节。

当我们使用IE文件时,我们有这种经验,并且从同一个Web服务器文件中,最多只能同时有两个文件。 第三个文件将被阻止,直到前一个文件完成。 这是因为 HTTP 11 该规范规定,客户端与服务器的 HTTP 连接不应超过两个,因为新连接将被阻止。 IE 在实施过程中严格遵守此规则。

http 1.1 对两个持久连接的限制会给使用持久连接的 Web 应用程序带来以下现象:如果客户端打开两个以上的 IE 窗口来访问使用持久连接的同一 Web 服务器,则第三个 IE 窗口的 HTTP 请求会被前两个窗口的持久连接阻止。

因此,在开发持久化应用时,需要注意这样一个事实,即在使用多个帧的页面中,不要为每个帧页面建立HTTP持久连接,这样会阻塞其他HTTP请求,并考虑让多个帧更新共享单个持久连接的设计。

典型的 Web 服务器会为每个连接创建一个线程,如果在大型业务应用程序中使用 Comet,则服务器端需要维护大量并发持久连接。 在此应用程序上下文中,需要在服务器端考虑负载平衡和集群技术; 或者对服务器端的持久连接进行一些改进。

应用和技术的发展总是带来新的需求,进而推动新技术的发展。 http 1.1 对 10 规格有一大区别:1在 0 规范下,服务器在处理每个 get post 请求后将关闭套接字连接; 和 11 服务器保持此连接,并在两个请求之间的时间内处于空闲状态。 j**a 1.4 引入了支持异步 IO 的 j**a.蔚来包装。 当连接处于空闲状态时,为该连接分配的线程资源将返回到线程池,并可供新连接使用。 当具有原始空闲连接的客户发出新请求时,将从线程池中分配线程资源来处理该请求。 在连接空闲概率高且并发连接数高的情况下,此技术在减少服务器上的资源负载方面非常有效。

然而,随着 ajax 的使用使请求更加频繁,并且彗星长时间占用连接,上述服务器模型在新应用程序的上下文中变得非常低效,线程池中有限的线程数量甚至可能阻止新的连接。 Jetty 6 Web 服务器对 Ajax 和 Comet 应用程序的特性进行了许多创新改进,请参考文章 “Ajax, Comet and Jetty” (参见 参考资料)。

使用持久连接时,有一个非常常见的场景:客户端网页需要关闭,服务器仍处于读取数据的状态,客户端需要及时通知服务器关闭数据连接。 服务器收到关机请求后,首先从读取数据的阻塞状态中唤醒,释放分配给客户端的资源,然后关闭连接。

因此,按照设计,我们需要让客户端的控制请求和数据请求使用不同的HTTP连接,这样控制请求就不会被阻塞。

在实现方面,如果是基于iframe流的持久连接,客户端页面需要使用两个iframe,一个是控制帧,用于向服务端发送控制请求,控制请求可以快速收到响应,不会被阻塞; 一个是显示框,用于向服务器发送持久连接请求。 在基于 AJAX 的长轮询的情况下,客户端可以异步发出 XMLhttpRequest 请求,以通知服务器关闭数据连接。

保持浏览器和服务器之间的持久连接会给通信带来一些不确定性:由于数据传输是随机的,客户端不知道服务器何时会传输数据。 服务器端需要确保当客户端不再工作时,释放分配给客户端的资源,以防止内存泄漏。 因此,需要一种机制,让双方都知道每个人都在正常运作。 关于实施:

服务器在阻塞读取时设置了时间限制,超时后会返回阻塞的读调用,并将没有新数据到达的心跳信息发送给客户端。 这种情况下,如果客户端关闭,服务器会异常地向通道写入数据,服务器会及时释放分配给客户端的资源。 如果客户端使用基于 AJAX 的长轮询方法; 服务器返回数据并关闭连接后,如果在一定时间后没有收到来自客户端的进一步请求,则认为客户端无法正常工作,并释放为客户端分配和维护的资源。 如果服务器在处理信息时出现异常,需要发送错误信息通知客户端、释放资源、关闭连接。 Pushlet 是一个开源的 COMET 框架,在设计方面有很多值得借鉴的地方,对于开发轻量级的 COMET 应用程序非常有价值。

观察者模型 pushlet 使用观察者模型:客户端发送请求并订阅感兴趣的事件; 服务器将会话 ID 作为令牌分配给每个客户端,事件源将新生成的事件多播到订阅者的事件队列。

客户端 j**ascript 库 pushlet 为长轮询模式下的“服务器推送”提供基于 ajax 的 j**ascript 库文件; 还为流模式下的“服务器推送”提供了基于 iframe 的 j**ascript 库文件。

j**ascript 库做了很多封装:

定义客户端的通信状态:state_errorstate_abortstate_nullstate_readystate_joinedstate_listening;服务器分配的会话 ID 将被保存,并且会话 ID 将在建立连接后附加到每个请求。 是的join()le**e()subscribe()unsubsribe()listen()和其他用于页面调用的 API; 提供用于处理响应的 j**ascript 函数的接口ondata()onevent()…网页可以使用这两个 j**ascript 库文件封装的 API 轻松地与服务器通信。

客户端-服务器通信信息格式 pushlet 使用 XML 格式定义一组用于客户端-服务器通信的信息格式。 定义客户端发送的请求类型:joinle**esubscribeunsubscribelistenrefresh;以及响应的事件类型:datajoin_acklisten_ackrefreshheartbeaterrorabortsubscribe_ackunsubscribe_ack

服务器端事件队列管理 Pushlet 是使用 J**A servlet 在服务器端实现的,其数据结构设计框架仍然可以应用于用 PHP 和 C 编写的后端客户端。

Pushlet 允许客户端选择使用流、拉取(长轮询)和轮询方法。 服务器端在读取事件队列 (fetchevents) 时以不同的方式处理 fetchevents,具体取决于客户选择的方式。 轮询模式fetchevents()很快就会回来。 如果超时,它会在没有收到新信息的情况下向客户端发送“心跳”事件,如果处于“拉取”模式,则会将“心跳”和“刷新”事件传递给客户端,以通知客户端重新发出请求并建立连接。

客户端服务器之间的会话管理在客户端发送join请求时,会为客户端分配一个会话 ID 并传递给客户端,然后客户端使用该 ID 来标识客户端subscribelisten请求。 服务器端为每个会话维护一个订阅的主题集合,即事件队列。

服务器端事件源将新事件多播到每个会话(即订阅者)的事件队列中。

本文介绍如何在现有技术的基础上选择合适的方案来开发“服务器推送”应用,最优方案取决于应用需求。 与传统的 Web 应用程序相比,开发 Comet 应用程序仍然具有挑战性。

为了使 Comet 模型适合大规模商业应用,方便用户构建 Comet 应用,近年来,服务器和浏览器中都涌现出许多新技术,以及许多开源的 Comet 框架和协议。 需求正在推动技术的发展,相信彗星的采用将像阿贾克斯一样无处不在。

相似文章

    什么是SSL?HTTP 和 HTTPS 之间的影响和差异

    SSL 安全套接字层 是一种安全套接字层 SSL 协议,也是传输层安全性 TLS 的前身。它位于TCP IP协议和各种应用层协议之间,为数据通信提供安全支持,是目前应用最广泛的安全协议之一。SSL在连接到Internet或内部网络的两台计算机之间提供了一个安全的信息通道,即HTTPS。SSL通过在数...

    在HTTPS网站中使用SSL证书有什么好处?

    HTTPS作为 生产的标准配置已经是大势所趋。首先,我们来谈谈SSL和HTTPS的关系,SSL是服务器安全证书,只有安装了SSL证书的 才能使用HTTPS进行访问。不同的SSL证书显示不同的HTTPS站点状态,理论上SSL安全证书越贵,安全性就越高,当然也会受到SSL品牌知名度的影响。对于普通用户来...

    基于Java SpringBoot和Vue的医院信息管理挂号系统

    总结 医院信息管理系统 HIMS 是应用于医疗机构的信息管理系统,旨在提高医疗服务质量,降低运营成本,提高工作效率,满足患者需求。通过对医院内各种信息的整合 管理和共享,实现医疗资源的有效利用和优化配置。HIMS的实施和应用,将有助于提高医院的管理水平,提高医疗服务质量,降低医疗成本,实现医疗资源的...

    基于 Prometheus Grafana 4 设置 IT 监控和告警的最佳实践

    看到像面孔一样的文字,大家好,我是小飞,上一篇文章介绍了发电机YML 文件配置和 prometheusYML文件配置,包括文件服务自动发现机制,以及基于生成器YML配置,根据SNMP导出器提供的生成器,生成SNMPYML配置文件等,今天主要讲解官方环境的配置和情况,包括虚拟机节点导出器节点数据采集器...

    基于 Prometheus Grafana 3 设置 IT 监控和告警的最佳实践

    大家好,我是小飞。延续上一部分,主要讲解配置文件的用途和说明,上一部分链接如下 Prometheus Grafana 构建 IT 监控和告警最佳实践 扩展交换机的数据采集,因为节点导出器采集器完善,使用官网模板采集数据基本满足当前需求,没有定制需求,而且Grafana的面板在Grafana官网上也有...