1

面试之Nginx的epoll的优势

 2 years ago
source link: https://zhangrr.github.io/posts/20220401-nginx_epoll/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

面试之Nginx的epoll的优势

2022-04-01 3 分钟阅读

面试时被问到:是否了解 Nginx,它使用的 epoll 模式和其他的相比有什么优势?

直接被问住,实际生产中配过不少的 Nginx,各种 rewrite、regex、正反向代理、php、fast-cgi、限流、证书、jwt、cors;epoll 只大概有印象是下面这行:

events {
    use epoll;
    worker_connections  1024;
}

实在是汗颜啊,所以得仔细研究一下这个 epoll。

首先扔概念

IO多路复用:

多路是指网络连接,复用指的是同一个线程。

IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件描述符;

一旦某个描述符就绪(一般是读就绪或者写就绪),就能够通知应用程序进行相应的读写操作;

没有文件描述符就绪时会阻塞应用程序,交出cpu。

那么IO多路复用的实现方法有三种: select、poll、epoll

select、poll、epoll本质上都是同步I/O,用户进程(这里就是Nginx)负责读写(从内核空间拷贝到用户空间),读写过程中,用户进程是阻塞的。

select:

  • 查询 fd_set 中,是否有就绪的 fd,可以设定一个超时时间,当有 fd (File descripter) 就绪或超时返回;

  • fd_set 是一个位集合,大小是在编译内核时的常量,默认大小为 1024

  • 连接数限制,fd_set 可表示的 fd 数量太小了;

  • 线性扫描:判断 fd 是否就绪,需要遍历一边 fd_set;

  • 数据复制:从内核空间拷贝到用户空间,复制连接就绪状态信息

poll:

  • 解决了连接数限制:

  • poll 中将 select 中的 fd_set 替换成了一个 pollfd 数组

  • 解决 fd 数量过小的问题

  • 数据复制:从内核空间拷贝到用户空间,复制连接就绪状态信息

epoll:event 事件驱动

  • 事件机制:避免线性扫描

  • 为每个 fd,注册一个监听事件

  • fd 变更为就绪时,将 fd 添加到就绪链表

  • fd 数量:无限制(OS 级别的限制,单个进程能打开多少个 fd)

区别在于:

epoll较灵活,如果有一百万个链接状态同时保持,但是在某个时刻,只有几百个链接是活跃的。epoll的处理是通过epoll_create()创建对象,epoll_ctl()收集所有的套接字添加到epoll对象,epoll_wait()收集所有发生事件也就是所谓的活跃的链接,并收集到一个List链表中,这样只需要遍历这些List链表里的数据,而不用遍历一百万个链接。 而后者select poll则是每次收集事件时,将这一百万个链接都传给操作系统,再由操作系统内核上判断某些链接产生了事件,造成了巨大的资源浪费(大批量的不同态内存复制)。

为什么epoll效率比较高

epoll 在epoll_create 时,就已经建立好了一个文件描述符对应 epoll 对象,同时,在内核 cache 里建立了一个红黑树,用于存储后续epoll_ctl传来的socket连接。再同时,又建立了一个list链表,用于存储准备就绪的事件。 等到 epoll_wait() 调用的时候,只需要观察list链表里有没有数据就可以,有数据就返回,没数据就sleep。等到timeout后,即使没数据,也返回了。所以 epoll_wait 会非常高效

三者的比较:

select poll epoll 数据结构 bitmap 数组 红黑树 最大连接数 1024 无上限 无上限 fd拷贝 每次调用select拷贝 每次调用poll拷贝 fd首次调用epoll_ctl拷贝,每次调用epoll_wait不拷贝 工作效率 轮询:O(n) 轮询:O(n) 回调:O(1)

Nginx 的并发处理能力

关于 Nginx 的并发处理能力:

  • 并发连接数,一般优化后,峰值能保持在 1~3w 左右。(内存和 CPU 核心数不同,会有进一步优化空间)
  • Nginx 的最大连接数:Worker 进程数量 x 单个 Worker 进程的最大连接数

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK