Nginx面试题:谈谈你对Nginx使用的epoll模型的理解?

我们都知道 Nginx 能做到高并发情况下的高效处理得意于它的 epoll模型,那如何理解它呢?

一些Linux基础知识

在这之前,我们需要了解一些 Linux 知识来作铺垫。

对于 Linux 而言:

一切都是文件

然而为了区分不同类型的事物,还有:

  • 普通文件
  • 目录文件
  • 链接文件
  • 设备文件

其中文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其值是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行 I/O 操作的系统调用都通过文件描述符

文件描述符
文件描述符

如果直接这么讲可能有些难以理解,对于 Linux 有一些使用的用户来说,会有类似如下的写法:

其中2>&1中的 2 就是表示的「标准错误」,1 就是「标准输出」,中间的 & 表示后面跟的数字是文件描述符而不是一个文件(不然所有的「标准错误」就都重定向到了一个名为 1 的文件中了)。

有了上面的知识,接下来就可以看看 select,poll 和 epoll 分别是什么了~

多路复用

select、poll 、epoll 这三者都是 I/O 多路复用机制,且简要介绍了多路复用的定义,那么如何更加直观地了解多路复用呢?看下图:

多路复用机制
多路复用机制

对于网页服务器 Nginx 来说,会有很多链接进来, epoll 会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。

一般来说以下场合需要使用 I/O 多路复用:

  • 当客户处理多个描述字时(一般是交互式输入和网络套接口)
  • 如果一个服务器既要处理 TCP,又要处理 UDP,一般要使用 I/O 复用
  • 如果一个 TCP 服务器既要处理监听套接口,又要处理已连接套接口

select

I/O 多路复用这个概念被提出来以后, select 是第一个实现,一个 select 的调用过程图如下所示:

select 的调用过程
select 的调用过程

其缺点为:

  • 每次调用 select,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大
  • 同时每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大
  • select 支持的文件描述符数量只有 1024,非常小

如果系统支持的文件描述符数量不够,在 Linux 上一般就会表现为:

此时就需要通过类似:ulimit -n 2048的方式来临时提升。

​poll

poll 和 select 原理一样,不过相比较 select 而言,poll 可以支持大于 1024 个文件描述符。

epoll

相比较 select 和 poll,epoll 的最大特点是:

  • epoll 现在是线程安全的,而 select 和 poll 不是。
  • epoll 内部使用了 mmap 共享了用户内核的部分空间,避免了数据的来回拷贝。
  • epoll 基于事件驱动,epoll_ctl 注册事件并注册 callback 回调函数,epoll_wait 只返回发生的事件避免了像 select 和 poll 对事件的整个轮寻操作。

什么是回调?

一个简单的例子

  • 驾照考试成绩快要出来的那段时间,小张每隔一段时间就去尝试查一下成绩,这个被称为轮询。
  • 小张知道不需要去盯着官网看成绩,等成绩出来后自然会有短信发到自己手机上:「叮,你的科目三没过」,这样就是回调。

另一个方便理解的对比如下:

  1. 对于 select / poll 模型来说,可以理解为让酒店代理订票,然后每隔几个小时就问一下买到没有,酒店在第二天订到了票,交钱给酒店拿到票,这样会需要额外的打电话时间和精力。
  2. 对于 epoll 来说则是委托酒店帮忙订票,但是并不反复去问,酒店在第二天买到了票,酒店打电话通知来领票,交钱给酒店拿到票。

epoll 和 Nginx

回到文章开头,最后我们可以简单总结一下为什么有了 epoll 的 Nginx 会有很高的运行效率,其原因在于它使用了异步,非阻塞,IO 多路复用。但是我们是不是就应该吹爆 Nginx,表示「Nginx 完爆 Apache」呢?

其实不是,相比较 Nginx 而言,Apache 作为一个非常老牌的网页服务器,其有丰富的模块组件支持,稳定性强,BUG 少,动态内容处理强,而 Nginx 的优势主要则在于占用资源少,负载均衡,高并发处理强,静态内容处理高效,所以只有掌握了自己的具体业务场景,才可以分情况地讨论这两个服务器之间的区别。

0

发表评论

您的电子邮箱地址不会被公开。