服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:
(1)同步阻塞IO(Blocking IO):即传统的IO模型。
(2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。
(3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。
(4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。
一、同步阻塞模式
1,阻塞模式,开发网络程序比较简单,容易实现,能够处理套接字数量较少的情况,但是当需要建立大量套接字线程的时候,阻塞模式将无从下手。
2,面对需要大量的socket连接的问题时,我们可能会使用多线程来解决,多线程的目的是让每一个连接都拥有独立的线程,这样一个连接的阻塞就不会影响到其他的连接。但是当服务器需要同时响应成百上千的连接请求时,线程的创建将会极大的占用系统资源,降低系统对外界的响应相率。
3,这时候线程池或者连接池的出现将降低CPU的负担,线程池旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池,尽量重用已有的连接、减少创建和关闭连接的频率。但是当请求量同时到达甚至超过池的最大量时,线程池也有些无能为力。
二、同步非阻塞模式
虽然IO操作会立即返回(因为数据没准备好)应用程序不断的调用读取数据操作,直到内核准备好数据,然后返回,这种方式因为不断的轮询、重复请求,消耗了大量CPU资源,所以实际应用很少。
三、异步阻塞模式
1,实际的应用模式:IO多路复用。最常用的高性能IO模式,IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数避免同步非阻塞IO模型中不断去轮询、重复请求的问题。
2,用户先将需要进行IO操作的socket添加到select中,然后等待select系统返回(遍历并找到可用socket)然后用户线程才正式发起请求。因为同一个线程中可以将多个socket放入select系统中去请求IO,这样就达到了同一个线程内同时处理多个IO请求的目的。
3,上面讨论的是单线程的情况,如果使用多线程+IO多路复用,就可以极大的提高性能,满足高并发系统的需求。
四、异步非阻塞模式
因为需要操作系统更强的支持(aio_read),在实际应用中并不常用。