云计算百科
云计算领域专业知识百科平台

上章节中文件的讲解

目录

配置文件

1、nginx.conf

2、lab.conf:定义后端服务器组


配置文件

两个配置文件的关系可以把它们理解成:

  • nginx.conf:公司的“总规章制度”
  • lab.conf:某个具体网站的“工作规则”

加载关系:

nginx.conf └── http     └── include /etc/nginx/conf.d/*.conf         └── lab.conf             ├── upstream             └── server                 └── location

nginx.conf 最后一行加载了 conf.d 目录中的配置,所以 lab.conf 实际上会被插入 http 块内。

1、nginx.conf

(1)详解

文件位置:conf/nginx.conf

① Worker 进程数量

worker_processes auto;

Nginx 通常有两类进程:

Master 主进程 ├── Worker 1 ├── Worker 2 ├── Worker 3 └── Worker 4

a. Master 进程

负责:

  • 读取配置
  • 创建 Worker
  • 接收 reload/stop 信号
  • 平滑更新配置

b. Worker 进程

负责:

  • 接收请求
  • 返回静态文件
  • 转发请求
  • 写日志

auto 表示让 Nginx 根据 CPU 数量自动决定 Worker 数量。

在 WSL 中,可以查看:podman exec nginx-lab ps

② 错误日志

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

含义是:

  • 错误日志路径:/var/log/nginx/error.log
  • 日志级别:warn

常见日志级别由详细到严重,大致为:

debug → info → notice → warn → error → crit → alert → emerg

使用 warn 时,会记录警告以及更严重的问题。

例如:

  • 后端连接失败
  • 后端响应超时
  • 请求被限流
  • 文件不存在
  • 配置或运行异常

项目把容器里的日志目录映射到了本机:

  • 容器:/var/log/nginx/
  • 本机:~/nginx-podman-lab/logs/

所以可以直接查看:tail -f ~/nginx-podman-lab/logs/error.log

③ PID 文件

pid /var/run/nginx.pid;

PID 是进程编号。

Nginx 把 Master 进程编号写到这个文件中,例如:26

当执行:nginx -s reload

Nginx 会通过 PID 找到 Master 进程,然后向它发送重新加载配置的信号。

一般不需要手动修改这一项。

④ events 块

events {
worker_connections 1024;
multi_accept on;
}

这里管理网络连接。

a. worker_connections 1024

表示每个 Worker 最多可以同时打开大约 1024 个连接。

假设有 4 个 Worker,理论连接上限大致为:

4 × 1024 = 4096

但不能简单地将它当成“最多 4096 个用户”,因为一次反向代理通常涉及两个连接:

用户 ←连接1→ Nginx ←连接2→ 后端

实际容量还会受到以下因素限制:

  • Linux 文件描述符上限
  • CPU
  • 内存
  • 后端处理能力
  • 长连接数量

本实验中的 1024 足够使用。

b. multi_accept on

当有很多新连接同时到来时,允许 Worker 一次接受多个连接。

大白话:

门口同时来了很多顾客,接待员可以连续接待,不必每次只领一个人。

生产环境中是否开启需要结合负载测试,本实验主要用于展示。

(2)http 块详细讲解

http {

}

所有普通 HTTP/HTTPS 网站配置通常都放在这里。

① 文件类型表

include /etc/nginx/mime.types;

default_type application/octet-stream;

a. mime.types

它告诉浏览器不同文件是什么类型:

.html → text/html

.css → text/css

.js → application/javascript

.png → image/png

如果没有正确类型,浏览器可能无法正常解析文件。

b. default_type

如果 Nginx 不认识某个文件扩展名,就使用:application/octet-stream

它表示:

这是一个普通二进制文件,具体类型不确定。

② 隐藏 Nginx 版本

server_tokens off;

默认错误页面或响应头可能显示:nginx/1.27.5

关闭后通常只显示:nginx

这样可以减少版本信息暴露。

但它只是基础安全设置,不代表服务器因此就绝对安全。

③ 高效发送文件

sendfile on;

tcp_nopush on;

a. sendfile on

普通发送文件过程可能是:磁盘 → 程序内存 → 网络

开启 sendfile 后,Linux 可以更高效地把文件数据交给网络层,减少不必要的数据复制。

适合:

  • HTML
  • CSS
  • JavaScript
  • 图片
  • 下载文件

b. tcp_nopush on

配合 sendfile 使用,尽量把数据凑成较完整的数据包后再发送。

大白话:

送货时尽量装满一车再发,而不是一个小包裹就发一辆车。

④ 客户端长连接

keepalive_timeout 65;

浏览器访问网页时,通常需要请求多个文件:

index.html

style.css

app.js

图片

如果没有长连接,每个文件可能都需要重新建立 TCP 连接。

开启 Keepalive 后:

建立一次连接

├── 请求 index.html

├── 请求 style.css

├── 请求 app.js

└── 暂时保留连接

65 表示连接空闲约 65 秒后关闭。

注意:这是客户端到 Nginx 的长连接设置,不是 Nginx 到后端的连接池。

⑤ 上传大小限制

client_max_body_size 10m;

客户端请求体最大为 10MB。

主要影响:

  • 文件上传
  • 大型 JSON
  • 表单提交

超过限制时,Nginx 通常返回:413 Request Entity Too Large

这是 http 级别的默认值,也可以在特定 server 或 location 中覆盖。

(3)Gzip 压缩

gzip on;

gzip_comp_level 5;

gzip_min_length 256;

gzip_types text/plain text/css application/json application/javascript application/xml text/xml;

① gzip on

开启响应压缩。

例如原本一个 CSS 文件有 100KB,压缩后可能只有 20KB。

过程如下:

Nginx 原始内容

         ↓ gzip 压缩

较小的数据

         ↓ 网络传输

浏览器自动解压

② gzip_comp_level 5

压缩等级为 5。

范围通常是 1~9:

  • 等级越高:文件可能越小
  • 等级越高:消耗的 CPU 越多

5 是比较平衡的实验值。

③ gzip_min_length 256

小于 256 字节的内容不压缩。

因为特别小的内容压缩收益很低,反而增加处理成本。

④ gzip_types

指定需要压缩的响应类型:

text/plain

text/css

application/json

application/javascript

application/xml

text/xml

图片一般不用再 gzip,因为 PNG、JPEG 等通常已经压缩。

验证是否压缩:

curl -I \\
-H 'Accept-Encoding: gzip' \\
http://127.0.0.1:18080/assets/style.css

如果生效,响应中可以看到:Content-Encoding: gzip

(4)限流区域

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;

这只是定义限流规则和存储区域,还没有真正应用到请求。

a. $binary_remote_addr

表示客户端 IP 的二进制形式。

Nginx 按 IP 分别计数:

IP 192.168.1.10 → 自己的计数

IP 192.168.1.11 → 自己的计数

使用二进制形式是为了节省内存。

b. zone=api_limit:10m

创建一个名为 api_limit 的共享内存区域,大小为 10MB。

Worker 进程会在这里共同记录:哪个 IP 最近发了多少请求

这里的 10m 不是“允许 10MB 流量”,而是用于保存限流状态的内存大小。

c. rate=5r/s

每个 IP 平均每秒允许 5 个请求。

真正使用这个规则的位置在 lab.conf:

limit_req zone=api_limit burst=10 nodelay;

可以理解成:

limit_req_zone → 创建限流器

limit_req → 在某个接口上启用限流器

(5)访问日志格式

log_format lab '$remote_addr – [$time_local] "$request" '
'status=$status '
'rt=$request_time '
'urt=$upstream_response_time '
'upstream=$upstream_addr '
'us=$upstream_status '
'ref="$http_referer" '
'ua="$http_user_agent"';

这里定义了一个名为 lab 的日志格式。

① $remote_addr

客户端 IP。

在 Podman实验里,可能看到容器网络地址。

② $time_local

Nginx 收到请求的时间。

③ $request

完整请求行,例如:GET /api/info HTTP/1.1

④ $status

Nginx 最终返回的状态码:

200 正常

404 地址不存在

413 上传过大

502 后端异常

503 限流或暂不可用

504 后端响应超时

⑤ $request_time

从 Nginx 收到请求,到发送完响应的总时间。

日志里写成:rt=0.015

表示整个请求用了 0.015 秒。

⑥ $upstream_response_time

后端响应耗时:urt=0.012

如果请求是静态文件,没有经过后端,通常显示 -。

⑦ $upstream_addr

请求交给了哪个后端:upstream=10.89.0.2:8000

⑧ $upstream_status

后端返回给 Nginx 的状态码。

例如:us=200

注意:

  • $status:Nginx 最终返回给用户的状态
  • $upstream_status:后端返回给 Nginx 的状态

二者不一定相同。

⑨ $http_referer

用户从哪个页面进入当前地址。

⑩ $http_user_agent

客户端信息,例如浏览器或 curl。

(6)启用访问日志

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

含义:

  • 日志写入 /var/log/nginx/access.log
  • 使用刚才定义的 lab 格式

查看:tail -f ~/nginx-podman-lab/logs/access.log

(7)加载网站配置

include /etc/nginx/conf.d/*.conf;

加载 conf.d 目录下所有 .conf 文件。

本实验通过 Podman 挂载后,加载的是:conf/conf.d/lab.conf

这种拆分方式可以让一个 Nginx 管理多个网站:

conf.d/

├── app.conf

├── api.conf

├── admin.conf

└── lab.conf

2、lab.conf:定义后端服务器组

upstream app_backend {
least_conn;
keepalive 16;
server backend-a:8000 weight=3 max_fails=2 fail_timeout=10s;
server backend-b:8000 weight=1 max_fails=2 fail_timeout=10s;
}

upstream 表示一组后端服务器。

名字是:app_backend

后面可以通过下面的写法使用它:proxy_pass http://app_backend;

(1)backend-a 和 backend-b 

它们是 Podman 容器名称。

三个容器加入了相同网络:nginx-lab-net

Podman 内部 DNS 会把:

backend-a → A 容器的内部 IP

backend-b → B 容器的内部 IP

所以 Nginx 不需要写死 IP。

(2)least_conn

least_conn;

表示优先把新请求交给当前连接较少的后端。

例如:

A 当前有 10 个连接

B 当前有 2 个连接

新请求通常更倾向于交给 B。

如果不写负载均衡算法,默认使用轮询。

(3)keepalive 16

keepalive 16;

让每个 Worker 最多保留一定数量的空闲上游长连接。

没有连接池时:每次请求 → 新建后端连接 → 请求结束 → 关闭

使用连接池后:建立连接 → 请求结束 → 暂时保留 → 后续请求复用

好处:

  • 减少 TCP 建连成本
  • 降低后端压力
  • 提高性能

这里还需要在反代位置使用:

proxy_http_version 1.1;

proxy_set_header Connection "";

否则连接复用可能无法按预期工作。

(4)后端定义

server backend-a:8000 weight=3 max_fails=2 fail_timeout=10s;

server backend-b:8000 weight=1 max_fails=2 fail_timeout=10s;

① weight

A 权重 3,B 权重 1。

大体上表示 A 承担更多流量,但因为这里同时使用了 least_conn,实际选择还会考虑当前连接数,并不能机械理解成每四个请求一定是 A、A、A、B。

② max_fails=2

如果在指定时间内连续发生一定数量的失败,Nginx 会暂时认为该节点不可用。

③ fail_timeout=10s

它有两个相关作用:

  • 统计失败的时间窗口
  • 达到失败次数后,暂时避开该节点约 10 秒

这属于被动健康检查:

先有真实请求失败

        ↓

Nginx 记录失败

        ↓

达到 max_fails

        ↓

暂时少选或不选该后端

它不是主动定时访问 /health 的健康检查。

(5)server:定义一个网站

server {
listen 80;
server_name localhost lab.local;
}

① listen 80

Nginx 容器内部监听 80 端口。

Podman做了端口映射:电脑 18080 → Nginx 容器 80

所以浏览器访问:http://127.0.0.1:18080

最终会到达容器的 80 端口。

② server_name

server_name localhost lab.local;

表示这个网站希望处理的域名是:

localhost

lab.local

本实验只有一个 server,因此使用 127.0.0.1 通常也会落到这里。

企业中可能有多个 server:

server_name api.company.com;

server_name admin.company.com;

server_name www.company.com;

Nginx 根据请求中的 Host 选择对应网站。

(6)健康检查 /healthz

location = /healthz {
access_log off;
default_type text/plain;
return 200 "ok\\n";
}

① location = /healthz

location 根据 URL 路径决定如何处理请求。

= 表示精确匹配:

/healthz → 匹配

/healthz/ → 不匹配

/healthz/test → 不匹配

精确匹配优先级非常高。

② access_log off

健康检查通常每几秒执行一次,如果全部记录,访问日志会出现大量无价值内容,所以这里关闭访问日志。

错误仍然可以进入错误日志。

③ default_type text/plain

告诉客户端返回内容是普通文本。

④ return 200 "ok\\n"

Nginx 直接返回:

HTTP 状态码:200

内容:ok

请求不会经过后端。

(7)静态网站

root /usr/share/nginx/html;

index index.html;

① root

设置静态文件根目录。

Podman把项目的 html 目录挂载到了:/usr/share/nginx/html

因此:

请求 /app.js

        → /usr/share/nginx/html/app.js

请求 /assets/style.css

        → /usr/share/nginx/html/assets/style.css

② index index.html

访问目录 / 时,默认查找:index.html

(8)try_files 和 SPA

location / {

try_files $uri $uri/ /index.html;

}

location / 是最宽泛的前缀匹配,大多数请求都能匹配它。

try_files 按顺序尝试:

  • $uri:有没有同名文件
  • $uri/:有没有同名目录
  • /index.html:都没有时返回首页
  • 例如请求:/assets/style.css

    Nginx 查到文件后直接返回。

    请求:/user/profile

    磁盘没有这个文件,于是返回:/index.html

    这适合 Vue、React 等单页应用,因为 /user/profile 可能是前端路由,不是真实文件。

    (9)静态资源缓存

    location /assets/ {
    expires 7d;
    add_header Cache-Control "public";
    access_log off;
    }

    这个规则匹配:

    • /assets/style.css
    • /assets/logo.png

    ① expires 7d

    告诉浏览器资源可以缓存 7 天。

    这样用户第二次访问时,可以直接使用本地缓存,减少请求。

    ② Cache-Control "public"

    表示该资源允许被浏览器、CDN 等公共缓存保存。

    ③ access_log off

    静态资源请求很多,实验中关闭日志以减少干扰。

    生产环境是否关闭,要根据审计和排障需求决定。

    (10)核心反向代理 /api/

    location /api/ {
    limit_req zone=api_limit burst=10 nodelay;
    proxy_pass http://app_backend/;

    }

    它匹配:

    • /api/info
    • /api/health
    • /api/slow

    ① 启用限流

    limit_req zone=api_limit burst=10 nodelay;

    使用 nginx.conf 中定义的:api_limit

    a. burst=10

    允许短时间额外突发约 10 个请求。

    可以理解成:

    • 正常速度:每秒 5 个
    • 临时允许一个小队列/桶承受突发
    • 超出后拒绝请求

    b. nodelay

    突发额度内的请求立即处理,不让它们排队慢慢等待。

    超过额度后,本实验通常返回 503。

    ② proxy_pass 尾斜杠

    proxy_pass http://app_backend/;

    这里末尾有 /。

    请求:/api/info

    转发给后端时变成:/info

    也就是 /api/ 前缀被替换成 /。

    这是本配置中非常重要的知识点。

    ③ 上游使用 HTTP/1.1

    proxy_http_version 1.1;
    proxy_set_header Connection "";

    默认情况下,上游连接可能不按预期保持。

    使用 HTTP/1.1 并清空 Connection 请求头,有助于复用前面 upstream 中配置的 Keepalive 连接。

    这里的空字符串表示:

    不要把这个请求头传给后端。

    (11)反向代理请求头

    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;

    ① Host $host

    告诉后端,用户访问的主机名是什么。

    例如:lab.local

    ② X-Real-IP $remote_addr

    告诉后端,Nginx 看到的客户端 IP 是什么。

    ③ X-Forwarded-For

    记录代理链路中的客户端 IP。

    例如:用户 → CDN → Nginx → 后端

    它可能类似:203.0.113.10, 10.0.0.5

    $proxy_add_x_forwarded_for 会保留已有内容,再追加当前客户端地址。

    ④ X-Forwarded-Proto $scheme

    告诉后端用户原本使用的协议:http

    如果以后增加 HTTPS,它可能是:https

    后端生成跳转地址、Cookie 或外部链接时经常需要它。

    (12)反向代理超时

    proxy_connect_timeout 3s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;

    ① proxy_connect_timeout

    Nginx 连接后端最多等待 3 秒。

    例如后端端口无法连接,等待超过时间后放弃。

    ② proxy_send_timeout

    Nginx 向后端发送请求数据时,连续写数据的等待超时。

    它并不是整个请求的绝对总时长。

    ③ proxy_read_timeout

    Nginx 等待后端返回数据的间隔超时。

    如果后端在指定时间内一直没有返回新数据,Nginx 会终止请求。

    普通 API 使用 30 秒只是实验值,生产中应该根据业务特点设置。

    (13)故意制造 504 的 /timeout/

    location /timeout/ {
    proxy_pass http://app_backend/;

    proxy_connect_timeout 1s;
    proxy_read_timeout 1s;
    }

    访问:/timeout/slow

    因为 proxy_pass 带尾斜杠,后端收到:/slow

    后端程序故意等待约 5 秒,但 Nginx 只允许连续等待 1 秒:

    后端等待 5 秒、Nginx 只等 1 秒 → 504 Gateway Timeout

    这里主要用来学习如何观察超时和错误日志,不能直接照搬到生产配置。

    (14)/raw/ 演示尾斜杠区别

    location /raw/ {
    proxy_pass http://app_backend;
    }

    注意这里没有尾斜杠。

    访问:/raw/info

    后端收到的仍然是:/raw/info

    而不是 /info。

    后端没有 /raw/info 接口,所以返回 404。

    对比:

    /api/info + proxy_pass …/ → 后端收到 /info

    /raw/info + proxy_pass … → 后端收到 /raw/info

    (15)精确匹配 /whoami

    location = /whoami {
    default_type application/json;
    return 200 '{"via":"nginx-exact-location","hint":"location = has highest priority"}\\n';
    }

    访问:/whoami

    Nginx 直接返回 JSON,不访问后端,也不查找静态文件。

    它用于演示:location = /whoami 比普通的 location / 优先级更高。

    但访问 /whoami/test 不会匹配精确规则,而会进入 location /。

    (16)完整请求流程

    ① 请求首页

    GET /

    → server 监听 80

    → 匹配 location /

    → try_files 找到 index.html

    → Nginx 返回静态网页

    ② 请求 CSS

    GET /assets/style.css

    → 匹配 location /assets/

    → 从磁盘读取 CSS

    → 添加 7 天缓存头

    → 返回浏览器

    ③ 请求 API

    GET /api/info

    → 匹配 location /api/

    → 检查限流

    → 去掉 /api/ 前缀

    → least_conn 选择 A 或 B

    → 转发 /info

    → 后端返回 JSON

    → Nginx 记录 upstream 和耗时

    → 返回浏览器

    ④ 请求慢接口

    GET /timeout/slow

    → 匹配 location /timeout/

    → 转发后端 /slow

    → 后端等待 5 秒

    → Nginx 等待 1 秒后超时

    → 返回 504

    ⑤ 请求 /raw/info

    GET /raw/info

    → 匹配 location /raw/

    → 保留完整路径 /raw/info

    → 后端没有该接口

    → 返回 404

    (17)修改配置的正确步骤

    先检查语法:podman exec nginx-lab nginx -t

    成功后平滑加载:podman exec nginx-lab nginx -s reload

    合并执行:

    podman exec nginx-lab nginx -t &&

    podman exec nginx-lab nginx -s reload

    查看最终完整配置:podman exec nginx-lab nginx -T

    查看实时日志:

    tail -f logs/access.log

    tail -f logs/error.log

    核心:

    nginx.conf:全局能力

    lab.conf:网站与路由规则

    upstream:后端名单

    server:一个网站

    location:不同 URL 怎么处理

    proxy_pass:请求转给谁

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 上章节中文件的讲解
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!