--- title: Nginx tags: [概念, nginx, web-server, 负载均衡, 反向代理, stream 模块, web, network] created: 2026-07-21 updated: 2026-08-12 sources:

  • raw/day28 快速构建集群架构.md
  • raw/day33 负载均衡层详解part1.md
  • raw/day34 负载均衡层详解part2.md
  • raw/day25 Shell编程6.md
  • raw/一、nginx详解 – Egon林海峰.md
  • raw/day44 nginx详解part4.md
  • raw/day41 nginx详解part1.md
  • raw/day42 nginx详解part2.md
  • raw/day43 nginx详解part3.md
  • raw/day45 nginx详解part5.md
  • raw/nginx优化上 – Egon林海峰.md
  • raw/nginx优化下 – Egon林海峰.md
  • raw/day47 ssl、tls及全站https.md aliases: [Nginx, 引擎-x, Igor Sysoev, OpenResty]

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.site1.example.com;
    root /var/www/html/site1;
}
server {
    listen 80;
    server_name www.site2.example.com;
    root /var/www/html/site2;
}
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

生产环境通常设置为 warn 或 error。

日志轮转(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 + /user/ → /var/www/html/user/
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。


HTTPS / SSL 配置

HTTPS = HTTP + SSL/TLS。Nginx 作为 SSL 终结端,在 server 块配置证书与加密参数,支持单节点与集群全站加密。加密原理、证书体系与认证流程详见 SSL/TLS 与 HTTPS 加密体系。

单节点 HTTPS 配置

server {
    listen 443 ssl http2;
    server_name example.com;
 
    # 证书配置(Certbot/Let's Encrypt 申请)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 
    # SSL 协议与加密套件
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
 
    # HSTS(强制浏览器始终使用 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000" always;
 
    root /var/www/html;
    index index.html;
}

HTTP 自动跳转 HTTPS

server {
    listen 80;
    server_name example.com;
 
    # 301 永久重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

全站 HTTPS(集群架构)

全站 HTTPS = 每一层通信都加密:用户 → 七层 LB(HTTPS)→ Web 层 → FastCGI → php-fpm → MySQL SSL。

七层负载均衡器 HTTPS 配置(代理到 Web 集群,透传原始协议):

server {
    listen 443 ssl http2;
    server_name example.com;
 
    ssl_certificate /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
 
    location / {
        proxy_pass http://web_servers;
        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;
    }
}

FastCGI + HTTPS(PHP 应用):后端代码需判断请求是否 HTTPS 时,传递 HTTPS 环境变量:

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 
    # 传递 HTTPS 标识给 PHP
    fastcgi_param HTTPS on;
    fastcgi_param HTTP_SCHEME https;
 
    include fastcgi_params;
}

SSL 参数速查

参数说明
ssl_certificate证书文件路径(含完整证书链)
ssl_certificate_key私钥文件路径
ssl_protocols支持的 TLS 协议版本
ssl_ciphers允许的加密套件
ssl_prefer_server_ciphers优先使用服务端加密套件顺序
HSTS(Strict-Transport-Security)强制浏览器在未来指定时间内始终使用 HTTPS

代理类型

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

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 个
}

架构优化思路

整套架构追求四大目标:高性能、高可用、高一致性、安全性。

优化三步法

第一步:摸清情况
  ├─ 画架构图/链路图
  └─ 了解业务特点(电商→峰值流量大;ToB→逻辑复杂 bug 率高)
第二步:发现瓶颈
  ├─ 计算类:峰值 QPS / 单机极限 QPS = 需要的机器数
  └─ 观察类:MySQL 慢查询日志、top、netstat、stub_status
第三步:针对性优化
  ├─ 高频读 → 少读 / 就近读 / 读缓存
  ├─ 高频写 → 少写 / 漏斗写 / buffer 写
  └─ 动静分离 / 冷热分离

核心思想:“细分问题 → 抽离成单独层 → 单独处理”。动静分离、冷热分离都是这一思想的体现。

分层优化方向

层级常见问题优化方向
数据库层慢查询、IO 瓶颈优化 SQL、加索引、引入 Redis 缓存
Web 应用层机器数不足、负载不均扩容、调整权重
负载均衡层内存/CPU 瓶颈多级负载均衡、硬件 F5
文件服务器层单点故障、性能不足分布式存储(Ceph)
网络层丢包、延迟、带宽不足优化网络、加带宽、CDN

单机通用优化

维度优化要点
硬件负载均衡器(大内存多核)、数据库(大内存+SSD)、缓存(大内存)
系统内核参数调优(ipv4、半连接/全连接队列)
软件服务配置优化(Nginx)、应用环境参数调优

系统与 Nginx 优化

系统层面(内核参数)

参数作用配置
文件描述符提高最大打开文件数ulimit -n 65535
半连接队列增大 SYN 队列net.ipv4.tcp_max_syn_backlog = 16384
全连接队列增大 accept 队列net.core.somaxconn = 16384
TIME_WAIT 复用快速回收端口net.ipv4.tcp_tw_reuse = 1
端口范围增大可用端口net.ipv4.ip_local_port_range = 4000 65000

完整内核参数清单(/etc/sysctl.conf):

参数值作用
net.ipv4.tcp_fin_timeout2快速释放 FIN_WAIT 连接
net.ipv4.tcp_tw_reuse1复用 TIME_WAIT 端口
net.ipv4.tcp_tw_recycle1快速回收 TIME_WAIT(NAT 环境慎用)
net.ipv4.tcp_syncookies1开启 SYN Cookie 防洪水攻击
net.ipv4.tcp_keepalive_time600长连接探活间隔
net.ipv4.tcp_max_syn_backlog16384半连接队列
net.ipv4.tcp_max_tw_buckets36000TIME_WAIT 桶上限
net.ipv4.tcp_syn_retries1SYN 重传次数
net.core.somaxconn16384全连接队列
net.core.netdev_max_backlog16384网卡收包队列
net.ipv4.ip_local_port_range4000 65000本地端口范围
vim /etc/sysctl.conf   # 写入后生效
sysctl -p

文件描述符: 写入 /etc/security/limits.d/*.conf(优先级高于 /etc/security/limits.conf,无需重启,重新登录生效):

cat > /etc/security/limits.d/k8s.conf <<'EOF'
* soft nofile 65535
* hard nofile 131070
EOF
# soft:超过时提示;hard:超过时直接限制
ulimit -Sn   # 查看软限制
ulimit -Hn   # 查看硬限制
lsof | wc -l # 查看已打开的句柄数

Nginx 层面

参数作用推荐配置
worker_processesworker 进程数auto(与 CPU 核数一致)
worker_connections每进程最大连接数10240
worker_rlimit_nofile文件描述符上限65535
use epollIO 模型epoll
sendfile零拷贝on
tcp_nopush大包发送(与 sendfile 配合)on
tcp_nodelay禁 Nagle 算法,低延迟on
keepalive_timeout长连接超时65
keepalive_requests单连接最大请求数100
gzip压缩传输on
client_max_body_size请求体大小20m
client_header_buffer_size请求头缓冲区128k
large_client_header_buffers大请求头缓冲区4 128k
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
 
events {
    use epoll;
    worker_connections 10240;
}
 
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 100;
    gzip on;
    client_max_body_size 20m;
    client_header_buffer_size 128k;
    large_client_header_buffers 4 128k;
}

线程池 + reuseport(server 块)

thread_pool nginx_pool threads=3 max_queue=1024;  # 全局定义线程池
 
http {
    aio threads=nginx_pool;   # 启用线程池
 
    server {
        listen 8089 reuseport backlog=10240;   # reuseport 与线程池不冲突
    }
}

Nginx 代理长连接优化

反向代理默认每个请求都新建后端连接,性能开销大。通过长连接复用减少握手。

负载均衡代理到 Web 后端

upstream tomcat {
    server 172.16.1.7:8080;
    keepalive 8;                 # 每个 worker 保留 8 个空闲后端连接
}
 
server {
    listen 80;
    location / {
        proxy_pass http://tomcat;
        proxy_http_version 1.1;          # 必须 HTTP/1.1 才支持长连接
        proxy_set_header Connection "";  # 清除 Connection 头,启用复用
        include proxy_params;
    }
}

Nginx 代理到 PHP-FPM

location ~* \.php$ {
    fastcgi_pass php_server;
    fastcgi_keep_conn on;   # 开启与 PHP-FPM 的长连接
    include fastcgi_params;
}

proxy_params 标准配置

# /etc/nginx/proxy_params
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
proxy_next_upstream http_500 http_502 http_503 http_504;

静态资源缓存机制

缓存相关 HTTP 头

响应头:

头作用
Cache-Control: max-age=604800最直接影响缓存策略;no-cache/no-store 表示不缓存
Expires: Tue, 11 Jun 2024 10:05:12 GMT过期时间;与 Cache-Control 并存时 Cache-Control 优先
Last-Modified资源最后修改时间
ETag资源唯一标识符

请求头:

头作用
If-Modified-Since值来自 Last-Modified,服务端比对未修改则返回 304
If-None-Match值来自 ETag,与服务端文件 ETag 比对相同则返回 304

浏览器缓存流程

① 优先看响应头 cache-control
  ├─ 设置了缓存时间且未过期 → 直接用缓存
  ├─ no-cache → 继续看 expires
  └─ 未设置 → 走 ETag 验证
② ETag:放入 If-None-Match 发往服务端比对
  ├─ 相同 → 304 Not Modified → 浏览器用缓存
  └─ 不同 → 走 Last-Modified
③ Last-Modified:放入 If-Modified-Since 比对
  ├─ 相同 → 走缓存
  └─ 不同 → 重新拉取

ETag 优先于 If-Modified-Since 被检测,因为 ETag 可解决 Last-Modified 时间精度问题(无法判断内容微小修改)。

Nginx 配置

# 配置缓存过期时间
location ~* \.(png|jpg|gif)$ {
    root /code/cache;
    expires 7d;
}
 
# 强制不走缓存
location ~* \.(png|jpg|gif)$ {
    etag off;
    add_header Cache-Control no-cache;
    if_modified_since off;
}

静态资源压缩

location ~* \.(png|jpg|gif)$ {
    gzip on;
    gzip_types image/jpeg image/gif image/png;
    gzip_comp_level 9;      # 图片也可压缩(1-9 级)
}

防盗链

防止其他网站未经授权直接引用本站资源(图片、视频等),通过检查 HTTP 请求头中的 Referer 字段实现。核心原理:检测 Referer 字段判断请求来源。

注意:curl -e 伪造 Referer 可绕过防盗链——防盗链防的是 img 标签直接引用(盗链网站用 <img src> 指向本站资源),不是反爬虫。

valid_referers 语法

valid_referers none | blocked | server_names | string ...;
参数含义
none匹配无 Referer 头的请求(地址栏直接访问、收藏夹)
blocked匹配被防火墙/代理删除、或被修改为 - 的 Referer
server_names匹配当前 server 块定义的 server_name
string自定义特定域名,*.example.com 匹配子域名

配置示例

location ~* \.(jpg|jpeg|png|gif|ico)$ {
    valid_referers none blocked server_names
                   *.example.com example.com;
    if ($invalid_referer) {
        return 403;
        # 或返回防盗链提示图片
        # rewrite ^/.*$ /static/anti-hotlink.jpg break;
    }
    expires 30d;
}

$invalid_referer 变量:合法为 0,非法为 1。允许特定域名盗链:valid_referers none blocked server_names *.baidu.com;(多加一个域名)。


允许跨域

跨域问题根源:浏览器同源策略——协议、域名、端口三者任一不同,浏览器会阻止请求。同源策略不限制跨域请求的发送,而是丢弃跨域请求的响应包。目标站点可通过响应头声明”我允许这个跨域请求”,浏览器就会放行响应。

前后端分离架构(前端和后端独立部署,通过 API 通信)是跨域的主要场景。

前后端开发模式

模式代码形态优点缺点
前后端混合前后端同包,一个端口部署简单、开发初期快耦合高、无法兼容多端
前后端分离前端静态包 + 后端 API解耦、多端复用、独立扩展需处理跨域、约定 API

分离部署的两种方式

同域部署(Nginx 统一代理,最常见):前端静态文件与后端 API 走同一域名,Nginx 按路径分发——/ 返回静态文件,/api 转发后端。无跨域问题、后端监听内网不暴露公网,适合中小项目;缺点 Nginx 单点故障、流量集中。

server {
    listen 80;
    server_name myapp.com;
 
    location / {
        root /var/www/html/;   # 前端静态文件
        index index.html;
    }
 
    location /api {
        proxy_pass http://内网地址:3000;   # 后端 API
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

跨域部署(前后端独立域名):前端 front.myapp.com(CDN/Nginx 静态)、后端 api.myapp.com,后端必须配置 CORS。完全解耦、前端可上 CDN 独立扩展,适合大型项目;缺点需双域名+CORS+证书、后端暴露公网需额外防护。

对比项同域部署跨域部署
部署复杂度较低较高(双域名+CORS+证书)
跨域问题无需后端配置 CORS
扩展性耦合高,整体扩展耦合低,独立扩展
适用场景中小项目快速部署大型项目独立优化
安全性后端隐藏内网后端暴露公网,建议 Nginx 防护
location /api/ {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
    add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
    add_header Access-Control-Allow-Credentials true;
 
    # 处理 OPTIONS 预检请求
    if ($request_method = 'OPTIONS') {
        return 204;
    }
 
    proxy_pass http://backend_servers;
}
响应头作用
Access-Control-Allow-Origin允许哪些域名访问(* 表示全部)
Access-Control-Allow-Methods允许哪些 HTTP 方法
Access-Control-Allow-Headers允许哪些请求头
Access-Control-Allow-Credentials是否允许携带 Cookie

生产环境建议将 * 替换为具体域名以增强安全性。

CSRF 与跨域的关系

CSRF(跨站请求伪造)利用浏览器自动携带 Cookie 的特性,伪装用户发请求。同源策略防不了 CSRF——因为它限制的是读取响应,不是发送请求。有效防御:服务端生成 CSRF token,请求时校验。

// CSRF 攻击示例:恶意网站用 img 标签向银行发转账请求
// 浏览器自动带上银行网站的 cookie,等同以用户身份操作
var img = new Image();
img.src = "https://www.mybank.com/transfer?acc=badguy&amount=10000";

CPU 亲和

将 Nginx 的 worker 进程固定绑定到特定 CPU 核心,避免进程在多个 CPU 之间频繁切换。

好处:

  • 减少进程切换开销
  • 高效利用 CPU 缓存(L1/L2 缓存数据始终有效)
  • 降低内存访问延迟(绑定到同一 NUMA 节点)

坏处: 运行计算密集型任务时,某个 CPU 会被持续占用,其他 worker 可能长时间得不到 CPU,整体效率反而下降。

worker_processes auto;
worker_cpu_affinity auto;   # 自动绑定(Nginx 1.9.10+)
 
# 手动绑定示例(4 核 CPU)
# worker_processes 4;
# worker_cpu_affinity 0001 0010 0100 1000;
# worker1→CPU0, worker2→CPU1, worker3→CPU2, worker4→CPU3

适用场景:高并发 Web 服务。不适用:计算密集型任务。


相关页面