processes
- master process:nginx 主进程,负责管理 worker 进程和读取配置,不处理具体请求。
- worker process:实际处理客户端请求的进程,数量一般等于 CPU 核心数。2 核就有 2 个 worker。
- cache manager process:nginx 缓存管理进程,用于清理过期缓存文件,不计入worker_processes。
案例1:
如果现在有一个 2核 的服务器,nginx 配置 worker_processes auto; 执行ps -ef|grep nginx
之后
js
root 31722 1 0 13:20 ? 00:00:00 nginx: master process ...
www 31723 31722 0 13:20 ? 00:00:00 nginx: worker process
www 31724 31722 0 13:20 ? 00:00:00 nginx: worker process
www 31725 31722 0 13:20 ? 00:00:00 nginx: cache manager process
为什么会多一个进程
当启用了 nginx 的 缓存功能 (例如 proxy_cache_path
),nginx 会额外启动 cache manager 和 cache loader 进程:
- cache manager:定期检查缓存目录,删除过期的缓存文件。
- cache loader :在 nginx 启动时加载磁盘上的缓存元数据到内存,启动完成后会退出。
验证方法:nginx.conf 里搜索proxy_cache_path
或fastcgi_cache_path
worker_connections
js
events{
worker_connections 1024;
}
在 Nginx 配置中,events
块的 worker_connections
用于定义单个 worker 进程可同时处理的最大连接数 (默认通常为 1024)。若将其配置得 "非常大"(如远超系统承载能力的 10 万、100 万),不会单纯带来 "连接数提升" 的好处,反而会引发一系列系统资源过载、性能反降甚至服务崩溃的问题,具体后果可从资源消耗、系统限制、Nginx 自身逻辑三个维度拆解:
一、核心后果:系统资源被过度占用,引发连锁故障
worker_connections
并非 "配置越大越好"------ 每个连接(即使是空闲连接)都需要消耗系统的内存 和文件描述符,配置过大会直接导致这两类核心资源耗尽。
- 内存耗尽(最直接、最致命的后果)
Nginx 的每个连接(包括 TCP 连接、HTTP 连接)都需要占用一块 "连接结构体" 内存(约 2KB~10KB,取决于连接类型和 Nginx 版本),同时 Linux 内核为每个 TCP 连接也会分配 "套接字(socket)缓冲区"(默认约 8KB 接收缓冲区 + 8KB 发送缓冲区,可通过sysctl
调整)。
当worker_connections
配置过大时(如 100 万),即使实际连接数未达上限,Nginx 启动时也可能因 "预分配连接资源" 或 "内核为潜在连接预留缓冲区" 导致内存被大量占用:
- 若服务器物理内存 / 虚拟内存不足,会触发 OOM(Out Of Memory)杀手:系统会强制杀死占用内存最高的进程(通常是 Nginx worker 进程),直接导致 Nginx 服务崩溃;
- 若内存未完全耗尽,剩余内存会被大量用于连接缓冲,导致 Nginx 处理 "实际请求"(如解析 HTTP 头、转发静态文件)的内存不足,引发请求处理延迟飙升、超时率上升;
- 极端情况下,系统内存耗尽会导致其他服务(如数据库、监控工具)也被 OOM 杀死,引发整机故障。
- 文件描述符(FD)耗尽,新连接无法建立
在 Linux 系统中,一切皆文件 ------Nginx 的每个连接(socket)、打开的配置文件、日志文件都需要占用一个 "文件描述符(File Descriptor,FD)"。
worker_connections
的最大值受限于两个层面的 FD 限制,配置过大会直接突破限制:
- 进程级 FD 限制 :Linux 对单个进程的最大 FD 数有默认限制(如
ulimit -n
默认值通常为 1024 或 65535)。若worker_connections
超过该值,Nginx 启动时会报错too many open files
,worker 进程无法正常启动; - 系统级 FD 限制 :Linux 还会限制整机的最大 FD 数(通过
sysctl -a | grep fs.file-max
查看,默认可能为几十万)。若worker_connections × worker_processes
(总最大连接数)超过系统级限制,即使进程级 FD 已调大,新连接仍会被内核拒绝,表现为 "客户端无法建立连接(Connection Refused)"。 即使手动调大 FD 限制(如通过ulimit -n 1000000
),也会导致系统 FD 资源被 Nginx 独占,其他进程(如 SSH、日志收集工具)无法获取 FD,进而无法正常工作。
二、性能反降:连接数远超 "实际处理能力",资源错配
Nginx 的 "连接处理" 并非孤立 ------ 每个连接背后可能对应一个 HTTP 请求,而请求处理需要 CPU 计算 (解析请求头、执行路由逻辑)、磁盘 I/O (读取静态文件)或 网络 I/O (反向代理到后端服务)。
若 worker_connections
配置过大,会出现 "连接数远超实际处理能力" 的情况:
- CPU 过载:单个 worker 进程是 "单线程、事件驱动" 的,若同时有几十万连接触发请求,worker 会陷入 "频繁处理事件循环" 的状态,无法高效处理核心请求(如静态文件转发),导致 CPU 使用率飙升至 100%,请求响应时间(RTT)从毫秒级变为秒级;
- I/O 瓶颈凸显 :即使 CPU 未过载,磁盘 I/O(如机械硬盘每秒只能处理几百次读写)或网络带宽(如 1G 网卡每秒最大传输约 100MB)也会成为瓶颈。此时多余的连接只会处于 "排队等待 I/O" 的状态,不仅无法提升吞吐量,还会因连接超时(如
keepalive_timeout
)导致大量重试,进一步加剧 I/O 压力; - 空闲连接浪费资源 :实际业务中,大量连接是 "长连接(keepalive)" 或 "空闲连接"(如客户端建立连接后未发送请求)。若
worker_connections
过大,这些空闲连接会长期占用内存和 FD,挤占 "活跃连接" 的资源,导致活跃请求被阻塞。
三、Nginx 自身逻辑限制:配置过大可能触发启动失败或异常
Nginx 对 worker_connections
有隐性逻辑限制,并非 "配置多少就支持多少":
- 启动时校验失败 :若
worker_connections
超过worker_rlimit_nofile
(Nginx 进程级 FD 限制,默认继承系统ulimit -n
),Nginx 启动日志会输出worker_connections exceed open file resource limit
,直接启动失败; - 连接数与 worker 进程的匹配问题 :总最大连接数 =
worker_processes × worker_connections
(通常建议worker_processes
等于 CPU 核心数)。若worker_connections
过大,总连接数可能远超服务器的 "TCP 端口范围"(Linux 端口默认范围是 1024~65535,即单个 IP 最多支持约 6.4 万 outbound 连接)------ 若 Nginx 作为反向代理(需主动连接后端服务),会因 "无法分配新端口" 导致后端连接失败; - 事件模型限制 :Nginx 依赖 Linux 的事件模型(如
epoll
)处理连接,epoll
的 "最大监听连接数" 受限于fs.epoll.max_user_watches
(默认约 10 万)。若worker_connections
超过该值,epoll
无法注册新连接,Nginx 会无法感知新连接请求,表现为 "客户端连接超时,但 Nginx 日志无任何记录"。
四、总结:合理配置 worker_connections
的原则
worker_connections
的合理值并非固定,需结合服务器硬件(CPU、内存、带宽)、业务场景(长连接 / 短连接、请求量)、系统限制综合计算,核心原则如下:
- 不超过系统 / 进程 FD 限制 :确保
worker_connections ≤ worker_rlimit_nofile
(建议worker_rlimit_nofile
手动设置为 65535 或更高,避免依赖系统默认值); - 不超过内存承载能力 :按 "每个连接占用 20KB 内存" 估算(保守值),若服务器内存为 8GB,可分配给 Nginx 连接的内存若为 4GB,则单 worker 最大连接数 ≈ 4GB / 20KB ≈ 20 万(需结合
worker_processes
分摊); - 匹配实际业务吞吐量 :通过监控工具(如
nginx-status
、Prometheus)观察 "实际最大并发连接数",通常配置为 "实际峰值的 1.2~1.5 倍" 即可(如实际峰值 1 万连接,配置 1.5 万即可,无需追求几十万); - 参考内核参数 :调优相关内核参数以匹配
worker_connections
,如:
ini
# 系统级最大 FD 数
sysctl -w fs.file-max=1000000
# epoll 最大监听数
sysctl -w fs.epoll.max_user_watches=1000000
# TCP 连接超时回收(减少空闲连接)
sysctl -w net.ipv4.tcp_keepalive_time=600
总之,worker_connections
是 "系统资源与业务需求的平衡参数",而非 "越大越好的性能开关"。配置过大会直接触发资源耗尽、性能反降甚至服务崩溃,合理的做法是 "基于实际监控数据,结合硬件上限逐步调优"。
http
include mime.types;
1. 什么是 MIME 类型
mime.types
文件是 Nginx 用来映射文件扩展名与 MIME 类型的配置文件 。
它的主要作用是:当 Nginx 处理静态文件时,告诉浏览器(或其他客户端)该文件的类型,从而让客户端正确解析和显示内容。
MIME(Multipurpose Internet Mail Extensions)类型是一种标准化的方式,用来表示文档、文件或字节流的性质和格式。
- 在 HTTP 协议中,通过响应头
Content-Type
告诉客户端返回的文件类型。 - 例如:
text/html
表示 HTML 页面application/javascript
表示 JavaScript 文件image/png
表示 PNG 图片
如果服务器返回的 Content-Type
不正确,浏览器可能会:
- 直接下载文件而不是显示
- 显示乱码
- 无法正确执行脚本或渲染图片
2. mime.types
的作用
mime.types
文件里定义了 "文件扩展名" 和 "MIME 类型" 的对应关系,例如:
js
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/json json;
}
- 左边是 MIME 类型
- 右边是对应的文件扩展名(多个扩展名用空格分隔) 当 Nginx 处理一个
.js
文件时:
- 查找
mime.types
,发现.js
对应application/javascript
- 在 HTTP 响应头中加入:
js
Content-Type: application/javascript
- 浏览器收到后,就知道这是 JavaScript 文件,会执行而不是下载。
3. Nginx 中如何使用 mime.types
在 nginx.conf
中,通常会这样引用:
js
http {
include mime.types;
default_type application/octet-stream;
}
include mime.types;
:加载mime.types
文件中的映射关系default_type application/octet-stream;
:如果文件扩展名没有在mime.types
中找到匹配项,就使用默认类型(通常会触发浏览器流式下载该文件)
4. 如果不配置 mime.types
会怎样
- 所有未匹配到类型的文件都会返回
application/octet-stream
- 浏览器可能会下载这些文件,而不是直接显示或执行
- 例如
.html
文件不会被解析为网页,而是直接下载
server
server 主要是用来 定义一个虚拟主机(Virtual Host) 的配置。当有请求到达时,如何处理针对某个域名(或 IP + 端口)的访问。
核心指令说明
listen
指定监听的端口,例如80
、443 ssl
。server_name
指定匹配的域名,可以写多个,空格分隔。location
根据 URL 路径匹配不同的处理规则,例如反向代理、静态文件等。root
指定静态文件的根目录。index
默认首页文件名。access_log
/error_log
访问日志和错误日志路径。
多域名部署多站点
通过 server_name 指令区分不同域名,共用 80/443 端口。
基本配置思路
- 一个服务器监听 80/443 端口
- 用
server_name
区分不同域名 - 每个域名对应不同的根目录或反向代理
ini
# 站点A配置
server {
listen 80;
server_name site-a.com www.site-a.com;
root /var/www/site-a;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
}
# 站点B配置
server {
listen 80;
server_name site-b.com www.site-b.com;
root /var/www/site-b;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
}