Scalable IO in Java解读

大神Doug Lea的Scalable IO in Java,篇幅虽短,但大家之作,高屋建瓴,有如内功心法。每当我在对NIO的一些东西不甚了解的时候,翻出它来仔细研读,总能找到我想要的答案。

当今基于TCPIP的网络应用服务(分布式?),大多数都有着类似的结构(流程):

  • 从底层IO读取网络字节请求
  • 把读取的网络字节请求进行解码,封装成为业务请求对象
  • 对解码封装后的业务请求对象进行业务处理
  • 将业务逻辑处理完后的响应进行编码为底层IO可传输的字节响应
  • 利用底层IO发送已编码的字节响应


整体流程如上图所示,但具体每一步所用到的技术手段有可能都不一样,比如解码协议是自定义的还是业界流行的?(比如是用XML还是JSON,或者Protobuf?),如果是XML解析,那又是用什么包来进行解析?Web页面如何生成?而处理过程因具体业务而不同。 经典(传统)的网络服务设计如上图所示,对每个请求都会产生一个新的线程来进行处理,这种设计的缺点是,线程的创建本身是系统资源的一个开销,如果并发请求达到一定数量,响应将会变慢,甚至有可能因为系统资源不足而造成系统崩溃。 上图是一个经典的Blocking IO ServerSocket代码示例,它实现的其实就是图3所描述的。 基于传统的网络服务设计(每个请求一个线程处理)的缺点,Doug Lea描述了高扩展性系统的目标:
* 在请求激增的负载下,至少能够优雅退化(这句话其实比较难理解,我是看了网上的一篇文章里面的解释才明白的),也就是说,高并发下,响应可以相对慢一些,但不要无响应甚至崩溃。
* 随着系统资源(CPU,内存,硬盘,带宽)的增加能持续改善
同时能够满足可用性与性能目标:

低延迟(即高响应)
能够满足最大峰值的处理请求,即在访问量突增的情况下,不宕机。
可调控(调优)的服务

最后还总结出一个对设计高扩展性系统的一条圭臬:
分而治之通常是构建高扩展性系统最佳解决方案

分而治之

*将处理分为多个小的任务,每个任务的执行都是非阻塞的。
*每个任务在它能被执行的时候立即执行(这一句我翻译得比较拗口,关键是enabled这个词比较难翻译出它的神髓),一般来说一个IO事件就会触发任务执行(回调)。
*Java的NIO包已经实现了上述的NIO处理框架

非阻塞(Non-Blocking)读写
分发(Dispatch)执行与IO事件相关的任务

事件驱动设计

通常比传统的设计更加有效率,它使用的资源更少,不用针对每个请求(用户)启用一条线程,减少了上下文切换,减少阻塞,不过任务分发可能会慢,必须手动将事件和处理动作绑定。
事件驱动编程会相对难一些,它要求将处理过程分割成简单的非阻塞的任务,类似于GUI(Swing)的事件驱动,而实际上它也无法避免所有的阻塞,比如GC,分页错误等等,此外它还需要跟踪记录服务的逻辑状态。

Reactor模式

Reactor响应IO事件,将IO事件分发给相应的Handler,类似于AWT的Thread。

Handler执行非阻塞的操作,类似于AWT的ActionListener。

通过将Handler与IO事件绑定来实现,类似于AWT的addActionListener。

基本Reactor设计

上图是单线程的版本,由一条线程来接收所有请求,然后再将请求分发给相应的Handler来处理。

TO BE CONTINUE.....

comments powered by Disqus