Nginx 是一款高性能的开源 Web 服务器,同时也是反向代理服务器、负载均衡器和 HTTP 缓存解决方案。其出色的性能和稳定性得益于独特的工作模式、高效的工作原理以及灵活的配置体系。本文将全面介绍Nginx 的工作模式、工作原理,并解析核心配置项,帮助读者建立对 Nginx 的系统认知
Nginx 主要支持两种工作模式:多进程模式(默认)和多线程模式,两种模式各有特点,适用于不同场景
核心架构与工作原理
事件驱动模型(异步非阻塞)
- Master 进程:
负责读取和验证配置文件,管理Worker 进程,以及处理信号等,它不直接处理客户端请求 - Worker 进程:
实际负责处理客户端请求,每个Worker 进程都是独立的,它们之间是平等的,通过争抢机制来处理请求(多进程 + 单线程非阻塞 I/O) - 关键优势:
1 个 Worker 可处理数千并发连接,内存消耗极低(约 Apache 的 1/10),且 Master 进程可以方便地进行配置更新、平滑升级等操作,而无需停止服务
异步非阻塞机制
- Worker 初始化
Worker 进程启动后,通过 epoll(Linux)/ kqueue(BSD)等事件监听接口进入就绪状态,监控其负责的 Socket 文件描述符(FD)集合。 - 连接事件触发
当新连接到达时,操作系统内核通过事件驱动模型通知 Worker 进程,Worker 以非阻塞模式接收连接 - 异步 I/O 处理
Worker 调用 recv() / send() 等 I/O 操作时,若数据未就绪,内核立即返回 EAGAIN 错误而非阻塞进程,Worker 转而处理其他就绪事件;当 I/O 操作需等待外部资源(如数据库响应)时,Worker 将连接状态挂起并注册回调函数,继续处理其他事件;待资源就绪(如内核通知数据可读),通过事件回调机制恢复处理
高并发原理
单个 Worker 通过状态机管理上万连接,全程无进程/线程切换开销,实现 C10K 级别并发。
核心配置解析
全局配置影响 Nginx 整体运行,位于配置文件最顶部
# 指定运行Nginx的用户
user nginx;
# 设置worker进程数量,auto表示自动匹配CPU核心数,推荐手动设置为与核心数一致
worker_processes 4;
# 定义错误日志路径和级别(debug、info、warn、error、crit),用于排查问题
error_log /var/log/nginx/error.log warn;
# 指定Nginx进程ID(PID)文件路径
pid /var/run/nginx.pid;
# 限制Nginx打开的文件描述符数量,-1表示不限制,必须同步调整系统级限制
worker_rlimit_nofile 65535;
events 块 (Events Context)
events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型.
use epoll;
#每个工作进程一次接受事件队列中的所有待处理连接(直到 worker_connections 上限)。适合突发高并发场景,减少事件通知次数,提升吞吐量。默认off
multi_accept on;
# 允许同时接收多个网络连接,提升连接处理效率
accept_mutex on;
# 必须同步调整系统级限制,单个进程最大连接数(max_clients = worker_processes × worker_connections)
worker_connections 10240;
}
http 块 (HTTP Context)
http
{
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型0 97n
access_log /var/log/nginx/access.log main; # 指定访问日志路径和格式(关联log_format定义的main)
# 定义访问日志格式,包含客户端IP、请求时间、请求内容、响应状态等信息
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 开启目录列表访问,合适下载服务器,默认关闭.
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
sendfile on; # 开启高效静态文件传输模式,适用于大文件传输下载,动态内容处理建议关闭
tcp_nopush on; # 通常与sendfile一起使用,用于优化数据包发送
tcp_nodelay off; #大文件传输关闭此设置
keepalive_timeout 65; # (单位s)设置客户端连接保持活动的超时时间,建议设置60-120秒
# gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #允许压缩的页面的最小字节数,页面字节数从header偷得content-length中获取.默认是0,不管页面多大都进行压缩.建议设置成大于1k的字节数,小于1k可能会越压越大
gzip_comp_level 5; #压缩等级.1压缩比最小,处理速度快.9压缩比最大,比较消耗cpu资源,处理速度最慢,但是因为压缩比最大,所以包最小,传输速度快
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;#选项可以让前端的缓存服务器缓存经过gzip压缩的页面
}
server 块 (Server Context)
http {
# 其他http块配置...
# 第一个虚拟主机,处理xxx.com相关请求
server {
# 监听的端口(如80对应HTTP,443对应HTTPS)
listen 80;
# 绑定的域名,多个域名用空格分隔,优先匹配精确域名
server_name xxx.com www.xxx.com;
# 网站根目录,用于存放静态资源
root /usr/share/nginx/xxx;
# 默认首页文件,按顺序查找
index index.html index.htm index.php;
# 访问日志,可单独设置
access_log /var/log/nginx/xxx_access.log main;
error_log /var/log/nginx/xxx_error.log error;
# 当请求的文件或目录不存在时,返回404页面
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
}
# 第二个虚拟主机,处理xxx2.com相关请求
server {
listen 80;
server_name xxx2.com;
root /usr/share/nginx/xxx2;
index index.html;
}
}
location 块 (Location Context)
server {
listen 80;
server_name xxx.com;
root /usr/share/nginx/xxx;
index index.html;
# 匹配所有未被其他location匹配的请求,通常作为默认规则
location / {
# 尝试查找请求的文件或目录,不存在则跳转至index.html(适用于单页应用路由)
try_files $uri$uri/ /index.html;
}
# 匹配以/static/开头的URI,用于处理静态资源
location /static/ {
# 浏览器缓存时间为30天
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# 正则匹配,处理图片文件(~*表示不区分大小写)
location ~* \.(jpg|jpeg|png|gif|webp)$ {
# 指定当前location的资源根目录
root /usr/share/nginx/images;
expires 7d;
}
# 处理PHP文件请求,转发给PHP-FPM处理
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 反向代理,将/api/开头的请求转发到后端服务器
location /api/ {
proxy_pass http://127.0.0.1:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
upstream 块 (Upstream Context)
http {
# 后端服务器集群,命名为backend
upstream backend {
server 172.30.1.1:8080 weight=3;
server 172.30.1.2:8080 weight=2;
# 备用服务器
server 172.30.1.3:8080 backup;
# 表示该服务器不可用
server 172.30.1.4:8080 down;
# 负载均衡策略,默认轮询
ip_hash; # 按客户端IP固定分配,解决会话保持问题
}
server {
listen 80;
server_name proxy.xxx.com;
location / {
# 转发到upstream集群
proxy_pass http://backend;
# 设置代理请求头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 代理连接超时时间
proxy_connect_timeout 60s;
# 代理接收后端服务器响应的超时时间
proxy_read_timeout 60s;
# 代理发送请求到后端服务器的超时时间
proxy_send_timeout 60s;
}
}
}
多环境配置示例
# 开发环境
server {
listen 8080;
server_name dev.xxx.com;
access_log /var/log/nginx/dev.access.log;
error_log /var/log/nginx/dev.error.log debug;
location / {
proxy_pass http://172.10.1.10:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# 生产环境
server {
listen 443 ssl http2;
server_name xxx.com www.xxx.com;
ssl_certificate /etc/nginx/sslkey/xxx.com/fullchain.pem;
ssl_certificate_key /etc/nginx/sslkey/xxx.com/privkey.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 24h;
ssl_session_tickets on;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:CHACHA20:!SHA1:!SHA256:!MD5';
# 安全头部
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'";
location / {
root /var/www/prod;
try_files $uri $uri/ /index.html;
# 缓存优化
expires 1y;
add_header Cache-Control "public, immutable";
}
location /api/ {
proxy_pass http://backend_cluster;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $Host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Remote_Addr $http_true_client_ip;
fastcgi_buffers 8 128k;
send_timeout 120;
}
}
二进制编译安装
我们以 Rocky Linux 8.10 版本为例,编译安装 Nginx,我们先安装依赖包
[root@localhost ~]# dnf install -y gcc gcc-c++ make cmake pcre-devel zlib-devel openssl-devel perl-ExtUtils-Embed
创建 Nginx 运行用户
useradd --system --no-create-home --shell /sbin/nologin nginx
下载 Nginx 源码 (稳定版本)
[root@localhost ~]# wget http://nginx.org/download/nginx-1.28.0.tar.gz
--2025-08-11 22:42:24-- http://nginx.org/download/nginx-1.28.0.tar.gz
Resolving nginx.org (nginx.org)... 3.125.197.172, 52.58.199.22, 2a05:d014:5c0:2600::6, ...
Connecting to nginx.org (nginx.org)|3.125.197.172|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1280111 (1.2M) [application/octet-stream]
Saving to: ‘nginx-1.28.0.tar.gz’
nginx-1.28.0.tar.gz 100%[===========================================================>] 1.22M 19.8KB/s in 41s
2025-08-11 22:43:05 (30.2 KB/s) - ‘nginx-1.28.0.tar.gz’ saved [1280111/1280111]
解压 Nginx 包
[root@localhost ~]# tar -zxvf nginx-1.28.0.tar.gz -C /usr/local/src/
nginx-1.28.0/
nginx-1.28.0/man/
nginx-1.28.0/CODE_OF_CONDUCT.md
nginx-1.28.0/LICENSE
nginx-1.28.0/configure
nginx-1.28.0/auto/
nginx-1.28.0/CHANGES
nginx-1.28.0/CHANGES.ru
.........................
配置编译参数
cd /usr/local/src/nginx-1.28.0
[root@localhost nginx-1.28.0]# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_secure_link_module --with-stream --with-stream_ssl_module --with-threads --with-file-aio --with-cc-opt="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC" --with-ld-opt="-Wl,-z,relro -Wl,-z,now -pie"
checking for OS
+ Linux 4.18.0-553.el8_10.x86_64 x86_64
checking for C compiler ... found
+ using GNU C compiler
+ gcc version: 8.5.0 20210514 (Red Hat 8.5.0-26) (GCC)
checking for gcc -pipe switch ... found
checking for --with-ld-opt="-Wl,-z,relro -Wl,-z,now -pie" ... found
checking for -Wl,-E switch ... found
checking for gcc builtin atomic operations ... found
checking for C99 variadic macros ... found
checking for gcc variadic macros ... found
checking for gcc builtin 64 bit byteswap ... found
checking for unistd.h ... found
checking for inttypes.h ... found
checking for limits.h ... found
checking for sys/filio.h ... not found
checking for sys/param.h ... found
checking for sys/mount.h ... found
checking for sys/statvfs.h ... found
checking for crypt.h ... found
checking for Linux specific features
checking for epoll ... found
checking for EPOLLRDHUP ... found
checking for EPOLLEXCLUSIVE ... found
checking for eventfd() ... found
checking for O_PATH ... found
checking for sendfile() ... found
checking for sendfile64() ... found
checking for sys/prctl.h ... found
checking for prctl(PR_SET_DUMPABLE) ... found
checking for prctl(PR_SET_KEEPCAPS) ... found
checking for capabilities ... found
checking for crypt_r() ... found
checking for sys/vfs.h ... found
checking for BPF sockhash ... found
checking for SO_COOKIE ... found
checking for UDP_SEGMENT ... not found
checking for poll() ... found
checking for /dev/poll ... not found
checking for kqueue ... not found
checking for crypt() ... not found
checking for crypt() in libcrypt ... found
checking for F_READAHEAD ... not found
checking for posix_fadvise() ... found
checking for O_DIRECT ... found
checking for F_NOCACHE ... not found
checking for directio() ... not found
checking for statfs() ... found
checking for statvfs() ... found
checking for dlopen() ... not found
checking for dlopen() in libdl ... found
checking for sched_yield() ... found
checking for sched_setaffinity() ... found
checking for SO_SETFIB ... not found
checking for SO_REUSEPORT ... found
checking for SO_ACCEPTFILTER ... not found
checking for SO_BINDANY ... not found
checking for IP_TRANSPARENT ... found
checking for IP_BINDANY ... not found
checking for IP_BIND_ADDRESS_NO_PORT ... found
checking for IP_RECVDSTADDR ... not found
checking for IP_SENDSRCADDR ... not found
checking for IP_PKTINFO ... found
checking for IPV6_RECVPKTINFO ... found
checking for IP_MTU_DISCOVER ... found
checking for IPV6_MTU_DISCOVER ... found
checking for IP_DONTFRAG ... not found
checking for IPV6_DONTFRAG ... found
checking for TCP_DEFER_ACCEPT ... found
checking for TCP_KEEPIDLE ... found
checking for TCP_FASTOPEN ... found
checking for TCP_INFO ... found
checking for accept4() ... found
checking for kqueue AIO support ... not found
checking for Linux AIO support ... found
checking for int size ... 4 bytes
checking for long size ... 8 bytes
checking for long long size ... 8 bytes
checking for void * size ... 8 bytes
checking for uint32_t ... found
checking for uint64_t ... found
checking for sig_atomic_t ... found
checking for sig_atomic_t size ... 4 bytes
checking for socklen_t ... found
checking for in_addr_t ... found
checking for in_port_t ... found
checking for rlim_t ... found
checking for uintptr_t ... uintptr_t found
checking for system byte ordering ... little endian
checking for size_t size ... 8 bytes
checking for off_t size ... 8 bytes
checking for time_t size ... 8 bytes
checking for AF_INET6 ... found
checking for setproctitle() ... not found
checking for pread() ... found
checking for pwrite() ... found
checking for pwritev() ... found
checking for strerrordesc_np() ... not found
checking for sys_nerr ... found
checking for localtime_r() ... found
checking for clock_gettime(CLOCK_MONOTONIC) ... found
checking for posix_memalign() ... found
checking for memalign() ... found
checking for mmap(MAP_ANON|MAP_SHARED) ... found
checking for mmap("/dev/zero", MAP_SHARED) ... found
checking for System V shared memory ... found
checking for POSIX semaphores ... not found
checking for POSIX semaphores in libpthread ... found
checking for struct msghdr.msg_control ... found
checking for ioctl(FIONBIO) ... found
checking for ioctl(FIONREAD) ... found
checking for struct tm.tm_gmtoff ... found
checking for struct dirent.d_namlen ... not found
checking for struct dirent.d_type ... found
checking for sysconf(_SC_NPROCESSORS_ONLN) ... found
checking for sysconf(_SC_LEVEL1_DCACHE_LINESIZE) ... found
checking for openat(), fstatat() ... found
checking for getaddrinfo() ... found
checking for PCRE2 library ... found
checking for OpenSSL library ... found
checking for zlib library ... found
creating objs/Makefile
Configuration summary
+ using threads
+ using system PCRE2 library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/etc/nginx"
nginx binary file: "/usr/sbin/nginx"
nginx modules path: "/etc/nginx/modules"
nginx configuration prefix: "/etc/nginx"
nginx configuration file: "/etc/nginx/nginx.conf"
nginx pid file: "/var/run/nginx.pid"
nginx error log file: "/var/log/nginx/error.log"
nginx http access log file: "/var/log/nginx/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
编译并安装
[root@localhost nginx-1.28.0]# make -j$(nproc) && make install
make -f objs/Makefile
make[1]: Entering directory '/usr/local/src/nginx-1.28.0'
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC -I src/core -I src/event -I src/event/modules -I src/event/quic -I src/os/unix -I objs \
-o objs/src/core/nginx.o \
..................................省略
test -f '/etc/nginx/nginx.conf' \
|| cp conf/nginx.conf '/etc/nginx/nginx.conf'
cp conf/nginx.conf '/etc/nginx/nginx.conf.default'
test -d '/run' \
|| mkdir -p '/run'
test -d '/var/log/nginx' \
|| mkdir -p '/var/log/nginx'
test -d '/etc/nginx/html' \
|| cp -R html '/etc/nginx'
test -d '/var/log/nginx' \
|| mkdir -p '/var/log/nginx'
make[1]: Leaving directory '/usr/local/src/nginx-1.28.0'
验证 Nginx 版本
[root@localhost nginx-1.28.0]# /usr/sbin/nginx -v
nginx version: nginx/1.28.0
创建相关目录并设置权限
mkdir -p /var/cache/nginx
mkdir -p /var/log/nginx
chown -R nginx:nginx /var/cache/nginx
chown -R nginx:nginx /etc/nginx
chown -R nginx:nginx /var/log/nginx
chmod -R 755 /etc/nginx
配置 systemd 服务
tee /etc/systemd/system/nginx.service << 'EOF'
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
启动 Nginx 服务
[root@localhost nginx-1.28.0]# systemctl enable --now nginx.service
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /etc/systemd/system/nginx.service.
[root@localhost nginx-1.28.0]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2025-08-11 23:27:34 CST; 4s ago
Process: 1020756 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 1020754 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 1020752 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 1020757 (nginx)
Tasks: 2 (limit: 100344)
Memory: 2.1M
CGroup: /system.slice/nginx.service
├─1020757 nginx: master process /usr/sbin/nginx
└─1020758 nginx: worker process
Aug 11 23:27:34 localhost.localdomain systemd[1]: Starting The nginx HTTP and reverse proxy server...
Aug 11 23:27:34 localhost.localdomain nginx[1020754]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Aug 11 23:27:34 localhost.localdomain nginx[1020754]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Aug 11 23:27:34 localhost.localdomain systemd[1]: Started The nginx HTTP and reverse proxy server.
验证 Nginx 模块
[root@localhost nginx-1.28.0]# nginx -V
nginx version: nginx/1.28.0
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-26) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_secure_link_module --with-stream --with-stream_ssl_module --with-threads --with-file-aio --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
总结
Nginx 凭借多进程架构、异步非阻塞事件模型,实现了高性能的并发处理能力,广泛应用于 Web 服务、反向代理和负载均衡场景。其配置灵活且模块化,通过全局配置、事件配置、虚拟主机和路径匹配,可满足复杂的业务需求。
参考文献
[1] Building nginx from Sources
[2] Stable version

要想成为扫地僧,需要不断的学习进步,这个世界,在悄悄惩罚那些不改变的人