2.5 非阻塞I/O
Servlet 3.0允许异步请求处理,但只允许传统的I/O,这限制了应用程序的可扩展性。在典型应用中,在while循环中读取ServletInputStream:
如果传入的数据被阻塞或者数据流慢于服务器的读取,那么服务器线程就要等待数据。如果数据被写入到ServletOutputStream,同样也可能发生这样的等待。这限制了Web容器的可扩展性。
非阻塞I/O允许开发人员在有可读的数据时执行读操作或者在有写入的数据时执行写操作。这不仅增加了Web容器可伸缩性,也增加了可以同时处理的连接数量。非阻塞I/O只能用于异步请求处理的Servlet、Servlet过滤器和升级处理。
Servlet 3.1通过引入两个新的接口实现了非阻塞I/O:ReadListener和WriteListener。这些接口定义了回调方法,用于在有可读或者可写内容时被调用而不阻塞线程。
在本例中doGet()方法需要重写:
调用setXXXListener方法表明使用非阻塞I/O来代替传统的I/O。
ReadListener有以下三个回调方法。
- 每当非阻塞的可读数据有效时,onDataAvailable()回调方法被调用。
- 每当当前请求的数据读取完全时,onAllDataRead()回调方法被调用。
- 如果请求处理过程中发生错误,onError()回调方法被调用:
在这段代码中,onDataAvailable()回调方法被调用时数据可以不受阻塞地读取。ServletInputStream.isReady()方法用于检查数据可以被读取而不会阻塞,然后将数据读出。context.complete()方法在onAllDataRead()方法和onError()方法中被调用,以发出完成读取数据的信号。ServletInputStream.isFinished()方法可被用于检查非阻塞I/O读取的状态。
在ServletIntputStream中最多可以注册一个ReadListener。
WriteListener有以下两个回调方法。
- 每当非阻塞的可写数据有效时,onWritePossible()回调方法被调用。
- 如果请求处理过程中发生错误,onError()回调方法被调用。
在ServletOutputStream中最多可以注册一个WriteListener。ServletOutputStream. canWrite()方法是个新的方法,用于检查非阻塞数据是否可写。