IO系列文章之五:读《Scalable io in java》看Socket网络编程模型演变

最近利用业余时间在看Java NIO,期间读了线程大师Doug Lea那篇很经典的《Scalable IO in Java》。在此写一写看过之后,对于Socket编程模型演变的一些理解。

首先,对于网络编程,一般都有一个共同的流程:

(1)读请求.

(2)解码请求.

(3)计算处理逻辑.

(4)编码响应.

(5)发送响应.

一、经典阻塞IO模型:

(图片来源:《Scalable io in java》ppt,下同)

如图,对于每一个请求都分发给一个线程,每个线程中都独自处理上面的流程。

这种模型由于IO在阻塞时会一直等待,因此在用户负载增加时,性能下降的非常快。

server导致阻塞的原因:

1、serversocket的accept方法,阻塞等待client连接,直到client连接成功。

2、线程从socket inputstream读入数据,会进入阻塞状态,直到全部数据读完。

3、线程向socket outputstream写入数据,会阻塞直到全部数据写完。

client导致阻塞的原因:

1、client建立连接时会阻塞,直到连接成功。

2、线程从socket输入流读入数据,如果没有足够数据读完会进入阻塞状态,直到有数据或者读到输入流末尾。

3、线程从socket输出流写入数据,直到输出所有数据。

4、socket.setsolinger()设置socket的延迟时间,当socket关闭时,会进入阻塞状态,直到全部数据都发送完或者超时。

改进:采用基于事件驱动的设计,当有事件触发时,才会调用处理器进行数据处理。

二、非阻塞IO模型(单线程):

如图,这里用到了Reactor模式。

关于Reactor模式的一些概念:

Reactor:负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理。

Handler:负责处理非阻塞的行为,标识系统管理的资源;同时将handler与事件绑定。

Reactor为单个线程,需要处理accept连接,同时发送请求到处理器中。

由于只有单个线程,所以处理器中的业务需要能够快速处理完。

改进:使用多线程处理业务逻辑。

三、非阻塞IO模型(多线程):

如上图,将处理器的执行放入线程池,多线程进行业务处理。但Reactor仍为单个线程。

继续改进:对于多个CPU的机器,为充分利用系统资源,将Reactor拆分为两部分。

四、非阻塞IO模型(多Reactor):

如图,Reactor拆分为mainReactor和subReactor,subReactor线程个数可以跟CPU个数一样。

其中,mainReactor监听server socket,accept新连接。

subReactor负责读写网络数据,业务处理逻辑仍旧分发到线程池由worker线程完成。

附:《Scalable IO in Java》原文地址找不到了,百度文库中地址: 

http://wenku.baidu.com/view/ad5ef8b069dc5022aaea00a1.html 

猜你喜欢

转载自shensy.iteye.com/blog/1882413