【IT168 专稿】如果你在Google中搜索“AJAX Web 2.0”,你可以得到上亿条搜索结果,但是你能从中发现有什么技术能真正实现今天的Web 2.0所承诺的东西吗?虽然Web 2.0至今还没有一个统一的定义,不过它的核心一定是作为社会化网络平台的互联网,在这个平台上具有相同爱好的群体可以创建和分享信息。富互联网应用(RIA)体现了部分Web 2.0概念,它提供了一个更加高效的用户界面,从而完善了Web 2.0平台;而AJAX之于Web 2.0之处则在于,它提供了一个开发RIA应用的轻量级方法,即RIA应用可通过Web浏览器这个单一的界面来执行。
如果研究一下像维基百科和博客等现有社会化网络平台的交互模式,你会发现它们都缺乏真实生活中人们交互的即时性的特点。因此可以把它们称之为准同步Web模式产品,当我们考虑Web 2.0规范的下一代平台时,需要克服这个缺点。基于互联网的聊天应用是最接近Web 2.0所需的即时交互特点的最简单例子,但是对于AJAX技术来说,即便是以一个可扩展、轻量级、基于浏览器的机制来实现这些基本的功能,也是其能力范围之外的事情。事实上,如果你仔细查看上面所说的上亿条搜索结果,你会发现只有一些开源技术能够解决通过标准浏览器机制异步推送内容给用户的难题。后面我们将粗略介绍一下这些技术,不过让我们先从最基本的东西开始介绍。
基于Web的推送技术基本原理
在将异步数据推送给浏览器方面,业内一直没有一个标准的机制或名称。在AJAX领域,该技术有不同的叫法,包括AJAX Push、Comet和Reverse Ajax,但是无论叫它什么,这些不同的实现方法具有一个共同的特点。在浏览器中唯一的轻量级通信机制就是HTTP协议,但是它仅仅能够帮助我们实现由浏览器发起的到服务器的通信的请求/响应的标准化。要想实现异步响应,有必要通过在服务器端保持一个开放的请求,当有更新的时候完成这个请求,实现对HTTP协议的翻转。通过下图,我们可以了解标准的AJAX请求过程和通过翻转机制来推送数据之间的不同。
为了支持异步推送,我们需要一直保持一个浏览器连接开放,来等待服务器端事件来触发浏览器中的外观变化。直觉告诉我们,这种实现方式存在问题,因为我们在浏览器和服务器端都面临着有关连接的问题。
浏览器连接限制
异步Web技术面临的主要困难之一典型的浏览器“双连接限制”问题。为降低服务器负载,HTTP规范建议,用户与每个服务器最多同时建立两个连接,但是异步技术已经占用了其中一个连接作为通知通道使用。那么考虑一下这种情况,多个浏览器窗口打开了同一个Web页面,如果每一个窗口试图建立它自己的连接,我们迅速会消耗完可用连接。为了在这个限制下实现我们的目的,必须共享使用其中一个连接,但是出于安全原因,不同浏览器窗口的脚本环境是独立分开的,这使得共同使用一个共享连接实现起来非常困难。另一个可以使用的技术是利用共享的HTTP cookie,通过它来实现与指定服务器的所有HTTP交互。该cookie被所有窗口所共享,通过JavaScript操作,还可用于跨窗口通信。
但是,这个问题在portal页面环境下再次被放大,因为传统的portal引擎都不支持必需的异步通信方式。为了可以在多个portlet中使用推送技术,不仅仅需要共享浏览器连接,还需要一个专门的共享服务器连接来聚合异步响应。如果portlet是通过多个WARs进行部署的,情况可能会更复杂一些,共享机制必须在多个Web应用之间协同工作,而且将需要一些IPC机制来实现。
在我们评价不同的推送机制的时候,理解它们如何解决共享连接的问题是非常重要的,因为这个问题比较复杂,而且超出了一般应用程序开发者所能接触的范围。另外,浏览器厂商们可能会通过允许每窗口支持两个连接,或者提供具有HTTP pipelining控制支持的XmlHttpRequest,从而允许不同的窗口共享一个专门的连接,来彻底降低连接共享的复杂性。
应用服务器的可扩展性
当我们从应用服务器角度来审视开放连接的问题时,我们发现了这个问题的多面性。我们都知道,现在的应用服务器可以高效率的处理大量的连接,但是在现有Servlet模式下,每一个连接需要执行一个线程。如果这些连接由于偶发性的服务器发起更新而变为长期存活的话,服务器的可扩展性势必受到线程池耗尽的严重威胁。
虽然在servlet模型中关于异步通信的标准正在JSR315中被实现,但业界一直在通过完全不同的非标准化方法来解决这个问题。标准机制的缺失让人非常失望,因为任何可升级扩展的推送机制将需要与底层的服务器机制来紧密结合,需要实行专门的部署。好消息是,在开源应用服务器上已经出现许多不同的解决方案。
Tomcat 6通过一个附加的Servlet接口——org.apache.catalina.CometProcessor,提供了异步请求处理(ARP)功能。CometProcessor可以在当数据在连接上可读的时候,让Servlet接收事件,而不会通过阻塞读来消耗一个线程。与不同的service()方法相比,基于事件的机制让开发者可以很好的对异步I/O处理进行控制。Tomcat 6还提供了一个CometFilter接口,当comet事件被处理的时候,才激活被调用的过滤器链。
Glassfish V2/Grizzly通过类com.sun.enterprise.web.connector.grizzly.comet.CometEngine来提供ARP功能。应用程序可以通过一个CometHandler来注册接受事件,而且和Tomcat 6一样,当数据可用的时候处理读事件,反之则执行阻塞读操作。
Jetty 6则在现有servlet API中提供了支持ARP的扩展机制。它的org.mortbay.util.ajax.Continuation类提供了suspend/resume方法,来挂起请求操作,并在以后让其在另一个不同的线程上异步恢复。当在servlet的Service()成员内调用suspend()时,将产生一个异常,并被Jetty服务器所捕获,然后用于确认这个请求是否被恢复。恢复这个请求需要重新调用service()方法,然后它可以进行写响应。延长机制的一个复杂之处是,service()方法必须被明确执行来支持触发延伸。更好的做法是可以应用过滤机制的标准servlet,不过,过滤器同样也必须处理触发延伸的问题。
ICEfaces异步HTTP服务器AHS算不上是一个应用服务器,但是它可以与任何应用服务器一起为ICEfaces应用提供ARP支持。和上面所提到机制不同之处是,没有与AHS相关的编程API,它的功能是专门针对ICEfaces的。需要对AHS进行配置来处理异步通讯通道,使用一个边界线程池来对进行中的请求匹配更新。它可以被部署在群环境中,包含一个servlet模式,可以被用来在portal环境下处理AJAX推送。
开发模式
在简单理解了推送机制和它相应的复杂性之后,很多开发者选择了对开发真正的推送风格应用敬而远之。现在将我们的目光转向那些可以帮助我们实现推送式应用程序开发的开源AJAX技术。
Dojo/Cometd/Bayeux提供了一个以客户端为中心的编程模式和一个通用的可扩展到服务器的发布/订阅机制。我们可以为专门的消息类定义一个专门的通道,这些通道的客户端可存在于浏览器或服务器中。使用JavaScript应用逻辑来处理从服务器推送的消息,以及相应的更新用户界面。从服务器角度来看,需要定义一个推送通道,然后服务器端应用逻辑通过该通道来发布事件。Cometd是一个非常灵活的机制,可同时支持在服务器端的Java和Python实现。Cometd已经被集成到Tomcat 6、Grizzly和Jetty 6中。通过使用一个支持在窗口之间进行大数据传输的共享cookie机制,浏览器连接共享成为可能。从本质上来说,Cometd方式带来了一个松散耦合的分布式系统,因此应用开发者需要解决一些相应的复杂问题,例如安全性和可维护性。
DWR/Reverse AJAX则在远程过程调用RPC基础上提供了一个以客户为中心的编程模式。简单来说,DWR通过JavaScript实现了从客户端调用服务器端的Java对象,而Reverse AJAX则是从服务器端的Java对象来调用JavaScript对象。对于一次推送交互,要求执行一个JavaScript来处理特定更新,服务器端的Java逻辑必须合理的调用这个JavaScript。DWR servlet则通过HTTP连接来处理RPC呼叫集合,但是连接共享问题在JavaScript执行中没有得到解决。DWR现已集成到Jetty 6中。
ICEfaces/AJAX推送在JSF基础上提供了一个以服务器为中心的编程模式。ICEfaces对JSF进行了扩展之后,可以支持一个透明AJAX桥,它可以在JSF生命周期的基础上实现更多针对浏览器的修改。一个简单的扩展API允许应用程序逻辑在一些异步事件基础上请求一个页面刷新,浏览器客户端的逻辑组合可以同时接收相同的更新。另外,它还提供了一个RenderHub功能来处理底层异步展现机制的同步和性能优化。ICEfaces可以被配置成从Tomcat 6、Grizzly和Jetty中使用ARP机制,当然还有ICEfaces AHS。ICEfaces桥通过一个共享cookie机制来支持连接共享,当在servlet模式下配置AHS后,可以支持portal环境中的AJAX推送。
结束语
在本篇文章中,我们把Web 2.0看作一个自然的即时社会化网络平台,而且也了解了使用轻量级Web技术来实现它所要求的推送功能的复杂性。尽管多数现有AJAX技术无法解决这一问题,不过一些开源技术已经出现,来帮助我们实现这个必需的功能。因此,有了这些开源技术,我们今天就能实现真正的Web 2.0。另外,随着标准化的进一步落实,下一代浏览器实现也将最终降低实现这一功能的复杂性。如果推送式的Web应用和Web 2.0已进入你的视线,那么投入到其中看看它能实现的强大应用吧。不过,需要提醒大家的是,你应该细心的检查你现有的非常好的开发模式和部署条件,进而设计一个方式,可以让你将精力集中在应用程序开发上,而不是底层的推送功能开发上。