最近几天,一直在研究服务器推技术,在网上看了很多资料,也下载了很多小例子,总体来说,学到了一些东西,有些心得分享下:
传统模式的 Web 系统以客户端发出请求、服务器端响应的方式工作。这种方式并不能满足很多现实应用的需求,譬如:监控系统:后台硬件热插拔、LED、温度、电压发生变化;
即时通信系统:其它用户登录、发送信息; 即时报价系统:后台数据库内容发生变化;
这些应用都需要服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求。“服务器推”技术在现实应用中有一些解决方案,本文将这些解决方案分为两类:一类需要在浏览器端安装插件,基于套接口传送信息,或是使用 RMI、CORBA 进行远程调用;而另一类则无须浏览器安装任何插件、基于 HTTP 长连接。
将“服务器推”应用在 Web 程序中,首先考虑的是如何在功能有限的浏览器端接收、处理信息:
客户端如何接收、处理信息,是否需要使用套接口或是使用远程调用。客户端呈现给用户的是 HTML 页面还是 Java applet 或 Flash 窗口。如果使用套接口和远程调用,怎么和 JavaScript 结合修改 HTML 的显示。
客户与服务器端通信的信息格式,采取怎样的出错处理机制。 客户端是否需要支持不同类型的浏览器如 IE、Firefox,是否需要同时支持 Windows 和 Linux 平台。
而基于客户端套接口的“服务器推”技术大体可以分为:
传统轮询:在 Web 早期,这一点常使用 meta 刷新实现。这将自动指示浏览器在指定秒数之后重新装载页面,从而支持简陋的轮询( polling )。例如在 HTML 文件中加入 <META HTTP-RQUIV="Refresh" CONTENT=12> ,实际上就是 HTTP 头标告知浏览器每 12 秒更新一次文档。
优点:不需要服务器端配置
缺点:用户体验度差 对服务器的压力很大,带宽流失严重 ajax轮询:Ajax 隔一段时间(通常使用 JavaScript 的 setTimeout 函数)就去服务器查询是否有改变,从而进行增量式的更新。但是间隔多长时间去查询成了问题,因为性能和即时性造成了严重的反比关系。间隔太短,连续不断的请求会冲垮服务器,间隔太长,务器上的新数据就需要越多的时间才能到达客户机。 优点:不需要太多的服务器端配置 降低了带宽的负荷(因为返回的不是完整的页面) 缺点:对服务器的压力并没有减少 实时性差,有一定的延迟 应用:这种技术很常见,很多webmail应用程序就是通过这种技术在电子邮件到达时显示电子邮件的。comet:Comet 方式通俗的说就是一种长连接机制 (long lived http) 。同样是由 Browser 端主动发起请求,但是 Server 端以一种似乎非常慢的响应方式给出回答。这样在这个期间内,服务器端可以使用同一个 connection 把要更新的数据主动发送给 Browser 。因此请求可能等待较长的时间,期间没有任何数据返回,但是一旦有了新的数据,它将立即被发送到客户机。Comet 又有很多种实现方式,但是总的来说对 Server 端的负载都会有增加 . 虽然对于单位操作来说,每次只需要建议一次 connection, 但是由于 connection 是保持较长时间的 , 对于 server 端的资源的占用要有所增加。
优点:实时性好(消息延时小);性能好(能支持大量用户) 缺点:长期占用连接,丧失了无状态高并发的特点。 应用:股票系统。实时通讯。 flash xml socket:这种方案实现的基础是:一、 Flash 提供了 XMLSocket 类。二、 JavaScript 和 Flash 的紧密结合:在 JavaScript 可以直接调用 Flash 程序提供的接口。 优点:实时性好(消息延时小);性能好(能支持大量用户) 缺点:因为 XMLSocket 没有 HTTP 隧道功能, XMLSocket 类不能自动穿过防火墙; 因为是使用套接口,需要设置一个通信端口,防火墙、代理服务器也可能对非 HTTP 通道端口进行限制; 应用:网络聊天室,网络互动游戏。 java appet:在客户端使用 Java Applet ,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 建立与服务器端的套接口连接,从而实现 “ 服务器推送 ” 。 缺点:需要安装java虚拟机 html5:此技术是一个在我认为中较好的技术了,内置了websocket,可以参考。 servlet3.0:作为 Java EE 6 体系中重要成员的 JSR 315 规范,将 Servlet API 最新的版本从 2.5 提升到了 3.0,这是近 10 年来 Servlet 版本号最大的一次升级,此次升级中引入了若干项令开发人员兴奋的特性。 而我所想探讨的方向是comet:comet的介绍:Comet 有时也称反向 Ajax 或服务器端推技术( server-side push )。其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据。听起来简单,但是如果熟悉 Web 应用程序,尤其是 HTTP 协议,那么您就会知道,这绝不简单。实现 Comet 风格的 Web 应用程序,同时保证在浏览器和服务器上的可伸缩性,这只是在最近几年才成为可能。目前一些主流网站都有类似的原理,例如: webQQ 、开心网、校内等等,它们中消息动态都是采用类似的技术,只是具体实现方式不一样。
COMET 的精髓就在于用服务器与 javascript 来维持浏览器的长连接,同时完成服务器端事件的浏览器端响应。这样的事件广播机制是跨网络的,同时也是实时的。 采用了 Comet 技术的服务器在客户机做出一个请求后,和客户机建立一个永久的连接,然后服务器会根据客户机的请求不断把数据包推向客户,这个推的过程是不间断的。由服务器推向客户机的数据在客户机的浏览器上会不断产生新的内容,而且不会产生 Client pull 那样的 HTML 文档头,从而大大减少了延迟的时间,向(服务器响应 -- 客户机请求)同步迈进了一步。 服务器推送通常效率要比客户端拖曳效率高,因为它不必为后续数据建立新的连接。由于始终保持连接,即使没有数据传输时也是这样,因此服务器必须愿意分配这些 TCP/IP 端口,对于 TCP/IP 端口数有限的服务器这将是一个严重的问题。 客户端拖曳效率低,因为这必须每次为传送数据建立新的连接。但是它不必始终保持连接。在实际情况中,建立 HTTP 连接通常需要花费相当多的时间,多达一秒甚至更多。因此从性能上考虑,服务器推送对于最终用户更有吸引力,特别是对于需要经常更新信息的情况下。 服务器推送相对客户端拖曳的另一点优势是,服务器推送相对比较容易控制。例如,服务器每一次推送时都保持一个连接,但它又随时可以关闭其中的任何连接,而不需要在服务器上设置特殊的算法。而客户端拖曳在同样的情况下要麻烦许多,它每次要与服务器建立连接,服务器为了处理将客户端拖曳请求与特定的最终用户匹配等情况,需要使用相当麻烦的算法。 如上所述,在服务器推送中,多个响应中连接始终保持,使服务器可在任何时间发送更多的数据。一个明显的好处是服务器完全能够控制更新数据的时间和频率。另外,这种方法效率高,因为始终保持连接。缺点是保持连接状态会浪费服务器端的资源。服务器推送还比较容易中断。
如果谈到comet的实现,我想应该有死循环法,改写web服务器,和使用框架。
下面是我所参考的一些资料其实实现comet,已经有很多开源的框架了,详情请参考这里;像apahe的jetty项目内部就有comet的例子,想看效果的朋友可以去下载看看,只是jetty主要是介于Continuations特性的在comet的开源框架中,我选择了pushelt,现在的版本好像是2.0.4,主要是使用了观察者模型。浏览器端提供了基于 AJAX 和 iframe 的 JavaScript 库,服务器端使用 Java Servlet。其实dwr框架也可以实现服务器推送的技术,在此不具体讲解了。