NGINX (从入门到精通)

  • 时间:2025-11-28 23:01 作者: 来源: 阅读:7
  • 扫一扫,手机访问
摘要:Day 1 — 基础概念 1. 什么是 Nginx 事件驱动 (Event-driven): 使用异步非阻塞模型,通过事件循环处理大量连接,效率高。高并发 (High Concurrency): 能够同时处理成千上万的并发连接,而不消耗大量资源。反向代理 (Reverse Proxy): 接收客户端请求,将请求转发给后端服务器,并返回响应。静态服务器 (Static Server): 可以直接返回

Day 1 — 基础概念

1. 什么是 Nginx

事件驱动 (Event-driven):
使用异步非阻塞模型,通过事件循环处理大量连接,效率高。高并发 (High Concurrency):
能够同时处理成千上万的并发连接,而不消耗大量资源。反向代理 (Reverse Proxy):
接收客户端请求,将请求转发给后端服务器,并返回响应。静态服务器 (Static Server):
可以直接返回静态文件(HTML、CSS、JS、图片等)给客户端。

2. Nginx 基本架构

Nginx 核心架构包含三个主要部分:

Master 进程

管理 Worker 进程读取配置文件信号控制(启动、停止、重载)

Worker 进程

处理实际客户端请求事件驱动模型(epoll / kqueue / select)

模块化设计

通过模块扩展功能,如 HTTP、Stream、Mail 模块等

3. Nginx 主要模块

模块类型功能
http提供 HTTP/HTTPS 服务,可作为静态服务器、反向代理、负载均衡等
stream提供 TCP/UDP 转发和负载均衡
mail提供 SMTP/POP3/IMAP 邮件代理服务
event事件处理模块,管理连接的异步事件

4. 启动、停止、重载


# 启动 Nginx
sudo nginx

# 停止 Nginx
sudo nginx -s stop

# 平滑重载配置(不中断服务)
sudo nginx -s reload

# 查看 Nginx 是否运行
ps -ef | grep nginx

5. 配置文件结构(nginx.conf)

主配置文件路径:通常 /etc/nginx/nginx.conf /usr/local/nginx/conf/nginx.conf主要块结构

user  nginx;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}

关键点

events:处理连接相关配置 http:处理 HTTP 请求配置 server:虚拟主机配置 location:请求路径处理规则

练习

安装 Nginx

# CentOS / RHEL
sudo yum install nginx -y

# Ubuntu / Debian
sudo apt update
sudo apt install nginx -y

# Docker
docker run -d -p 80:80 nginx
启动 Nginx 并访问首页

sudo systemctl start nginx       # 启动
sudo systemctl enable nginx      # 开机自启
firefox http://localhost         # 浏览器访问
验证配置文件

sudo nginx -t # 检查配置文件是否正确

Day 2 — 常用配置

1. server 块与 location

server 块

定义一个虚拟主机可以配置监听端口、域名等

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
}

location 块

定义路径匹配规则用于处理不同请求路径的具体行为

location /images/ {
    root /var/www/static;
}

location /api/ {
    proxy_pass http://127.0.0.1:8080;
}

2. 静态文件服务

Nginx 可以直接返回静态文件,如 HTML、CSS、JS、图片等配置示例:

server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

3. alias vs root

指令作用注意事项
root指定请求路径的根目录location 中路径会追加到 root 后
alias指定请求路径对应的目录location 中路径会被替换,不追加
示例:

# 使用 root
location /static/ {
    root /var/www/html;
    # /static/img.jpg => /var/www/html/static/img.jpg
}

# 使用 alias
location /static/ {
    alias /var/www/html/static-files/;
    # /static/img.jpg => /var/www/html/static-files/img.jpg
}

4. 日志格式

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"';

access_log /var/log/nginx/access.log main;

error_log

记录错误日志

error_log /var/log/nginx/error.log warn;

5. 配置测试命令

测试配置文件语法是否正确:

sudo nginx -t
输出示例:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

练习

配置一个静态资源网站

server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html/my_site;
        index index.html;
    }
}
创建静态目录并放置 HTML 文件:

mkdir -p /usr/share/nginx/html/my_site
echo "<h1>Hello Nginx!</h1>" > /usr/share/nginx/html/my_site/index.html
自定义 access_log 格式

log_format mylog '$remote_addr - $remote_user [$time_local] "$request" '
                 '$status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/my_access.log mylog;
测试配置并重载

sudo nginx -t       # 测试配置
sudo nginx -s reload # 重载配置

Day 3 — location 深入

1. location 匹配方式

Nginx 的 location 块匹配请求路径时,有几种方式:

1.1 精确匹配 =
完全匹配请求 URI

location = /index.html {
    root /var/www/html;
}
只有请求 /index.html 才会命中该 location。
1.2 前缀匹配(默认)
匹配 URI 开头部分

location /images/ {
    root /var/www/html;
}
请求 /images/pic.jpg 会匹配。
1.3 正则匹配 ~ / ~*
~:区分大小写的正则匹配 ~*:不区分大小写的正则匹配

location ~ .php$ {
    fastcgi_pass 127.0.0.1:9000;
}

2. 匹配优先级

匹配顺序如下:

精确匹配 =前缀匹配 ^~(表示匹配到该前缀就停止搜索正则)正则匹配 ~ / ~*(按配置顺序匹配)普通前缀匹配(最长前缀优先)

示意表:

类型示例优先级
精确匹配 = /index.html最高
前缀匹配 ^~ /images/
正则匹配 ~ .php$
普通前缀 /最低

3. rewrite 重写规则

3.1 return
直接返回响应或重定向

# 返回 301 重定向
location /old {
    return 301 /new;
}
3.2 rewrite
改写请求 URI 并可重定向

location /blog/ {
    rewrite ^/blog/(.*)$ /newblog/$1 permanent;
}

常用标志:

last:内部跳转,继续匹配 location break:停止 rewrite,直接在当前 location 执行 permanent:301 永久重定向 redirect:302 临时重定向

练习

写一个路径跳转规则

server {
    listen 80;
    server_name localhost;

    # 跳转 /old -> /new
    location /old {
        return 301 /new;
    }

    location /new {
        root /usr/share/nginx/html;
        index index.html;
    }
}
设计 3 个 location 测试优先级

server {
    listen 80;
    server_name localhost;

    # 精确匹配
    location = /test.html {
        return 200 "Exact match!";
    }

    # 前缀匹配
    location ^~ /static/ {
        return 200 "Prefix match!";
    }

    # 正则匹配
    location ~ .php$ {
        return 200 "Regex match!";
    }

    # 普通前缀匹配
    location / {
        return 200 "Default match!";
    }
}
测试方法:

curl http://localhost/test.html   # 精确匹配
curl http://localhost/static/file # 前缀匹配
curl http://localhost/index.php   # 正则匹配
curl http://localhost/anything    # 普通前缀匹配

Day 4 — 反向代理基础

1. proxy_pass 的工作原理

proxy_pass 用于将客户端请求转发到后端服务器(HTTP/TCP)工作流程: 客户端发起请求 → Nginx 接收根据 location 规则匹配 → 将请求转发给后端 upstreamNginx 接收后端响应 → 返回给客户端 示例:

location /api/ {
    proxy_pass http://127.0.0.1:8080;
}

2. upstream 基础

定义一组后端服务器,实现负载均衡

upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

server {
    listen 80;
    location /api/ {
        proxy_pass http://backend;
    }
}

常用负载均衡策略:

轮询(默认):轮流分配请求least_conn:最少连接数ip_hash:基于客户端 IP 分配,保证同一用户请求固定节点

3. Host / X-Real-IP / X-Forwarded-For

Host:客户端请求的域名,默认转发时保持原 Host

X-Real-IP:记录客户端真实 IP

X-Forwarded-For:记录经过的代理链路 IP

配置示例:


location /api/ {
    proxy_pass http://backend;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

4. keepalive 原理

目的:复用 TCP 连接,减少频繁建立/关闭连接的开销应用在 upstream

upstream backend {
    server 127.0.0.1:8080;
    keepalive 16;  # 最多保持 16 个空闲连接
}

server {
    listen 80;
    location /api/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

练习:配置一个反向代理 + 保留真实 IP

upstream 定义

upstream myapp {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    keepalive 16;
}
server & location 配置

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://myapp;
        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_http_version 1.1;
        proxy_set_header Connection "";
    }
}
重载 Nginx

sudo nginx -t       # 测试配置
sudo nginx -s reload # 重载生效
验证

curl -i http://localhost/
查看后端日志,确认能收到客户端真实 IP。

Day 5 — 负载均衡算法

1. round_robin(默认)

原理:按顺序轮流将请求分配给每个后端节点特点:简单,适合后端性能均衡的场景

upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

2. ip_hash

原理:根据客户端 IP 计算哈希值,固定访问同一个后端特点:保证同一用户的请求始终分配到同一节点(session 粘性)

upstream backend {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

3. least_conn

原理:将请求分配给当前连接数最少的节点特点:适合请求处理时间差异大的场景

upstream backend {
    least_conn;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

4. 一致性哈希(第三方模块)

原理:通过哈希算法,将相同 key 映射到同一个后端节点特点:适合缓存场景,保证 key 数据的稳定性实现:需要第三方 Nginx 模块,如 nginx-upstream-hash

upstream backend {
    hash $request_uri consistent;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

练习:配置一个 upstream,测试三种负载均衡方式

轮询(round_robin)

upstream myapp {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

server {
    listen 80;
    location / {
        proxy_pass http://myapp;
    }
}
测试:

curl http://localhost/  # 多次请求,轮流访问不同节点
IP 哈希(ip_hash)

upstream myapp {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}
测试:

curl http://localhost/  # 相同客户端 IP 总是访问同一节点
最少连接(least_conn)

upstream myapp {
    least_conn;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}
测试:

# 模拟多个请求,观察分配给连接最少的节点


Day 6 — Nginx 缓存机制

1. proxy_cache

作用:缓存后端服务器的响应,减少重复请求,提高性能配置步骤: 定义缓存路径:

proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
levels=1:2:缓存目录分层 keys_zone=my_cache:10m:缓存区域名称 + 内存大小 max_size:最大缓存大小 inactive:多久未访问被删除 在 location 中启用缓存:

location /api/ {
    proxy_pass http://backend;
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m;  # 状态码 200/302 缓存 10 分钟
    proxy_cache_valid 404 1m;       # 404 缓存 1 分钟
}

2. expires

作用:为客户端设置缓存时间(浏览器端缓存)示例

location /images/ {
    root /var/www/html;
    expires 30d;  # 浏览器缓存 30 天
}
也可以使用 modified

expires modified 7d;  # 文件修改后 7 天缓存

3. etag / cache-control

ETag:标识资源版本,浏览器可基于 ETag 判断资源是否更新

etag on;
Cache-Control:控制浏览器缓存行为

add_header Cache-Control "public, max-age=2592000";  # 30 天

练习:配置静态图片缓存

创建缓存目录

mkdir -p /tmp/nginx_cache
nginx.conf 配置

http {
    proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=img_cache:10m max_size=500m inactive=30m use_temp_path=off;

    server {
        listen 80;
        server_name localhost;

        # 静态图片缓存
        location /images/ {
            root /usr/share/nginx/html;
            expires 30d;
            add_header Cache-Control "public, max-age=2592000";
        }

        # 动态接口缓存
        location /api/ {
            proxy_pass http://127.0.0.1:8080;
            proxy_cache img_cache;
            proxy_cache_valid 200 10m;
            proxy_cache_valid 404 1m;
            proxy_cache_use_stale error timeout updating;
        }
    }
}
重载配置

sudo nginx -t
sudo nginx -s reload
验证 静态图片请求:

curl -I http://localhost/images/pic.jpg
# 查看 Cache-Control 和 Expires
动态接口请求:

curl -I http://localhost/api/data
# 查看 X-Cache-Status 是否命中缓存


Day 7 — 健康检查与超时

1. 超时配置

Nginx 代理请求时,可以设置各种超时,防止长时间阻塞。

指令作用示例
proxy_connect_timeout与后端建立 TCP 连接的超时时间 proxy_connect_timeout 5s;
proxy_send_timeout向后端发送请求的超时时间 proxy_send_timeout 10s;
proxy_read_timeout读取后端响应的超时时间 proxy_read_timeout 30s;
注意:超时只计算连接/发送/读取操作的等待时间,不是整个请求的总时间。

2. upstream 健康检查

目的:检测后端节点状态,避免将请求发送到不可用节点Nginx 开源版:可使用 max_fails + fail_timeout 简单健康检查

upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
}
Nginx Plus:提供主动健康检查模块,可定期探测节点可用性

3. 失败重试

使用 proxy_next_upstream 指令,失败时切换到其他节点

location /api/ {
    proxy_pass http://backend;
    proxy_connect_timeout 5s;
    proxy_send_timeout 10s;
    proxy_read_timeout 30s;

    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_next_upstream_tries 3;
}

常用参数:

error:连接错误 timeout:连接超时 invalid_header:响应头无效 http_5xx:后端返回 5xx 错误

练习:配置超时与失败重试

定义 upstream

upstream backend {
    server 127.0.0.1:8080 max_fails=2 fail_timeout=10s;
    server 127.0.0.1:8081 max_fails=2 fail_timeout=10s;
}
server 配置

server {
    listen 80;
    server_name localhost;

    location /api/ {
        proxy_pass http://backend;
        proxy_connect_timeout 5s;
        proxy_send_timeout 10s;
        proxy_read_timeout 30s;

        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
        proxy_next_upstream_tries 3;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
重载配置

sudo nginx -t
sudo nginx -s reload
验证 模拟一个后端挂掉:

curl -i http://localhost/api/  # Nginx 会自动切换到可用节点
查看 Nginx 日志:

tail -f /var/log/nginx/error.log
日志会显示尝试切换节点的记录

Day 8 — HTTPS

1. 申请证书(Let’s Encrypt)

Let’s Encrypt 提供免费的 SSL/TLS 证书推荐使用 Certbot 自动申请和更新证书

# Ubuntu / Debian 安装 Certbot
sudo apt update
sudo apt install certbot python3-certbot-nginx -y

# 申请证书
sudo certbot --nginx -d example.com -d www.example.com

Certbot 会自动修改 Nginx 配置,并设置自动续期

证书默认路径:

/etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem

2. ssl_certificate / ssl_protocols

配置 HTTPS:

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        root /var/www/html;
        index index.html;
    }
}
ssl_protocols:指定支持的 TLS 协议版本ssl_ciphers:指定加密算法套件

3. HSTS(HTTP Strict Transport Security)

强制浏览器使用 HTTPS,防止降级攻击

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

说明:

max-age=31536000:缓存 1 年 includeSubDomains:包含子域名 preload:可加入浏览器 HSTS 预加载列表

4. 443/80 兼容配置(HTTP 跳转 HTTPS)


# HTTP 跳转到 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

练习:将一个网站完整升级 HTTPS

安装 Certbot 并申请证书:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
检查 Nginx 配置:

sudo nginx -t
重载 Nginx:

sudo nginx -s reload
验证:

curl -I https://example.com
# 应该返回 200,并且使用 HTTPS
可选:手动配置 HSTS

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
浏览器访问后,HTTP 请求会自动跳转 HTTPSCertbot 会自动设置定期续期:

sudo systemctl status certbot.timer

Day 9 — WebSocket 代理

1. WebSocket 代理配置原理

WebSocket 需要 HTTP 升级 (Upgrade),使用 proxy_http_version 1.1

Nginx 默认是 HTTP/1.0,需要设置 HTTP/1.1 来支持长连接

关键头部:

Upgrade: websocket Connection: Upgrade

2. Nginx 配置示例

假设后端 WebSocket 服务地址: ws://localhost:12333


map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name localhost;

    location /ws/ {
        proxy_pass http://localhost:12333;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
map 指令确保 Connection 头在 Upgrade 时正确设置 proxy_set_header 保留客户端真实 IP 和 Host

3. 常见 400 / 502 错误排查

错误原因解决方案
400 Bad RequestUpgrade 或 Connection 头未正确设置检查 $http_upgrade $connection_upgrade 配置
502 Bad Gateway后端服务未启动或端口错误确认 WebSocket 服务正常运行,端口与 proxy_pass 匹配
长时间无响应proxy_read_timeout 太短增加 proxy_read_timeout,如 60s

练习:配置 WebSocket 代理

后端 WebSocket 服务

# 假设一个简单 WebSocket 服务运行在 12333 端口
node websocket_server.js
Nginx 配置

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name localhost;

    location /ws/ {
        proxy_pass http://localhost:12333;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
重载 Nginx

sudo nginx -t
sudo nginx -s reload
测试

// 浏览器或 Node.js 测试客户端
const ws = new WebSocket('ws://localhost/ws/');
ws.onopen = () => console.log('Connected');
ws.onmessage = (msg) => console.log('Message:', msg.data);
确认客户端能正常连接并收发消息查看 Nginx 日志排查可能的 400 / 502 问题

Day 10 — 跨域 CORS & 安全头

1. add_header 详解

用于在响应中添加 HTTP 头基本语法:

add_header name value [always];
always 参数确保即使响应码非 200 也添加头

2. 常见安全头

头部作用示例
X-Frame-Options防止页面被 iframe 嵌套点击劫持 add_header X-Frame-Options SAMEORIGIN;
Strict-Transport-Security (HSTS)强制浏览器使用 HTTPS add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
X-Content-Type-Options阻止 MIME 类型嗅探 add_header X-Content-Type-Options nosniff;
Content-Security-Policy内容安全策略 add_header Content-Security-Policy "default-src 'self';";

3. CORS(跨域资源共享)

允许指定来源访问后端资源Nginx 配置示例:

location /api/ {
    proxy_pass http://backend;

    add_header Access-Control-Allow-Origin https://example.com;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";

    # 处理 preflight 请求
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Max-Age 1728000;
        add_header Content-Type text/plain;
        return 204;
    }
}

说明:

Access-Control-Allow-Origin:允许访问的域名 Access-Control-Allow-Methods:允许请求方法 Access-Control-Allow-Headers:允许请求头 OPTIONS 请求为浏览器预检请求

练习:配置跨域后端代理

upstream 后端

upstream backend {
    server 127.0.0.1:8080;
}
server 配置

server {
    listen 80;
    server_name localhost;

    location /api/ {
        proxy_pass http://backend;

        # 保留客户端真实 IP
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # CORS 配置
        add_header Access-Control-Allow-Origin https://client.example.com;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";

        if ($request_method = 'OPTIONS') {
            add_header Access-Control-Max-Age 1728000;
            add_header Content-Type text/plain;
            return 204;
        }

        # 安全头
        add_header X-Frame-Options SAMEORIGIN;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-Content-Type-Options nosniff;
    }
}
重载 Nginx

sudo nginx -t
sudo nginx -s reload
验证 浏览器端 JS 测试跨域访问:

fetch('http://localhost/api/data')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));
确认来自 https://client.example.com 的请求可以访问查看响应头是否包含 Access-Control-Allow-Origin 和安全头

Day 11 — Rate Limit 限流

1. 限流指令

指令作用示例
limit_req_zone定义请求限流的 key 和速率 limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_req在 location 中应用请求限流 limit_req zone=one burst=5 nodelay;
limit_conn_zone定义连接数限制的 key limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn在 location/server 中应用连接数限制 limit_conn addr 5;
$binary_remote_addr:以客户端 IP 为 keyrate:请求速率burst:突发允许请求数nodelay:超过 burst 不延迟,直接拒绝

2. 限流算法

令牌桶算法(Token Bucket):

每秒生成固定速率令牌请求消耗令牌,令牌用完则拒绝或等待

limit_req 默认使用令牌桶算法


3. 实战:请求超过 20/s 返回 503


# 定义限流 zone
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;

server {
    listen 80;
    server_name localhost;

    location /api/ {
        proxy_pass http://backend;

        # 应用限流
        limit_req zone=one burst=5 nodelay;

        # 保留客户端真实 IP
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
超过速率 20r/s,直接返回 503 Service Unavailable

练习:为后端服务加一个 10r/s 限流

定义限流 zone

limit_req_zone $binary_remote_addr zone=my_limit:10m rate=10r/s;
在 location 中应用

server {
    listen 80;
    server_name localhost;

    location /api/ {
        proxy_pass http://backend;

        # 限流
        limit_req zone=my_limit burst=5 nodelay;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
重载 Nginx

sudo nginx -t
sudo nginx -s reload
验证 使用 ab wrk 等压测工具模拟请求:

ab -n 50 -c 20 http://localhost/api/
观察超过 10r/s 后请求返回 503

Day 12 — 性能调优

1. worker_processes 自动

作用:定义 Nginx 工作进程数,处理请求建议设置为 CPU 核心数或 auto

worker_processes auto;
每个 worker 独立处理事件,不共享请求

2. worker_connections

作用:每个 worker 能处理的最大连接数理论最大并发 = worker_processes × worker_connections

events {
    worker_connections 10240;
    use epoll;  # Linux 推荐 epoll
}

3. epoll 和事件驱动模型

事件驱动:单进程非阻塞处理大量连接epoll(Linux)高性能 I/O 多路复用机制常用配置:

events {
    worker_connections 10240;
    use epoll;
    multi_accept on;  # 一次接受多个连接
}

4. sendfile、tcp_nopush、tcp_nodelay

sendfile:直接在内核空间传输文件,减少用户态拷贝tcp_nopush:延迟发送 TCP 包,提高吞吐量(适合大文件)tcp_nodelay:立即发送小包(减少延迟)

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    client_max_body_size 50M;
}

练习:调优 Nginx 支持 10w QPS 基础配置


# nginx.conf
worker_processes auto;

events {
    worker_connections 65536;
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    client_max_body_size 50M;

    server {
        listen 80;
        server_name localhost;

        location / {
            root /var/www/html;
            index index.html;
        }

        location /api/ {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

说明:

worker_processes auto → 利用多核 CPU worker_connections 65536 → 每 worker 高并发 epoll + multi_accept → 高效事件处理 sendfile + tcp_nopush + tcp_nodelay → 高吞吐与低延迟

理论最大并发 = worker_processes × worker_connections


验证方法:


ab -n 100000 -c 1000 http://localhost/
wrk -t12 -c1000 -d30s http://localhost/api/
检查是否能支撑高并发请求,CPU 和网络利用率合理

Day 13 — 日志与排错

1. 如何读 error.log

Nginx 日志分为:

access.log:记录客户端请求信息error.log:记录错误、告警、异常信息

日志等级

debug / info / notice / warn / error / crit

查看日志:


# 实时查看
tail -f /var/log/nginx/error.log
# 查看最近 100 条
tail -n 100 /var/log/nginx/error.log
日志示例

[error] 1234#0: *45 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.10, server: localhost, request: "GET /api/ HTTP/1.1", upstream: "http://127.0.0.1:8080/api/", host: "localhost"

分析思路:

日志等级(error、warn)client IPupstream 地址错误原因(Connection refused、timeout 等)

2. 常见 HTTP 错误排查

状态码常见原因排查方法
403 Forbidden权限/目录配置不当检查 root/alias,文件权限,SELinux
404 Not FoundURL 或路径不存在检查 location 配置、文件路径、alias/root 使用
500 Internal Server Error后端错误或脚本异常检查后端服务、PHP/CGI 日志
502 Bad Gateway后端服务不可用检查 upstream 是否启动,端口正确,超时
504 Gateway Timeout后端响应超时检查 proxy_read_timeout、后端处理性能

3. upstream 超时与负载均衡异常排查

常见日志:

connect() failed (111: Connection refused) while connecting to upstream
upstream timed out (110: Connection timed out)

排查步骤:

确认 upstream 节点是否运行检查防火墙 / SELinux检查端口和 IP 配置是否正确查看 proxy_connect_timeout proxy_read_timeout 配置检查负载均衡策略,是否某节点压力过大

练习:制作“常见错误排查手册”

创建文档 nginx_error_guide.md

# Nginx 常见错误排查手册

## 1. 403 Forbidden
- 原因:
  - 文件/目录权限不足
  - alias/root 配置错误
  - SELinux 限制
- 解决:
  - `chmod 755 /var/www/html`
  - 检查 alias 路径是否正确
  - `setenforce 0` 测试 SELinux

## 2. 404 Not Found
- 原因:
  - location 未匹配
  - 文件路径不存在
- 解决:
  - 检查 root/alias
  - 确认文件存在
  - 使用 `nginx -T` 查看最终配置

## 3. 500 Internal Server Error
- 原因:
  - 后端应用出错
- 解决:
  - 查看后端日志
  - 检查脚本权限

## 4. 502 Bad Gateway
- 原因:
  - upstream 未启动
  - 端口错误
- 解决:
  - 启动后端服务
  - 检查 proxy_pass 地址
  - 检查防火墙/SELinux

## 5. 504 Gateway Timeout
- 原因:
  - 后端响应慢
- 解决:
  - 增加 `proxy_read_timeout`
  - 优化后端处理性能

## 6. upstream 异常
- 查看 error.log,判断节点拒绝或超时
- 检查负载均衡策略
- 使用 `curl` 测试单个节点
保存并随时更新,形成个人 Nginx 排错手册日常遇到新问题,记录原因与解决方案,逐渐完善

Day 14 — 实战项目:完整生产案例

目标:搭建一个生产环境级 Nginx,包含 HTTPS、WebSocket、负载均衡、静态资源、限流、日志定制与性能调优。


1. 基础性能调优


worker_processes auto;

events {
    worker_connections 65536;
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    client_max_body_size 50M;

    include       mime.types;
    default_type  application/octet-stream;

    # 日志定制
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;

    # 限流
    limit_req_zone $binary_remote_addr zone=my_limit:10m rate=10r/s;

2. upstream 负载均衡 + 健康检查


    upstream backend {
        server 127.0.0.1:8080 max_fails=2 fail_timeout=10s;
        server 127.0.0.1:8081 max_fails=2 fail_timeout=10s;
        least_conn;  # 可选:least_conn 或 ip_hash
    }

3. HTTPS 配置


    server {
        listen 443 ssl;
        server_name example.com www.example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        # 静态资源
        location /static/ {
            root /var/www/html;
            expires 30d;
            add_header Cache-Control "public, max-age=2592000";
        }

        # API 代理
        location /api/ {
            proxy_pass http://backend;
            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_connect_timeout 5s;
            proxy_send_timeout 10s;
            proxy_read_timeout 30s;
            proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
            proxy_next_upstream_tries 3;

            # 限流
            limit_req zone=my_limit burst=5 nodelay;

            # CORS(可选)
            add_header Access-Control-Allow-Origin https://client.example.com;
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
            add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";

            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Max-Age 1728000;
                add_header Content-Type text/plain;
                return 204;
            }
        }

        # WebSocket 代理
        location /ws/ {
            proxy_pass http://localhost:12333;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }

    # HTTP 跳转到 HTTPS
    server {
        listen 80;
        server_name example.com www.example.com;
        return 301 https://$host$request_uri;
    }
}

4. 功能点总结

功能配置说明
HTTPSSSL 证书 + HSTS
WebSocket proxy_http_version 1.1 + Upgrade/Connection
负载均衡upstream + least_conn / ip_hash
静态资源 /static/ + expires + Cache-Control
限流 limit_req_zone + limit_req
日志定制自定义 log_format + access_log/error_log
性能调优worker_processes、worker_connections、epoll、sendfile、tcp_nopush、tcp_nodelay

5. 部署与验证

检查配置

sudo nginx -t
重载 Nginx

sudo nginx -s reload
验证 HTTPS: curl -I https://example.comWebSocket:测试 /ws/ 连接API:请求 /api/,检查限流、负载均衡静态资源:访问 /static/,检查缓存头日志:查看 access.log error.log

这样就构建了一个 生产级 Nginx 案例,可以支撑高并发、支持 HTTPS/WebSocket,同时具备安全、限流、负载均衡和性能优化。


Nginx 面试题(50 道)

基础概念与架构(1-10)

Nginx 是什么?

高性能 HTTP / 反向代理服务器,事件驱动、高并发

Nginx 的主要模块有哪些?

http、stream、mail、event

Nginx 的事件驱动模型是什么?

单进程异步非阻塞 I/O

worker_processes 和 worker_connections 的作用?

控制并发能力:worker_processes × worker_connections

Nginx 如何实现高并发?

epoll + 异步事件驱动 + 多进程

Nginx 的 master 与 worker 关系?

master 管理配置和 worker,worker 处理请求

Nginx 配置文件结构有哪些?

nginx.conf、conf.d/.conf、sites-enabled/.conf

如何启动、停止、重载 Nginx?

nginx / nginx -s stop / nginx -s reload

Nginx 与 Apache 区别?

Apache 进程/线程模式,Nginx 事件驱动;Nginx 更适合高并发

Nginx 支持哪些协议?

HTTP、HTTPS、WebSocket、TCP/UDP(stream)

server 与 location 配置(11-20)

server 块和 location 块的区别?

server 控制域名监听,location 控制 URI 路径匹配

root 与 alias 区别?

root 拼接 location,alias 直接替换路径

location 匹配规则优先级?

精确 =,前缀 ^~,正则 /*,普通前缀

rewrite 指令作用?

重写 URL,可 return 或 rewrite

如何配置静态文件服务?

root/alias + index + location

access_log 格式如何自定义?

log_format 指令

如何测试 Nginx 配置?

nginx -t

如何实现 HTTP 跳转 HTTPS?

server listen 80 + return 301

如何配置 gzip 压缩?

gzip on; gzip_types text/html text/css application/json;

如何限制客户端请求体大小?

client_max_body_size

反向代理与负载均衡(21-30)

proxy_pass 的作用?

将请求代理到后端服务器

如何保留客户端真实 IP?

proxy_set_header X-Real-IP $remote_addr;

upstream 配置作用?

定义后端服务器组

Nginx 支持哪些负载均衡策略?

round-robin、ip_hash、least_conn、一致性哈希(第三方)

proxy_connect_timeout 与 proxy_read_timeout 区别?

连接超时 vs 响应读取超时

proxy_next_upstream 有哪些参数?

error、timeout、http_500、http_502、http_503、http_504

如何实现失败重试?

proxy_next_upstream + proxy_next_upstream_tries

upstream max_fails + fail_timeout 作用?

简单健康检查

如何实现 WebSocket 代理?

proxy_http_version 1.1 + Upgrade/Connection

如何做请求限流?

limit_req_zone + limit_req

缓存与性能优化(31-40)

proxy_cache 的作用?

缓存后端响应,提高访问速度

expires 与 cache-control 区别?

expires 客户端缓存时间,cache-control 更灵活

etag 的作用?

验证资源是否被修改

sendfile 的作用?

零拷贝传输文件

tcp_nopush 与 tcp_nodelay 区别?

nopush 延迟发送,提高吞吐;nodelay 减少小包延迟

keepalive 的作用?

保持长连接,提高性能

worker_processes auto 为什么推荐?

自动使用 CPU 核心数

multi_accept 指令作用?

一次接受多个连接,提高并发处理效率

Nginx 如何实现高并发 QPS ?

worker_processes × worker_connections + epoll + sendfile/tcp优化

如何监控 Nginx 性能瓶颈?

stub_status、日志分析、top/htop/netstat

安全与跨域(41-50)

如何启用 HTTPS?

ssl_certificate + ssl_certificate_key + listen 443 ssl

HSTS 的作用?

强制浏览器使用 HTTPS

X-Frame-Options 的作用?

防止点击劫持

X-Content-Type-Options nosniff 作用?

阻止 MIME 类型嗅探

Content-Security-Policy 用途?

限制页面加载资源来源

CORS 如何配置?

add_header Access-Control-Allow-Origin + 方法/头

如何防止频繁请求攻击?

limit_req + limit_conn

Nginx error.log 中 502 错误排查?

后端未启动、端口错、超时

Nginx error.log 中 504 错误排查?

后端响应慢,调整 proxy_read_timeout

常用安全加固措施有哪些?

HTTPS、HSTS、X-Frame-Options、CSP、限流、日志监控
  • 全部评论(0)
手机二维码手机访问领取大礼包
返回顶部