Nginx

Nginx(发音 “engine-x”)是一款开源的高性能 Web 服务器,同时具备反向代理和负载均衡能力,由俄罗斯程序员 Igor Sysoev 开发。在集群架构中,Nginx 遍布多个层级,是最核心的基础设施组件之一。

核心能力

1. 七层负载均衡(http 模块)

工作于 OSI 第七层(应用层),解析 HTTP 协议内容进行精细化路由:

  • 按 URL 路径(/api/* → API 集群,/static/* → 静态文件服务器)
  • 按域名(Host: blog.example.com → 博客集群)
  • 按 Cookie、User-Agent 等头部信息
  • 支持 proxy_pass 反向代理 + upstream 后端服务器池
http {
    upstream web_servers {
        server 192.168.71.112:8080 weight=1;
        server 192.168.71.113:8080 weight=1;
    }
    server {
        listen 8081;
        location / {
            proxy_pass http://web_servers;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

2. 四层负载均衡(stream 模块)

工作于 OSI 第四层(传输层),基于 IP+Port 转发 TCP/UDP 流量:

  • 代理 MySQL、Redis 等非 HTTP 协议
  • 四层代理七层放大并发(四层粗分发 → 七层细分发)
  • 配置语法:stream { upstream {} server { listen; proxy_pass; } }
stream {
    upstream l7_servers {
        server 192.168.71.116:8081;
        server 192.168.71.111:8081;
    }
    server {
        listen 9999;
        proxy_pass l7_servers;
    }
}

3. 静态文件服务 + 反向代理

集群架构中的典型位置:

用户 → LVS(四层)→ Nginx(七层,动静分离)→ 应用服务器
                                       → 静态文件直接返回

4. 协议透传

  • 七层:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
  • 四层:配合 Proxy Protocol(HAProxy 协议)透传客户端 IP

与其他方案对比

方案层级性能功能适合场景
LVS四层⭐⭐⭐大规模集群入口
Nginx四/七层⭐⭐⭐⭐⭐Web 七层负载均衡首选
Haproxy四/七层⭐⭐⭐⭐精细 ACL 路由
F5四/七层⭐⭐⭐⭐⭐⭐金融/运营商(昂贵)

关键配置要点

  • worker_processes:CPU 核心数
  • worker_connections:每个 worker 最大连接数
  • worker_rlimit_nofile:文件描述符上限(高并发必须调高)
  • proxy_connect_timeout / proxy_timeout:后端连接超时
  • max_fails / fail_timeout:健康检查参数

安装方式

方式命令优点适用场景
Yum 安装yum install nginx快速便捷,包管理测试环境、快速部署
源码编译./configure && make && make install可定制编译参数,模块自由选择生产环境、定制需求

Yum 安装文件分散在系统目录;源码安装文件集中在 --prefix 指定目录,便于管理。

源码常见编译参数:

./configure --prefix=/usr/local/nginx \
            --with-http_ssl_module \
            --with-stream \
            --with-http_v2_module \
            --with-threads

依赖:gcc pcre-devel openssl-devel zlib-devel


文件分布(Yum 安装)

路径用途
/etc/nginx/nginx.conf主配置文件
/etc/nginx/conf.d/子配置文件目录(通过 include 加载)
/etc/nginx/fastcgi_paramsFastCGI 协议参数
/etc/nginx/uwsgi_paramsuWSGI 协议参数
/etc/nginx/mime.typesMIME 类型映射
/usr/sbin/nginx管理命令
/var/log/nginx/日志文件(access.log、error.log)
/etc/logrotate.d/nginx日志轮转配置

常用命令与平滑升级

命令说明
nginx -t检查配置文件语法
nginx -T检查并输出完整配置
nginx -s reload热重载配置(不重启进程)
nginx -s stop快速停止
nginx -s quit优雅停止(处理完当前请求后退出)
nginx -s reopen重新打开日志文件
nginx -v / nginx -V查看版本 / 版本+编译参数

平滑升级:将新版本 Nginx 编译安装到独立目录 → 切换软链接 → 发送 USR2 信号启动新 master → 发送 QUIT 信号让旧 master 优雅退出。


配置结构

Nginx 配置采用分块层级结构

main(全局块)
├── events 块(网络IO模型)
├── http 块(HTTP 协议相关)
│   ├── upstream 块(后端服务器池)
│   ├── server 块(虚拟主机)
│   │   └── location 块(URL 匹配与处理)
│   └── ...
└── stream 块(四层 TCP/UDP 代理)
    └── server 块

http 块关键指令

指令作用
sendfile零拷贝文件传输
tcp_nopush / tcp_nodelayTCP 性能优化
keepalive_timeout长连接超时
types_hash_max_sizeMIME 类型哈希表大小
default_type默认 Content-Type

server 块(虚拟主机)

  • listen:监听 IP:端口
  • server_name:域名匹配(精确/通配符/正则)
  • index:默认索引文件(按顺序查找)
  • error_page:自定义错误页

Events 配置与网络 IO 模型

events 块配置 Nginx 连接处理方式。Nginx 采用 epoll 异步非阻塞事件驱动模型,是其高并发能力的核心。

网络 IO 模型对比

模型机制效率适用场景
select遍历所有连接检查数据到达连接越多效率越低连接 < 1024
poll类似 select,无连接数限制大量连接仍低效连接数稍多
epoll每个 IO 绑定回调,数据到达时主动触发连接越多优势越明显高并发场景

并发量计算

最大并发 ≈ worker_processes × worker_connections
  • worker_processes:工作进程数,通常设为 CPU 核心数
  • worker_connections:每个 worker 的最大连接数
  • 需结合硬件资源(CPU/内存)和系统文件描述符限制(ulimit -n)设置

events 配置示例

events {
    use epoll;                  # 使用 epoll 模型
    worker_connections 1024;    # 每进程最大连接数
    multi_accept on;            # 单次 accept 可接受多个连接
}

HTTP 核心优化参数

文件传输

参数说明推荐值
sendfile on;零拷贝:文件直接从内核缓冲区到网卡,绕过用户态on
tcp_nopush on;与 sendfile 配合,数据包填满后再发送on
tcp_nodelay on;禁用 Nagle 算法,小块数据实时发送on

传统传输:硬盘 → 内核缓冲区 → 用户态缓冲区 → 内核缓冲区 → 网卡
sendfile:硬盘 → 内核缓冲区 → 网卡(零拷贝)

连接与超时

参数说明推荐值
keepalive_timeout长连接超时时间65s
keepalive_requests单连接最大请求数100
client_max_body_size客户端请求体最大大小1m
client_header_timeout请求头超时60s
client_body_timeout请求体超时60s
reset_timedout_connection on;超时后重置连接on

文件缓存

open_file_cache max=1000 inactive=20s;    # 打开文件缓存
open_file_cache_valid 30s;                 # 缓存有效期
open_file_cache_min_uses 2;                # 最少使用次数
open_file_cache_errors on;                 # 缓存错误信息

Gzip 压缩

gzip on;                                    # 启用压缩
gzip_min_length 1k;                         # 最小压缩大小
gzip_comp_level 6;                          # 压缩级别(1-9)
gzip_types text/plain text/css application/json application/javascript text/xml;

Server 与虚拟主机

虚拟主机指通过一个 Nginx 承载多个站点,每个站点对应一个 server 块。

三种实现方式

方式配置依据适用场景
基于域名server_name最常用,多域名共享同一 IP:端口
基于端口listen 不同端口不同服务使用不同端口
基于 IP不同 IP 地址服务器有多个 IP
# 基于域名(最常用)
server {
    listen 80;
    server_name www.egon1.com;
    root /var/www/html/egon1;
}
server {
    listen 80;
    server_name www.egon2.com;
    root /var/www/html/egon2;
}
server {
    listen 80 default_server;   # 默认站点(未匹配时使用)
    server_name _;
    root /var/www/html/default;
}

Location 匹配规则

location 是 Nginx 配置中最核心的模块,决定了请求如何路由到不同的处理逻辑。

匹配优先级(从高到低)

优先级语法示例说明
1(最高)= uri= /logo.png精确匹配,命中即停止
2^~ uri^~ /static/前缀匹配,命中后不再检查正则
3~ pattern~ \.php$正则匹配(区分大小写),按定义顺序
4~* pattern~* \.jpg$正则匹配(不区分大小写)
5(最低)uri/ / /api/普通前缀匹配,取最长匹配

匹配完整流程

① 先检查精确匹配(=)
  ├─ 命中 → 直接使用,停止
  └─ 未命中 → 进入第②步

② 检查前缀匹配(^~ 和普通前缀)
  ├─ 记录最长前缀匹配
  ├─ 如果有 ^~ 命中 → 跳过正则检查,使用该 location
  └─ 否则 → 进入第③步

③ 按定义顺序检查正则匹配(~ / ~*)
  ├─ 命中第一个正则 → 使用该 location
  └─ 全部未命中 → 使用第②步记录的最长前缀

命名 location

location @name { ... } 形式,用于内部重定向(类似 goto),不对外暴露。


日志配置

访问日志(access_log)

# 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';
 
# json 格式(便于日志收集系统解析)
log_format json escape=json '{'
    '"time_local":"$time_local",'
    '"remote_addr":"$remote_addr",'
    '"request":"$request",'
    '"status":$status,'
    '"body_bytes_sent":$body_bytes_sent,'
    '"http_referer":"$http_referer",'
    '"http_user_agent":"$http_user_agent",'
    '"http_x_forwarded_for":"$http_x_forwarded_for"'
'}';
 
# 应用日志格式
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
参数说明
buffer=32k缓冲区大小,满后写入磁盘
flush=5s缓冲区超时刷出
gzip实时压缩后写入

错误日志(error_log)

error_log /var/log/nginx/error.log warn;   # 级别:debug < info < notice < warn < error < crit < alert < emerg

生产环境通常设置为 warnerror

日志轮转(logrotate)

日志文件不断增长,需定期切割归档。通过 /etc/logrotate.d/nginx 配置:

/var/log/nginx/*.log {
    daily            # 每天轮转
    rotate 52        # 保留 52 份
    compress         # 压缩旧日志
    delaycompress    # 延迟压缩
    notifempty       # 空文件不轮转
    create 644 nginx nginx
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`   # 通知 Nginx 重开日志文件
        fi
    endscript
}

或手动:nginx -s reopen 重新打开日志文件句柄。


root vs alias

两个指令都用于将 URI 映射到文件系统路径,但行为关键不同:

指令行为示例
root拼接:root 路径 + location 路径root /var/www/html + /egon//var/www/html/egon/
alias替换:直接用 alias 路径替代alias /mmm/ + //mmm/(不拼接)

alias 末尾必须加斜杠/),否则路径拼接异常。


return 指令

用于停止处理请求,直接返回状态码或重定向。

语法

return code [text];      # 返回状态码 + 响应体
return code URL;          # 重定向到 URL
return URL;               # 需以 http:// 或 https:// 开头

301 vs 302

对比项301 永久重定向302 临时重定向
浏览器缓存缓存结果,后续直接走新地址不缓存,每次都请求原地址
服务器压力仅第一次请求每次请求都到服务器
SEO 影响权重转移权重不转移
适用场景域名永久迁移、HTTP→HTTPS临时活动页、AB 测试、维护中跳转

使用建议:简单跳转优先用 return(比 rewrite 性能更好)。HTTPS 跳转用 301,临时活动页用 302。


代理类型

类型代理对象客户端配置位置要求典型用途
正向代理客户端需要内/外网均可翻墙、访问限制
透明代理客户端(对用户透明)不需要必须与客户端同内网上网行为分析、内容过滤
反向代理服务端不需要服务端前置负载均衡、安全防护、缓存

Nginx 主要提供反向代理功能。


动静分离

通过 location 将动态请求和静态请求分开处理。分离和分层都是优化思想——核心思路是:能不能抽离出来?能抽离就能单独针对性地优化。

三大方案对比

方案实施位置优点缺点
方案一前端代码CDN 加速效果最好需修改代码,更新需刷新 CDN
方案二Web 服务器精细化管理,缓存控制灵活Web 服务器仍承担部分静态流量
方案三-1七层负载均衡器动静分离彻底负载均衡器职责不清(既派活又干活)
方案三-2七层负载均衡 + 独立集群职责清晰,可独立扩展架构复杂,成本较高

推荐组合:方案一(CDN 加速前端静态资源)+ 方案二(Web 服务器层精细缓存 + expires)+ 方案三-2(LB 层抽离到独立静态集群)。

方案一:前端代码直接使用 CDN 地址

后端返回前端代码时,静态文件 URL 直接配置为 CDN 地址:

<img src="https://cdn.example.com/static/img/logo.jpg">
<link rel="stylesheet" href="https://cdn.example.com/static/css/style.css">

方案二:Web 服务器层分离

server {
    listen 80;
    root /var/www/html;
 
    # 动态请求:转发给 php-fpm
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi_params;
    }
 
    # 静态请求:Nginx 直接返回,设置缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        access_log off;
    }
}

方案三:七层负载均衡层分离

upstream app_servers {
    server 192.168.43.100:8080;
    server 192.168.43.101:8080;
}
upstream static_servers {
    server 192.168.43.200:80;
    server 192.168.43.201:80;
}
 
server {
    listen 80;
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        proxy_pass http://static_servers;
        expires 30d;
    }
    location / {
        proxy_pass http://app_servers;
    }
}

Web 服务器层分离(基础形式)

location / {
    proxy_pass http://web_servers;       # 动态请求 → 应用服务器
}
location /static/ {
    root static;                          # 静态请求 → 本地文件
}

资源分离

动静分离的进一步细化——根据请求特征(如 User-Agent、URL 参数等)将请求分发到不同后端集群:

upstream android { server 10.0.0.7:80; }
upstream iphone  { server 10.0.0.8:80; }
upstream pc      { server 10.0.0.9:80; }
 
server {
    listen 80;
    server_name example.com;
 
    location / {
        if ($http_user_agent ~* "Android") { proxy_pass http://android; }
        if ($http_user_agent ~* "iPhone")  { proxy_pass http://iphone; }
        if ($http_user_agent ~* "WOW64")   { return 403; }
        proxy_pass http://pc;               # 默认走 PC 集群
    }
}

常用于移动端/PC 端分离、灰度发布等场景。


TCP 连接队列

半连接队列与全连接队列

在 TCP 三次握手过程中,内核为每个监听 socket 维护两个队列:

队列状态存储内容内核参数
半连接队列(SYN Queue)SYN_RECV已发 SYN+ACK 等待第三次握手net.ipv4.tcp_max_syn_backlog
全连接队列(Accept Queue)ESTABLISHED三次握手完成,等待 accept()net.core.somaxconn

队列满的后果:半连接队列满 → 新 SYN 被丢弃;全连接队列满 → 新连接被丢弃或客户端超时。

SYN Flood 攻击:攻击者大量发 SYN 不回复 ACK,占满半连接队列。通过 net.ipv4.tcp_syncookies = 1 启用 SYN Cookie 防御。

Nginx 全连接队列两种模式

模式一:共享全连接队列(默认)

所有 worker 进程从同一个全连接队列中通过 accept() 取连接。优点:某个 worker 处理耗时请求时,其他 worker 仍能取新连接,压力自动平衡。缺点:多 worker 并发争抢需加锁,有性能损耗。

模式二:独享全连接队列(reuseport)

每个 worker 进程独立调用 bind() + listen(),拥有独立的全连接队列。内核根据四元组哈希将连接分发到各 worker,无需加锁。

server {
    listen 80 reuseport backlog=4096;   # 开启 reuseport
}

优点:减少锁竞争,处理效率更高。缺点:某个 worker 繁忙时,其他 worker 无法分担其队列压力。

Worker 内多线程

通过 --with-threads 编译选项支持,配置 aio threads; 开启。好处:缓解 worker 繁忙时的压力;坏处:引入线程间资源争抢,增加 bug 风险。

Nginx 抗并发优化路径

默认模式(共享队列 + 单线程 worker)
  → 开启 reuseport(独享队列,减少锁竞争)
  → 开启 threads(多线程 worker,进一步提升并发)

Upstream 健康检查与负载均衡

健康检查参数

参数说明
max_fails=3连续失败最大次数,超过后标记不可用
fail_timeout=5s超时时间内累计 max_fails 次则不可用
backup备用服务器
down手动下线
upstream my_servers {
    server 192.168.43.100:8080 max_fails=3 fail_timeout=5s;
    server 192.168.43.101:8080 max_fails=3 fail_timeout=5s;
    server 192.168.43.102:8080 backup;
    server 192.168.43.103:8080 down;
}

双重故障检测

  • 端口级max_fails + fail_timeout 检测进程挂掉、网络不通
  • 应用层proxy_next_upstream 检测后端进程存在但返回错误响应
location / {
    proxy_pass http://my_servers;
    proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_403 http_404;
}

慢启动(slow_start)

新服务器瞬间接收大量流量可能打满连接池。slow_start 让新服务器逐步接收流量(Nginx Plus 支持,开源版不支持)。

Nginx 开源版替代方案:流量低峰期上线、手动逐步增加权重、或使用 Haproxy(原生支持 slow_start)。

负载均衡算法

算法说明适用场景
轮询(默认)按顺序轮流分发后端配置相同
weight按权重比例分发后端性能不同
ip_hash按客户端 IP 哈希,同一 IP 固定到同一服务器会话保持
least_conn分发到当前连接数最少的服务器WebSocket 长连接
url_hash按 URL 哈希分发缓存服务器提高命中率

Rewrite 重写模块

ngx_http_rewrite_module 提供 URI 改写功能,将请求 URI 中的路径部分改写为新的路径。

应用场景

场景说明
伪静态将动态 URL 转为静态路径格式,方便搜索引擎收录
协议/端口更换HTTP → HTTPS,端口重写
域名迁移旧域名的访问跳转到新域名

五种控制指令

指令作用类比
break终止循环,不再执行后续重写规则循环中的 break
last终止本次循环,重新开始新一轮 location 匹配循环中的 continue
if条件判断编程语言中的 if
return返回状态码或重定向,整体结束函数返回
rewrite将 URL 路径重写为新路径URL 改写

执行流程

① 请求到达
    ↓
② 执行 server 块中的重写规则
    ├─ 重写为完整 URL(带域名)→ 直接跳转
    └─ 重写为纯路径 → 进入 loop 循环
    ↓
③ Loop 循环(最多 10 次,防死循环)
    ├─ 执行 location 块中的重写规则
    ├─ 匹配到新 location → 继续执行新 location 的重写规则
    └─ 不匹配 → 结束循环
    ↓
④ 请求处理结束

rewrite 指令详解

语法:rewrite regex replacement [flag];

参数说明
regex正则表达式,匹配请求 URI
replacement替换后的路径或完整 URL
flag可选标志,控制重写后的行为

四种 Flag:

Flag说明类比
break终止循环,不再执行后续重写规则循环 break
last终止本次循环,重新进行 location 匹配循环 continue
redirect返回 302 临时重定向302 状态码
permanent返回 301 永久重定向301 状态码

配置示例

server {
    listen 80;
 
    # break:终止循环,直接返回文件
    location /break/ {
        rewrite ^/break/(.*) /static/$1 break;
    }
 
    # last:重新进行 location 匹配
    location /last/ {
        rewrite ^/last/(.*) /static/$1 last;
    }
    location /static/ {
        root /var/www/static;
    }
 
    # redirect:302 临时重定向(URL 栏会变)
    location /old {
        rewrite ^/old(.*) /new$1 redirect;
    }
 
    # permanent:301 永久重定向(浏览器缓存结果)
    location /http {
        rewrite ^/(.*) https://$server_name/$1 permanent;
    }
}

rewrite vs return

对比项rewritereturn
功能URL 路径改写返回状态码/重定向
正则支持支持不支持
性能稍慢(需正则匹配)更快
适用场景复杂的 URL 重写简单的跳转

生产场景中简单的域名跳转优先使用 return(性能更好)。

伪静态案例

# 将 /article/123 映射到 /article.php?id=123
location / {
    rewrite ^/article/(\d+)$ /article.php?id=$1 last;
}

调试

rewrite_log on;
error_log /var/log/nginx/error.log notice;

重写日志会记录到 error_log 中。


其他常用模块

模块功能配置示例
目录索引自动生成目录列表autoindex on;
访问控制基于 IP 的访问限制allow 192.168.1.0/24; deny all;
访问认证HTTP 基本认证auth_basic "Restricted"; auth_basic_user_file .htpasswd;
状态监控查看 Nginx 连接状态stub_status on;
连接限制限制同一 IP 并发连接数limit_conn addr 10;
请求限制限制请求频率limit_req zone=req burst=20 nodelay;

配置示例

# 目录索引
location /download/ {
    autoindex on;
    autoindex_exact_size off;
    autoindex_localtime on;
}
 
# 访问控制
location /admin/ {
    allow 192.168.1.0/24;
    deny all;
}
 
# 访问认证
location /secret/ {
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}
 
# 状态监控
location /nginx_status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}
 
# 连接限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
location / {
    limit_conn addr 10;   # 同一 IP 最多 10 个并发连接
}
 
# 请求限制
limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
location / {
    limit_req zone=req burst=20 nodelay;  # 每秒最多 10 个请求,突发 20 个
}

相关页面