zoukankan      html  css  js  c++  java
  • select与epoll、apache与nginx实现原理对比

    转自:http://www.tuicool.com/articles/AzmiY3

    关于select与epoll

    两种IO模型,都属于多路IO就绪通知,提供了对大量文件描述符就绪检查的高性能方案,只不过实现方式有所不同:

    select:

    一个select()系统调用来监视包含多个文件描述符的数组,当select返回,该数组中就绪的文件描述符便会被内核修改标志位。

    select的 跨平台 做的很好,几乎每个平台都支持。

    select缺点有以下三点:

    1. 单个进程能够 监视的文件描述符的数量存在最大限制
    2. select()所维护的 存储大量文件描述符的数据结构 ,随着文件描述符数量的增长,其在用户态和内核的地址空间的复制所引发的开销也会线性增长
    3. 由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()还是会对 所有的socket进行一次线性扫描 ,会造成一定的开销

    poll:

    poll是unix沿用select自己重新实现了一遍,唯一解决的问题是poll 没有最大文件描述符数量的限制

    epoll:

    epoll带来了两个优势,大幅度提升了性能:

    1. 基于事件的就绪通知方式 ,select/poll方式,进程只有在调用一定的方法后,内核才会对所有监视的文件描述符进行扫描,而epoll事件通过epoll_ctl()注册一个文件描述符,一旦某个文件描述符就绪时,内核会采用类似call back的回调机制,迅速激活这个文件描述符,epoll_wait()便会得到通知
    2. 调用一次epoll_wait()获得就绪文件描述符时,返回的并不是实际的描述符,而是一个代表就绪描述符数量的值,拿到这些值去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里使用内存映射(mmap)技术, 避免了复制大量文件描述符带来的开销

    当然epoll也有一定的局限性, epoll只有Linux2.6才有实现 ,而其他平台都没有,这和apache这种优秀的跨平台服务器,显然是有些背道而驰了。

     

    Apache与Nginx:

    Apache与Nginx的性能谁更高效,取决于其服务器的并发策略以及其面对的场景:

    并发策略:

    我们目前使用的 Apache是基于一个线程处理一个请求的非阻塞IO并发策略 。这种方式允许一个进程中通过多个线程来处理多个连接,其中每个线程处理一个连接。Apache使用其worker模块实现这种方式,目的是减少perfork模式中太多进程的开销,使得apache可以支持更多的并发连接。

    至于,非阻塞IO的实现,是通过一个子进程负责accept(),一旦接收到连接后,便将任务分配给适当worker的线程。

    由于apache的线程使用的是内核进程调度器管理的轻量级进程,因此与perfork模式比较,进程上下文切换的开销依然存在,性能提升不是很明显。

     Nginx使用的是一个进程处理多个连接、非阻塞IO模式 ,这种模式最特别的是设计了独立的listener进程,专门负责接收新的连接,再分配给各个worker,当然为了减少任务调度的开销,一般都是由worker进程来进行接收。

    而IO模型层面,Nginx选择epoll,此方式高效主要在于其基于事件的就绪通知机制,在高连接数的场景下,epoll通知方式更具优势。另外,epoll方式只关注活跃连接,而不像select方式需要扫描所有的文件描述符,这样在大量连接的场景下,epoll方式优势会更加明显。

    面对的场景:

    我们反观一下网站目前的状况和场景:

     

     
     

     

    上图可以看到,rt监控当中,由于我们是动态网站,网站的大部分内容都需要动态获取、计算、输出,因此响应时间普遍位于100毫秒以上,响应时间较长,服务器必将创建更多的连接处理这些请求,而tcp监控当中,可以看到由于TCP协议特有的特性,服务端主动关闭一个连接,连接会进入等待超时的状态,且此状态会持续2MSL(即两倍的数据包最大生存时间,这个时 间长短跟操作系统有关,一般会在1-4分钟),因此服务器端会保留一定量time_wait连接,管理大量的连接也会对服务器造成一定的成本,而epoll在多连接并发处理以及管理这两方面,都较于select具有很大的优势。这也正是高并发、高连接的互联网网站大量使用Nginx服务器的原因所在。

  • 相关阅读:
    go-zero尝试运行输出hello-world
    grpc客户端 服务端测试
    protobuf序列化
    protobuff3语法详情
    【转】普通程序员如何转向AI方向
    深度学习微软 azure-云服务器组 centos特殊内核版本 gpu NVIDIA 驱动及CUDA 11.0安装
    分享一个主要用于nas场景的集成了迅雷,百度网盘等软件的docker ubuntu vnc镜像-适用于x86环境
    以spark sql 维护spark streaming offset
    打通es及lucene应用,lucene应用es Query,应用完整的es query
    打通es及lucene应用,lucene应用es Query,结合非queryString查询(二)
  • 原文地址:https://www.cnblogs.com/xiatian1071/p/3560917.html
Copyright © 2011-2022 走看看