现在的位置: 首页 > 综合 > 正文

通过 Tomcat Advanced I/O 获得高性能的 Ajax

2013年10月14日 ⁄ 综合 ⁄ 共 1677字 ⁄ 字号 评论关闭

使用非阻塞 I/O(Non-Blocking
I/O,NIO)可以极大地提高服务器的性能,因为它能充分地利用系统资源(线程)。在具有长轮询机制的 Asynchronous JavaScript + XML
(Ajax) 应用程序中,性能的提升非常显著。它还允许在受限制的条件下控制服务器系统资源的使用。本文解释了如何在处理 Ajax
和常规请求期间优化服务器的性能。

浏览器通过发送请求和显示来自服务器的响应与 Web 服务器进行通信。这似乎不是很重要,但从几个方面考虑,它都与本文相关。

富 Web 应用程序逐渐尝试提供一些与请求/响应模型不同的功能。Ajax
框架由底层的请求/响应模型抽象而来,它提供了一种运行在客户端的类似于图形用户界面(GUI)的模型。它像一个本地的重量级 Microsoft® Windows®
或 KDE 应用程序。这意味着您可以创建响应事件的代码,而不是响应请求的代码。细粒度的事件处理对富用户界面至关重要。

Ajax 资源中心

请访问 Ajax 资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki
和新闻。任何 Ajax 的新信息都能在这里找到。

但在底层,仍然有一个请求/响应模型。这不仅是一个有限制的编程模型 — 您可以使用 API 抽象处理它 —
在很多情况下,它还导致性能问题,并且损害服务器在繁忙时控制资源的能力。如果不按照它的设计初衷使用,该模型还会导致更严重的问题。

例如,浏览器客户端期望收到关于服务器更改的通知。这原先是不可能实现的;您只能每隔 5 分钟重新加载整个页面来模仿这个行为。因为引入了 JavaScript
代码和 Ajax,所以能够以更高效更美观的方式让页面实现更改通知。

页面可能会定期轮询服务器,从而创建大量的服务器请求,以及事件和通知之间的大幅度延迟。或者它可以在等待响应时,始终为服务器打开一个连接。第二个模型称为长轮询:本文将讨论这一轮询模型
— 因为它以最快的速度响应服务器上的事件 — 以及一些需要克服的困难。

在典型的 servlet
模型中,一个打开的连接意味着一个不执行任何操作的专用线程,它将一直等待,直到在响应事件时更新客户端。线程还是比较耗费资源的,一个服务器上可用的线程是有限制的。并发访问的增加会快速消耗服务器上的资源。单个的访问不只是意味着一些偶然的页面请求;它还意味着在访问期间有一个持续打开的连接(带有等待线程)。如果有几百个访问者在他们离开电脑时不关闭浏览器,就会带来一些问题。抽象并不能解决这样的性能问题。

解决方案

低级别的问题可以在低级别的 API 中找到解决方案。在坚持使用请求/响应模型的同时,您可以使用非阻塞
I/O(NIO)来保持连接的打开状态,而不需要浪费等待线程。为了方便在 servlet 中使用 NIO,您需要一个基于事件的
API,它会在打开的连接上适时发出恰当的读写行为。Tomcat 6 提供的 CometProcessor API 为这种基于事件的模型提供了便利。本文引入了
CometProcessor API。



回页首

NIO

首先,您需要对 NIO 有一定的了解。在典型的阻塞 I/O(blocking
I/O)中,您始终从一个线程中读取流,并且该线程会一直等待,直到整个流完成。对于需要在一次迭代中处理的、生命周期很短的流而言,这很有效:开始读取数据直到读完所有数据,然后关闭连接。这在一次的迭代中占有很少时间,所以只是短时间占用系统资源。大量并发的短生命周期连接不会造成问题。

为了获得通知,您需要一个机制,它只在需要读时才读,需要写时才写,但又保持连接打开,以迅速响应发生的事件。为了便利这个过程,要用到 NIO,它已是 1.4
版本以后的 Java™ 语言的一部分。

通过使用 NIO,就会在流完成之后才遍历它。在没有可用数据时才遍历流,这样就可以让流执行其他工作。当发生影响流的事件时 — 例如,进入更多的数据 —
您将继续遍历流。清单 1 展示了一个针对这种事件的示例处理程序;注意 is.available()

清单 1. 针对 InputStream 的单个读迭代

本文转自IBM Developerworks中国

      请点击此处查看全文

 

抱歉!评论已关闭.