Nginx如何支撑百万级高并发连接
原文:https://mp.weixin.qq.com/s/bi5kRMHiuKVNOvHpF1AJGg
“你是否曾经好奇过,为什么几乎所有大型互联网公司都在使用Nginx?为什么一个看似简单的软件能够支撑起百万级流量?当你的网站面临突发流量时,为什么总有人建议”上Nginx”?
今天,我来揭秘Nginx的核心工作原理,带你探索这款性能怪兽如何凭借三大核心设计创造奇迹。想象一下,仅占用2MB内存,如何轻松应对10万并发连接的狂风暴雨?
Nginx工作原理
了解Nginx如何处理请求对于优化配置和排查问题至关重要。下面我们来看看一个HTTP请求在Nginx中的完整处理流程。
请求接收与事件处理
- 客户端发起请求:客户端(如浏览器)向 Nginx 服务器发送 HTTP/HTTPS 请求
- 事件处理:Nginx 使用 epoll/kqueue/select 等机制检测到新的连接请求
- 分配工作进程:主进程根据负载均衡算法将请求分配给某个工作进程
HTTP请求处理阶段
Nginx 处理 HTTP 请求的过程分为11个阶段,每个阶段都有特定的功能:
- POST_READ:读取请求头后的第一个阶段,常用于 realip 模块修改客户端 IP
- SERVER_REWRITE:server块中的重写指令在此阶段执行
- FIND_CONFIG:根据请求URI查找匹配的 location 配置
- REWRITE:location块中的重写指令在此阶段执行
- POST_REWRITE:重写完成后的处理,如果URI改变,可能会回到 FIND_CONFIG阶段
- PREACCESS:访问控制前的准备工作,如限制连接数
- ACCESS:访问控制阶段,如基于IP或密码的访问控制
- POST_ACCESS:访问控制后的处理
- PRECONTENT:内容生成前的准备工作
- CONTENT:生成响应内容,如静态文件服务、代理转发等
- LOG:记录访问日志
分阶段处理的设计使得各个模块可以在适当的阶段注册处理函数,实现功能的解耦和扩展。
响应处理与返回
- 内容生成:根据配置生成响应内容(静态文件、代理内容等)
- 响应过滤:应用各种过滤器(如gzip压缩、字符集转换等)
- 发送响应:将处理后的内容发送给客户端
- 连接处理:根据配置决定是关闭连接还是保持连接(keepalive)
整个处理流程高效而灵活,使得Nginx能够快速响应各种类型的请求。
Nginx三大核心设计
Nginx采用多进程架构设计实现资源隔离与高稳定性,通过事件驱动设计实现了惊人的并发处理能力,依通过模块化架构设计构建了高度灵活的扩展体系。这三大技术的完美结合,让Nginx在高负载下依然能够保持稳如泰山的性能表现。
Master-Worker 多进程架构设计
Nginx采用 Master-Worker 架构:
- Master 进程:负责读取配置、管理 worker进程,不处理网络请求;
- Worker 进程:每个Worker 独立运行,进程间无需通信,基于事件驱动模型处理请求;
多进程架构的设计可以充分利用多核系统,同时保持稳定性和可管理性。主进程以 root 权限运行,而工作进程以较低权限运行,提高了安全性,worker 进程数量一般设置为 CPU 核心数,避免了进程切换的开销。
事件驱动设计
传统服务器采用“一个连接一个线程”的模型,而Nginx则采用事件驱动模型,核心目标是以单线程应对海量并发,从”点对点”通信升级到了”广播”模式,效率提升实现质的飞跃。
核心设计原理:
异步非阻塞I/O模型
- 采用事件驱动架构,完全避免进程/线程阻塞
- 通过 epoll/kqueue 等系统调用实现高效事件通知
- 单线程可处理数万并发连接
Nginx单Worker进程可处理10万连接,仅需约2.4MB内存
多阶段事件处理
- 将请求处理分解为多个非阻塞阶段
- 每个阶段对应特定的事件处理器
- 通过状态机管理请求处理流程
核心构成组件:
事件收集器(Event Collector)
- 多路复用机制:
- Linux系统使用 epoll(红黑树+就绪链表)
- FreeBSD系统使用kqueue
- Windows系统使用IOCP
事件分发器(Event Dispatcher)
- 基于事件类型调用对应处理器
- 支持定时器事件、I/O事件、信号事件等
事件处理器(Event Handlers)
- 连接处理器(ngx_http_connection_handler)
- 请求处理器(ngx_http_request_handler)
- 定时器处理器(ngx_event_timer_handler)
模块化设计
Nginx的另一大特色是其模块化设计,主要包括:
- 核心模块:提供基本功能,如配置解析、内存管理、事件驱动等
- 主功能模块:
- HTTP模块:实现HTTP协议处理和反向代理
- 事件模块:实现事件驱动机制和多路复用
- Stream模块:提供TCP/UDP代理功能
- Mail模块:提供邮件代理服务
- 扩展模块:
- 第三方模块:如LuaJIT、WAF(Web应用防火墙)、限流模块等
- 自定义模块:根据业务需求定制的功能扩展
模块化架构使得Nginx具有极高的扩展性和灵活性,用户可以根据需要选择加载不同的模块,避免了不必要的资源消耗。
Nginx通过事件驱动+非阻塞I/O减少资源消耗,多进程架构提升稳定性,模块化设计实现功能扩展,配合内存优化和负载均衡策略,最终达成百万级并发连接能力。
实战调优
参数调优
要支持百万并发连接,配置是关键。以下是经过实战验证的黄金配置:
# 主配置
worker_processes auto; # 自动检测CPU核心数
worker_rlimit_nofile 100000; # 每个worker进程的最大文件描述符数量
events {
worker_connections 65535; # 每个worker进程的最大连接数
multi_accept on; # 一次接受所有新连接
use epoll; # 使用epoll事件模型
}
http {
# 连接优化
keepalive_timeout 65;
keepalive_requests 10000;
# 缓冲区优化
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
# 文件优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 超时设置
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
}
这套配置在16核32G的服务器上可以稳定支持30万并发连接,CPU利用率维持在50%左右。
极限场景应对方案
突发流量:漏桶算法与令牌桶限流配置
面对突发流量,限流是保护系统的最后防线。Nginx提供了两种限流机制:
漏桶算法(适合恒定速率):
# 限制每个IP的请求速率为10r/s
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location / {
limit_req zone=mylimit burst=20 nodelay;
}
}
令牌桶算法(允许短时突发):
# 限制连接数
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location / {
limit_conn conn_limit 10; # 每个IP最多10个并发连接
}
}
在实际应用中,通常结合使用这两种限流方式,既控制请求速率,又限制并发连接数。
长连接优化:keepalive_timeout
长连接是提高并发效率的关键。在高并发场景下,合理设置keepalive参数可以大幅提升性能:
# 客户端 keepalive
keepalive_timeout 65;
keepalive_requests 10000;
# 上游服务器 keepalive
upstream backend {
server 192.168.1.10:8080;
keepalive 32; # 每个worker保持的空闲连接数
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1; # 启用HTTP/1.1
proxy_set_header Connection ""; # 清除 Connection头,启用 keepalive
}
}
实测下来,启用keepalive后,在高并发场景下可以提升30%~50%的吞吐量,同时减少50%的连接建立开销。
文件句柄:/proc/sys/fs 调优参数
Linux系统默认的文件句柄限制
往往是百万并发的第一道坎。以下是必要的系统调优:
# 在/etc/sysctl.conf中添加
fs.file-max = 2000000 # 系统全局文件句柄数量
fs.nr_open = 2000000 # 单个进程可打开的文件句柄上限
# 在/etc/security/limits.conf中添加
nginx soft nofile 1000000
nginx hard nofile 1000000
别忘了还需要调整Nginx配置:
worker_rlimit_nofile 1000000; # 必须小于系统fs.nr_open值
最后编辑:Jeebiz 更新时间:2025-10-18 21:08