您的位置:首页 > 运维架构 > Linux

浅谈Linux的I/O模型

2016-07-01 11:20 471 查看
       今天看了篇文章,在聊Linux下的I/O模型,也让我复习一下操作系统方面的知识,让我以后写网络I/O模型的时候也能够有所借鉴。

具体的介绍就不说了,人家写的挺好。点击这里,可以看到:http://my.oschina.net/xianggao/blog/662803。

       我主要想说一下我的理解,对于I/O模型,基本上所有的web应用都少不了。

那么我想说一下对于几个服务器的网络I/O模型是什么样子的。

       对于年代最久远的Apache来说,当时最早的时候linux中还没有epoll模型,Apache采用的是多线程/多进程select模型,每收到一个socket连接(在服务器端叫做请求),就会创建一个进程(或者使用线程池)来处理,每个请求都在一个进程内完成处理。这样的话,当并发量增大的时候,就会出现频繁的CPU切换,非常的耗时和浪费资源,所以高并发情况下会出现性能的下降。

      对于当前最火的ngnix服务器,在高并发情况下,性能会比Apache高很多,为什么那? 这就得益于epoll模型,epoll模型和select的对比就是:假如你去书店买书,你和店员挨个书柜的找,还是你先告诉店员书名,你在那里等着,当找到了告诉你一声,这就是select和epoll的区别。另外,ngnix高性能的原因还有一个,就是模块化、序列化的组织形式,当一个请求出现,把这个请求解析成非常多的模块,accept()、recv()、I/O、proc()等等,只有需要CPU处理的核心模块能占用CPU资源。

拿一个HTTP请求来说,首先在事件收集分发模块注册感兴趣的监听事件,注册好之后不阻塞直接返回,接下来就不需要再管了,等待有连接来了内核会通知你(epoll的轮询会告诉进程),cpu就可以处理其他事情去了。一旦有请求来,那么对整个请求分配相应的上下文(其实已经预先分配好),这时候再注册新的感兴趣的事件(read函数),同样客户端数据来了内核会自动通知进程可以去读数据了,读了数据之后就是解析,解析完后去磁盘找资源(I/O),一旦I/O完成会通知进程,进程开始给客户端发回数据send(),这时候也不是阻塞的,调用后就等内核发回通知发送的结果就行。整个下来把一个请求分成了很多个阶段,每个阶段都到很多模块去注册,然后处理,都是异步非阻塞。

       对了,虽然说Apache高并发的时候会出现性能下降,但是随着这几年的优化,人家的性能也提升了不少,关于Apache和Ngnix的比较,并没有褒贬好坏之分,只是适用的场景不同,前者更偏CPU密集型应用,后者更喜欢浅谈Linux的I/O密集型应用,仅此而已。

       再看看Redis的I/O模型,它使用多路复用I/O技术,单进程单线程的轮询方式,其实也就是同步阻塞的,它不需要进行频繁的CPU切换、轮询很多费时费力的系统开销,也没有许多创建线程的开销,其实I/O多路复用技术最大的优势就是节省资源,没有太多的系统开销。其实这也是Redis选用这种模型的原因。Redis作为内存数据库,而内存是非常宝贵的资源,如果大部分资源都用来I/O了,那怎么存数据啊?还有一个,为什么选择单线程?答案只有一个,简单啊!单线程不需要加锁,不需要担心线程切换时出现的问题等等,而这对于一个内存数据库来说非常重要。

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: