Servlet API和NIO: 最终组合在一起 - 编程入门网
Servlet API和NIO: 最终组合在一起时间:2011-01-26 IBM Taylor CowanNIO 是带有 JDK 1.4 的 Java 平台的最有名(如果不是最出色的)的添加部分之一。下面的许多文章阐述了 NIO 的基本知识及如何利用非阻塞通道的好处。但它们所遗漏的一件事正是,没有充分地展示 NIO 如何可以提高 J2EE Web 层的可伸缩性。对于企业开发人员来说,这些信息特别密切相关,因为实现 NIO 不像把少数几个 import 语句改变成一个新的 I/O 包那样简单。首先,Servlet API 采用阻塞 I/O 语义,因此默认情况下,它不能利用非阻塞 I/O。其次,不像 JDK 1.0 中那样,线程不再是“资源独占”(resource hog),因此使用较少的线程不一定表明服务器可以处理更多的客户机。 在本文中,为了创建基于 Servlet 并实现了 NIO 的 Web 服务器,您将学习如何解决 Servlet API 与非阻塞 I/O 的不配合问题。我们将会看到在多元的 Web 服务器环境中,这个服务器是如何针对标准 I/O 服务器(Tomcat 5.0)进行伸缩的。为符合企业中生存期的事实,我们将重点放在当保持 socket 连接的客户机数量以指数级增长时,NIO 与标准 I/O 相比较的情况如何。 注意,本文针对某些 Java 开发人员,他们已经熟悉了 Java 平台上 I/O 编程的基础知识。 线程不再昂贵 大家都知道,线程是比较昂贵的。在 Java 平台的早期(JDK 1.0),线程的开销是一个很大负担,因此强制开发人员自定义生成解决方案。一个常见的解决方案是使用 VM 启动时创建的线程池,而不是按需创建每个新线程。尽管最近在 VM 层上提高了线程的性能,但标准 I/O 仍然要求分配惟一的线程来处理每个新打开的 socket。就短期而言,这工作得相当不错,但当线程的数量增加超过了 1K,标准 I/O 的不足就表现出来了。由于要在线程间进行上下文切换,因此 CPU 简直变成了超载。 由于 JDK 1.4 中引入了 NIO,企业开发人员最终有了“单线程”模型的一个内置解决方案:多元 I/O 使得固定数量的线程可以服务不断增长的用户数量。 多路复用(Multiplexing)指的是通过一个载波来同时发送多个信号或流。当使用手机时,日常的多路复用例子就发生了。无线频率是稀有的资源,因此无线频率提供商使用多路复用技术通过一个频率发送多个呼叫。在一个例子中,把呼叫分成一些段,然后给这些段很短的持续时间,并在接收端重新装配。这就叫做 时分多路复用(time-division multiplexing),即 TDM。 在 NIO 中,接收端相当于“选择器”(参阅 java.nio.channels.Selector )。不是处理呼叫,选择器是处理多个打开的 socket。就像在 TDM 中那样,选择器重新装配从多个客户机写入的数据段。这使得服务器可以用单个线程管理多个客户机。 Servlet API 和 NIO 对于 NIO,非阻塞读写是必要的,但它们并不是完全没有麻烦。除了不会阻塞之外,非阻塞读不能给呼叫方任何保证。客户机或服务器应用程序可能读取完整信息、部分消息或者根本读取不到消息。另外,非阻塞读可能读取到太多的消息,从而强制为下一个呼叫准备一个额外的缓冲区。最后,不像流那样,读取了零字节并不表明已经完全接收了消息。 这些因素使得没有轮询就不可能实现甚至是简单的 readline 方法。所有的 servlet 容器必须在它们的输入流上提供 readline 方法。因此,许多开发人员放弃了创建基于 Servlet 并实现了 NIO 的 Web 应用程序服务器。不过这里有一个解决方案,它组合了 Servlet API 和 NIO 的多元 I/O 的能力。 在下面的几节中,您将学习如何使用 java.io.PipedInput 和 PipedOutputStream 类来把生产者/消费者模型应用到消费者非阻塞 I/O。当读取非阻塞通道时,把它写到正由第二个线程消费的管道。注意,这种分解映射线程不同于大多数 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |