当前位置: 首页 > 科技观察

linux服务器网络开发模式分析

时间:2023-03-14 12:25:36 科技观察

前几天,公司同事把notebook系统改成了liunx系统,看起来不错,应该的应用基本都有了。比如文档处理软件,表格处理软件,eclipse开发环境等等,别说了,确实不错。又一次想装个liunx系统用,一直不敢。使用linux系统实在是太浪费精力了,很多东西都得自己设置。为什么Nginx的性能比Apache高很多?这主要是因为Nginx使用了最新的epoll(Linux2.6内核)和kqueue(FreeBSD)网络I/O模型,而Apache使用的是传统的select模型。曾经在博客上看到这样一个例子:假设你在大学读书,正在等一个朋友来拜访,而这个朋友只知道你在A栋,却不知道你住在哪里,于是你一个约会我想在A楼门口见面,如果你使用阻塞IO模型来处理这个问题,那么你只能在A楼门口等待朋友的到来。在此期间,您不能做其他事情。很难知道,这种方法的效率很低。现在时代变了,多路复用IO模型就是用来处理这个问题的。你叫你的朋友来A栋找楼管阿姨,让她告诉你怎么做。到那里怎么走。这里的楼管阿姨起到了多路IO的作用。解释一下select和epoll模型是如何工作的:select版的阿姨做了如下的事情:比如A同学的朋友来了,select版的阿姨傻了,带着她的朋友从房间查询到房间是A同学,你的朋友等着来。如果每次有朋友来楼,管理阿姨都要查询整栋楼的学生,那处理效率难免低下,过一会楼底就人山人海了.epoll版本中的阿姨更高级。她记下了A同学的信息,比如他的房间号,这样当A同学的朋友来的时候,她只需要告诉朋友A同学在哪个房间,就不用自己带了。大楼里挤满了找人的人。epoll阿姨不费吹灰之力就可以定位到A同学。epoll和select模型的区别一目了然。在Linux内核中,select使用的FD_SET是有限制的,即内核中有一个参数__FD_SETSIZE定义了每个FD_SET的句柄数量,内核源码/usr/include/linux/posix_types中的#undef__FD_SETSIZE#.hdefine__FD_SETSIZE1024如果要同时检测1025个句柄的可读可写状态,select无法实现。在内核中使用轮询的方式来实现select,即每次检测都会遍历FD_SET中的所有句柄。很明显,select函数的执行时间和FD检测句柄的数量越多,就越耗时。epoll是多路复用IO(I/OMultiplexing)中的一种方法,只用于linux2.6以上的内核。epoll模型支持的FD上限是最大可以打开的文件数。这个数字一般比2048大很多,比如在1GB内存的机器上大约是100000。具体可以参考:cat/proc/sys/fs/file-max,这个数字跟系统内存有很大关系。传统select/poll的另一个致命弱点是当你有一个很大的socket集合,但是由于网络延迟,任何时候只有一部分socket是“活跃的”,但是每次调用select/poll都会线性扫描所有的A的收集,导致效率线性下降。但是epoll不存在这个问题,它只对“活跃”的套接字进行操作---这是因为在内核实现中,epoll是根据每个fd上的回调函数来实现的。那么,只有“活跃”的套接字才会主动调用回调函数,其他空闲状态的套接字则不会。此时epoll实现了一个“伪”AIO,因为此时的驱动力是os内核。在某些基准测试中,如果所有套接字基本上都是活动的——例如高速局域网环境,epoll并不比select/poll更有效。相反,过多使用epoll_ctl,效率会略有下降。.但是一旦使用空闲连接来模拟WAN环境,epoll的效率就远高于select/poll。epoll有两种工作模式:EdgeTriggered(ET),LevelTriggered(LT)LT(leveltriggered)是默认的工作模式,同时支持block和no-blocksocket。在这种做法中,内核会告诉你一个文件描述符是否就绪,然后就可以对这个就绪的fd进行IO操作。如果你什么都不做,内核会继续通知你,所以在这种模式下编程错误的可能性较小。传统的select/poll就是这种模式的代表。ET(edge-triggered)是一种高速工作模式,只支持no-blocksocket。在这种模式下,内核会通过epoll告诉您描述符何时从未就绪变为就绪。然后它假定您知道文件描述符已就绪,并且不会再为该文件描述符发送任何就绪通知,直到您执行导致该文件描述符不再就绪的操作(例如,您在以下情况下导致了EWOULDBLOCK错误)发送、接收或接收请求,或发送和接收少于一定数量的数据)。