epoll简介

您使用 epoll来获取这篇博文。对于您在 Internet 上执行的几乎所有操作,服务器都将运行 Linux,并且它将使用 epoll 及时且经济实惠地接收和回复您的请求。

  • epoll 使 Go 成为编写服务器软件的出色语言。这是 Go 的 Go's netpoll中的 epoll。
  • epoll 使 nginx 成为世界上最受欢迎的 Web 服务器(本博客运行 nginx)。这里是nginx对epoll的使用。
  • 在大多数编程语言中,这通常就是我们所说的"异步"的意思。例如,Rust 的两个主要异步框架中,async-std 使用polling,tokio 使用 mio

以上所有内容都适用于许多操作系统,并且支持除 epoll 以外的 API,这是 Linux 特有的。互联网主要由 Linux 组成,因此 epoll 是重要的 API。

问题

运行网络服务的核心问题(epoll 解决的问题)是您的网络非常快,而您的客户端网络非常慢。处理请求的服务器通常如下所示:

css 复制代码
read the user's request (e.g. a browser HTTP GET)
do what they asked (e.g. load some information from the database)
write a response (e.g. HTML that the browser will display)

在上面的"read"和"write"部分期间,服务器处于空闲状态,等待数据或该数据的确认在网络上移动。

在epoll之前

在 epoll 之前,解决这个问题的标准方法是运行一个进程池,每个进程处理不同的用户请求,通常使用 Apache mod_prefork。当一个进程等待用户确认数据包时,另一个进程可以使用 CPU。一种新兴的替代方案是使用比进程池更轻的线程池,并且可以处理数百个并发用户。多线程是有风险的,因为许多库不是线程安全的。 Steven 2004 年的参考文献《UNIX 网络编程》有一章讨论了preforked与prethreaded设计,因为这些是当时的选择。

然后大家都来了,甚至数百个并发用户都不够。一篇有影响力的文章The C10K problem 于 1999 年开始了这一讨论。Web 请求超时并不罕见。人们会镜像热门网站以传播流量。

解决方案

2000 年,Jonathan Lemon 通过设计和构建 kqueue/kevent 为 FreeBSD 4.3 解决了这个问题,使 BSD 成为高性能网络的早期选择。

2001 年 7 月,Davide Libenzi 独立解决了 Linux 的问题,推出了 epoll 的第一个草案,并于 2002 年 10 月将其合并到 Linux 内核 2.5.44(开发版本)中,并于 2003 年 12 月随着 epoll 的发布而广泛可用。稳定内核 2.6。

Jim Blandy 在comparison of threads vs epoll-based async here进行了精彩的比较。

epoll是怎么运行的

epoll 允许单个线程或进程 注册对一长串网络套接字的兴趣(它支持网络套接字以外的东西,例如管道和终端,但很少有数千个)。然后 epoll_wait 调用将被阻塞,直到其中一个调用准备好读取或写入为止。使用 epoll 的单个线程可以处理数万个并发(大部分是空闲)请求。

epoll 的缺点是它改变了应用程序的架构 。您现在拥有一个更类似于游戏引擎的主循环,而不是使用简单的 {read request, handle, write response} 处理每个连接。代码变为:

vbnet 复制代码
loop
 epoll_wait on all the connections
 for each of the ready connections:
   continue from where you left off

您可能会在一个就绪套接字上读取请求,并在另一个套接字上写入响应。你必须记住你的状态 ,只执行套接字在不阻塞的情况下可以接受的 I/O,然后再次 epoll_wait。 Go 以及 C#、Javascript 和 Rust 等语言中的"async/await"模型之所以流行,很大一部分原因在于它们隐藏了事件循环,允许您编写直线代码,就像仍在执行线程一样-每个连接

结论

如果没有 epoll,当今互联网的经济性将会大不相同(每台机器的请求更少,因此机器更多,花费更多的钱),或者我们将在 BSD 上运行我们的服务器。如果没有 BSD 的 kqueue(它比 epoll 早两年),我们真的会遇到麻烦,因为唯一的替代方案是专有的(Solaris 8 中的 /dev/poll 和 Windows NT 3.5 中的 I/O Completion Ports)。

epoll 自最初发布以来已经得到了改进,特别是 EPOLLONESHOT 和 EPOLLEXCLUSIVE 标志,但核心 API 保持不变。 epoll 解决了 Linux 上的 C10K 问题,Linux 为互联网提供了动力,使我们能够构建快速且廉价的互联网服务。


附录:

  • Linux 在 epoll 之前有 pollselect 。它们被设计为处理少量文件描述符,并且在该数量上可扩展 O(n)。 epoll 的规模为 O(1)。 Kerrisk 的性能数据显示,poll 和 select 在超过数百个文件描述符时变得不可用,而 epoll 仍然快速达到数万个。

  • Linux 在 epoll 之前也有信号驱动的 I/O。引用UNIX网络编程:

不幸的是,信号驱动的 I/O 对于 TCP 套接字来说几乎毫无用处 作者能够找到的带套接字的信号驱动 I/O 的唯一实际用途是使用 UDP 的 NTP 服务器。


epoll: The API that powers the modern internet

相关推荐
安冬的码畜日常1 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele2 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE3 小时前
VSCode终端:提升命令行使用体验
前端
xgq3 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
用户3157476081353 小时前
前端之路-了解原型和原型链
前端
永远不打烊3 小时前
librtmp 原生API做直播推流
前端