模型和模样的区别

模型和模样的区别,第1张

Apache select和Nginx epoll模型区别 部分内容摘自跟老男孩学Linux运维:Web集群实战(运维人员必备书籍)

  http://oldboy.blog.51cto.com/2561410/1752270


1.select epoll模型 1.1.IO模型概述

     通常来,网IO可以抽象成用户态和内核态之间的数据交换。一次网络数据读取 *** 作(read),可以拆分成两个步骤:1)网卡驱动等待数据准备好(内核态)2)将数据从内核空间拷贝到进程空间(用户态)。根据这两个步骤处理方式不一样,我们通常把网络IO划分成阻塞IO和非阻塞IO。

      ·阻塞IO。用户调用网IO相关的系统调(例如read),如果此内核网卡没有取到网数据,那么本次系统调用将会一直阻塞,直到对端系统发送的数据到达为止。如果对端一直没有发送数据,则本次调用将永远不会返回。

      · 非阻塞IO。当用户调用网IO相关的系统调(例如read),如果此内核网络还没有收到网数据,那么本次系统调用将会立即返回,并返回一个EAGAIN错误码

在没有IO多路复用技之前,由于没有一种好的方式来探IO是否可可写。因此,了增加系的并发连接量,一般是借助多线程或多程的方式来增加系的并发连接数。但是种方式有个问题就是系的并发连接数受限于 *** 作系的最大线程或程数,并且随着 *** 作系线程或程数增加,将会引大量的上下文切致系的性能急下降。了解决问题, *** 作系引入了IO多路接技IO multiplexing)。

1.2.  IO多路技术

    IO多路转接技术其实就是使用select、epoll等 *** 作系统提供的系统调用来检测IO事件的各种机制。通过select、epoll等机制,我们可以很轻松的同时管理大量的网络IO连接,并且获取到处于活跃状态的连接。当其中一个或多个发生网络IO事件时,select、epoll等系统调用就会返回相应的连接,我们就可以对这些连接进行读取或写入 *** 作,从而完成网络数据交互。

1.3.select 工作原理

       select函数原型:

        int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

          select各个参数明:

               ·  nfds

这个参数的值一般设置为读集合(readfds)、写集合(writefds)以及exceptfds(异常集合)中最大的描述符(fd)+1,当然也可以设置为FD_SETSIZE。FD_SETSIZE是 *** 作系统定义的一个宏,一般是1024。也就是说读写以及异常集合大小的最大值是1024,所以使用select最多只能管理1024个连接。如果大于1024个连接,select将会产生不确定行为。

· readfds

指向可读描述符集的指针,如果我们关心连接的可读事件,需要把连接的描述符设置到读集合中。

·writefds

指向可写描述符集的指,如果我关心接的可写事件,需要把接的描述符置到可写集合中。

· exceptfds

指向异常描述符集的指,如果我关心接的是否生异常,需要把接的描述符置到异常描述符集合中。

·timeout

select愿意等待的时间

                      struct timeval {

                                           longtv_sec;      //秒数

                                           longtv_usec;    //微秒数

                                   }

                一般来,分三种情况:

·timeout空,select将会永等待。直到有接可读、可写或者被信号中断时返回。

·timeout->tv_sec = 0 且 timeout->tv_usec = 0,完全不等待。检测所有指定的描述符后立即返回。这是得到多个描述符的状态而不阻塞select函数的轮询方法。

·timeout->tv_sec != 且 timeout->tv_usec != 0,等待指定的秒数和微秒数。当指定的描述符之一已经准备好,或者超过了指定的时间值,则立即返回。如果超时了,还没有一个描述符准备好,则返回0。

     select的工作原理,select过轮询来检测各个集合中的描述符fd)的状,如果描述符的状态发生改变,则会在该集合中设置相应的标记位;如果指定描述符的状态没有发生改变,则将该描述符从对应集合中移除。因此,select的调用复杂度是线性的,即O(n)。举个例子,一个保姆照看一群孩子,如果把孩子是否需要尿尿比作网络IO事件,select的作用就好比这个保姆挨个询问每个孩子:你要尿尿吗?如果孩子回答是,保姆则把孩子拎出来放到另外一个地方。当所有孩子询问完之后,保姆领着这些要尿尿的孩子去上厕所(处理网络IO事件)。

    select的限制,前面提到FD_SETSIZE宏,这个宏是 *** 作系统定义的。在linux下面通常是1024,也就是说select最多只能管理1024个描述符。如果大于1024的个描述,select将会产生不可预知的行为。那在没有poll或epoll的情况下,怎样使用select来处理连接数大于1024的情况呢?答案是使用多线程技术,每个线程单独使用一个select进行检测。这样的话,你的系统能够处理的并发连接数等于线程数*1024。早期的apache就是这种技术来支撑海量连接的。

1.4.epoll工作原理

  epoll函数原型:

        int epoll_create(int size);

        intepoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

 

                int epoll_wait(intepfd,  struct epoll_event *events, intmaxevents,  int timeout);

         epoll上述三个函数,既可以完成成千上万的并发连接管理。epoll使用方式,1)通epoll_create建立epoll句柄。2)将描述符所感趣的事件通epoll_ctl添加到epoll句柄中。3epoll_wait返回所有可写的描述符。

  epollLinux内核为处理大批量文件描述符而作了改epoll,是Linux下多路复用IO接口select/poll的增版本,它能著提高程序在大量发连中只有少量活的情况下的系CPU利用率。另一点原因就是取事件的候,它无整个被听的描述符集,只要遍那些被内核IO事件异步醒而加入Ready列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触Level Triggered)外,提供了边缘Edge Triggered),就使得用程序有可能IO,减少epoll_wait/epoll_pwait用,提高用程序效率。

      还是以保姆照看一群孩子为例,在epoll机制下,保姆不再需要挨个的询问每个孩子是否需要尿尿。取而代之的是,每个孩子如果自己需要尿尿的时候,自己主动的站到事先约定好的地方,而保姆的职责就是查看事先约定好的地方是否有孩子。如果有小孩,则领着孩子去上厕所(网络事件处理)。因此,epoll的这种机制,能够高效的处理成千上万的并发连接,而且性能不会随着连接数增加而下降。

1.5.selectepoll

上所述,selectepoll比如下表所示


select

epoll

性能

随着接数增加,急下降。理成千上万并发连接数,性能很差。

随着接数增加,性能基本上没有下降。理成千上万并发连,性能很好。

接数

连接数有限制,处理的最大连接数不超过1024。如果要处理超过1024个连接数,则需要修改FD_SETSIZE宏,并重新编译 。

接数无限制。

内在处理机制

线性轮询

回调callback

开发复杂性

 

老男孩教育最新课程selectepoll简单区别比喻

select的调用复杂度是线性的,即O(n)。举个例子,一个保姆照看一群孩子,如果把孩子是否需要尿尿比作网络IO事件,select的作用就好比这个保姆挨个询问每个孩子:你要尿尿吗?如果孩子回答是,保姆则把孩子拎出来放到另外一个地方。当所有孩子询问完之后,保姆领着这些要尿尿的孩子去上厕所(处理网络IO事件)。

还是以保姆照看一群孩子为例,在epoll机制下,保姆不再需要挨个的询问每个孩子是否需要尿尿。取而代之的是,每个孩子如果自己需要尿尿的时候,自己主动的站到事先约定好的地方,而保姆的职责就是查看事先约定好的地方是否有孩子。如果有小孩,则领着孩子去上厕所(网络事件处理)。因此,epoll的这种机制,能够高效的处理成千上万的并发连接,而且性能不会随着连接数增加而下降。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/778381.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-03
下一篇 2022-05-03

发表评论

登录后才能评论

评论列表(0条)

保存