Nginx 事件循环:一个进程为什么能同时招呼几千个连接

如果你打开 Nginx 的源码,会发现它不像很多初学者想象的那样:来一个连接就开一个线程,来一千个连接就开一千个线程。那种写法很直观,但很快就会把机器拖死,因为线程本身也要占内存,还要不停切换。

Nginx 更狠一点。它把连接先登记到操作系统那里,然后主循环反复问一句:现在谁真的有事?在 Linux 上,这通常靠 epoll 完成。没有数据的连接就安静躺着,不占用 CPU;真正有数据可读、可写、超时的连接,才会被拿出来处理。

这就是事件驱动。程序关心的不是“我有多少连接”,而是“这一刻有哪些连接发生了事件”。所以 Nginx 的 worker 进程看起来像一个很忙但不慌的人:它不陪每个连接干等,只处理已经准备好的那几个。

源码里最关键的味道,是它把连接、事件、定时器拆成了清楚的数据结构。连接对象记录“是谁”,读写事件记录“发生了什么”,定时器记录“什么时候算超时”。主循环只做一件事:取事件,分发事件,再回去等下一批。复杂性没有消失,但被放在了正确的位置。



容易混淆的是,“单进程处理很多连接”不等于“一个 CPU 同时执行很多代码”。它真正做到的是不把时间浪费在等待上。网络服务的敌人通常不是计算太慢,而是大量连接都在空等。Nginx 的好品味就在这里:别给每个等待都配一个线程,把等待交给操作系统,把程序留给真正发生的事。

#CS