应用服务器的可扩展性
当我们从应用服务器角度来审视开放连接的问题时,我们发现了这个问题的多面性。我们都知道,现在的应用服务器可以高效率的处理大量的连接,但是在现有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推送。