Nginx如何扛住千万级请求不崩?

Nginx是大型架构核心,下面我详解Nginx千万级请求@mikechen

核心模型:Epoll 的“降维打击”

传统模型是“一个连接一个线程/进程”,每个连接都占一整条执行流。

还要上下文切换,连接一多,CPU 都耗在切换上,根本扛不住百万连接。

Nginx如何扛住千万级请求不崩?

Nginx 走的是“少量进程 + 事件驱动”的思路:

每个 worker 进程都是单线程事件循环,不做阻塞调用。

所有 socket 设为非阻塞,然后统一交给 epoll 管理。

epoll_wait 像“监听大厅”,哪个 fd 有事件(可读/可写/异常)。

就把它拉出来处理一小会,处理完继续轮询。

这就是“降维打击”:别再用“一个连接一个线程”的粗暴方式。

而是用一个进程/线程,用 epoll 把大量连接“排队”,谁有事件就服务谁,从资源模型上直接领先一代。

 

内存神技:零拷贝(Zero-Copy)

Nginx 利用的是操作系统提供的零拷贝能力(典型是 sendfile/ splice 等):

Nginx如何扛住千万级请求不崩?

Nginx 作为静态资源服务器时,可以直接使用 sendfile。

把内核文件缓存直接“映射”到 socket 缓冲区,省掉用户态来回拷贝。

对用户态来说,“我调用一次 sendfile,数据就在内核里从磁盘缓冲区流向网卡”,整个过程几乎不需要用户态参与。

收益:

CPU 从“大量 memcpy + 模式切换”中解放出来,更多算力留给业务逻辑、加密、压缩等。

在相同 CPU 资源下,可以支撑更多连接和更高吞吐,从而成为“百万连接”能力的重要组成部分。

 

多路复用的“指挥官”:进程模型

epoll 决定“怎么处理大量 fd”,而 Nginx 的进程模型决定“谁去处理这些事件”。

Nginx 的典型模型:

1 个 master 进程:负责读取配置、创建监听 socket、管理 worker(启动、重启、平滑重载)。

N 个 worker 进程:一般设置为 CPU 核心数,每个 worker 内部是单线程 + 事件循环 + epoll。

Nginx如何扛住千万级请求不崩?

这有几个直接好处:

利用多核:多个 worker 分布在不同 CPU 核上,充分吃满多核能力。

降低锁竞争:worker 内是单线程事件循环,基本不需要在业务层搞重锁。

稳定性:单个 worker 出问题(比如异常退出)时,master 可以拉起新的,不至于整个服务直接挂死。

 

突破系统极限:内核参数调优

Nginx如何扛住千万级请求不崩?

即便 Nginx 本身再强,如果 Linux 内核这道“门槛”太低,百万并发也只是纸上谈兵。

在大厂实战中,以下参数是必须要优化的:

常见措施包括:提升文件描述符上限(ulimit 与 fs.file-max)、调整 epoll/网络相关缓冲大小。

优化 TCP 参数(如 tcp_max_syn_backlog、tcp_tw_reuse、tcp_fin_timeout、somaxconn)。

开启端口重用(SO_REUSEPORT)和合理配置网卡队列(RSS、irq affinity)。

此外,监控内核队列、连接状态与资源使用,结合负载特性动态调整,是维持长期稳定性的关键。

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧