nginx语法

nginx语法解析

Nginx 配置文件超详细解读

为了方便日后查阅,我就以我项目中的 nginx.conf 为例,进行讲解:

conf 复制代码
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/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;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
}

一、全局块(第1-5行)

user nginx;

复制代码
作用:指定 Nginx 以哪个用户身份运行

比喻:公司规定,这个员工用什么工牌上班

详解:
- nginx 是一个 Linux 用户名
- 为什么要指定用户?出于安全考虑
- 不用 root 用户,是因为 root 权限太大,万一被黑客攻击,损失更大
- 用一个权限有限的用户更安全

worker_processes auto;

复制代码
作用:开启几个工作进程

比喻:餐厅雇佣几个服务员

详解:
- auto = 自动根据 CPU 核心数决定
- 如果你的服务器是 4 核 CPU,就会开 4 个进程
- 每个进程独立工作,互不干扰
- 进程越多,能同时处理的请求越多

可选值:
- auto(推荐)
- 具体数字,如 4、8

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

复制代码
作用:错误日志保存在哪里,记录什么级别的错误

比喻:投诉记录本放在哪里,记录什么程度的投诉

详解:
- /var/log/nginx/error.log 是文件路径
- notice 是日志级别

日志级别(从低到高):
┌─────────┬────────────────────────────┐
│  级别   │          记录内容          │
├─────────┼────────────────────────────┤
│ debug   │ 调试信息(最详细,最多)   │
│ info    │ 一般信息                   │
│ notice  │ 值得注意的信息             │
│ warn    │ 警告                       │
│ error   │ 错误                       │
│ crit    │ 严重错误(最少)           │
└─────────┴────────────────────────────┘

级别越高,记录的内容越少,文件越小
生产环境通常用 warn 或 error

pid /var/run/nginx.pid;

复制代码
作用:记录 Nginx 主进程的进程号(PID)

比喻:员工工号记录在哪个文件里

详解:
- 这个文件里只有一个数字,比如 "12345"
- 其他程序可以通过读这个文件,知道 Nginx 的进程号
- 用于停止、重启 Nginx 时找到正确的进程

二、events 块(第7-9行)

nginx 复制代码
events {
    worker_connections  1024;
}

worker_connections 1024;

复制代码
作用:每个工作进程最多能同时处理多少个连接

比喻:每个服务员最多同时服务多少桌客人

详解:
- 1024 表示每个进程最多 1024 个连接
- 总连接数 = worker_processes × worker_connections
- 如果 4 个进程,每个 1024,总共最多 4096 个同时连接

实际计算:
┌──────────────────────────────────────────┐
│  4 个进程 × 1024 连接 = 4096 最大连接    │
│                                          │
│  一般网站足够了                          │
│  高并发网站可以调到 65535               │
└──────────────────────────────────────────┘

三、http 块(第11-43行)

http 块是最重要的部分,配置 HTTP 服务的所有内容。

include /etc/nginx/mime.types;

复制代码
作用:引入文件类型映射表

比喻:引入一本"文件类型字典"

详解:
- mime.types 文件里定义了文件扩展名和内容类型的对应关系
- 比如:
  .html → text/html
  .css  → text/css
  .js   → application/javascript
  .png  → image/png
  .jpg  → image/jpeg

为什么需要?
- 浏览器需要知道文件类型才能正确处理
- 比如 .css 文件要当成样式表解析
- 如果类型错了,浏览器可能无法正常显示

default_type application/octet-stream;

复制代码
作用:如果文件类型未知,默认当什么类型处理

比喻:如果字典里查不到,就当成"未知物品"处理

详解:
- application/octet-stream 表示"二进制流"
- 意思是:不知道是啥,就当成普通文件下载
- 浏览器遇到这种类型,会弹出下载框

log_format main '...'

复制代码
作用:定义访问日志的格式

比喻:设计来客登记表的格式

详解:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';

这里定义了一个叫 "main" 的日志格式:

┌────────────────────────┬─────────────────────────────────┐
│        变量            │            含义                 │
├────────────────────────┼─────────────────────────────────┤
│ $remote_addr           │ 访客的 IP 地址                  │
│ $remote_user           │ 访客用户名(通常是 -)          │
│ $time_local            │ 访问时间                        │
│ $request               │ 请求内容(如 GET /index.html)  │
│ $status                │ HTTP 状态码(200、404 等)      │
│ $body_bytes_sent       │ 发送的字节数                    │
│ $http_referer          │ 从哪个页面跳转来的              │
│ $http_user_agent       │ 浏览器信息                      │
│ $http_x_forwarded_for  │ 代理链中的真实 IP               │
└────────────────────────┴─────────────────────────────────┘

实际日志长这样:
192.168.1.100 - - [04/Feb/2026:10:30:00 +0800] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0..."

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

复制代码
作用:访问日志保存在哪里,用什么格式

比喻:来客登记表放在哪里,用哪种表格

详解:
- /var/log/nginx/access.log 是文件路径
- main 是上面定义的日志格式名称

每个人访问你的网站,都会在这个文件里留下一条记录

sendfile on;

复制代码
作用:开启高效文件传输模式

比喻:开启"快速传菜通道"

详解:
┌─────────────────────────────────────────────────────────┐
│  sendfile off(关闭):                                 │
│  磁盘 → 内核缓冲区 → 用户空间 → 内核缓冲区 → 网络       │
│  (数据要复制好几次,慢)                               │
├─────────────────────────────────────────────────────────┤
│  sendfile on(开启):                                  │
│  磁盘 → 内核缓冲区 → 网络                               │
│  (数据只复制一次,快)                                 │
└─────────────────────────────────────────────────────────┘

结论:永远开启,没有理由关闭

#tcp_nopush on;

复制代码
作用:优化网络传输(被注释掉了,没启用)

详解:
- # 开头表示注释,这行不生效
- tcp_nopush 开启后,会把小数据包攒在一起发送
- 减少网络包数量,提高效率
- 通常和 sendfile 一起使用效果更好

keepalive_timeout 65;

复制代码
作用:保持连接的超时时间(秒)

比喻:客人点完餐后,服务员等他 65 秒再去服务下一桌

详解:
┌─────────────────────────────────────────────────────────┐
│  没有 keepalive:                                       │
│  请求1 → 建立连接 → 传输 → 断开连接                     │
│  请求2 → 建立连接 → 传输 → 断开连接(每次都要重新连接) │
├─────────────────────────────────────────────────────────┤
│  有 keepalive:                                         │
│  请求1 → 建立连接 → 传输                                │
│  请求2 → 复用连接 → 传输                                │
│  请求3 → 复用连接 → 传输                                │
│  ...65秒没有新请求... → 断开连接                        │
└─────────────────────────────────────────────────────────┘

好处:减少建立连接的开销,提高性能

#gzip on;

复制代码
作用:开启压缩(被注释掉了,没启用)

详解:
- 开启后,会把文件压缩后再传输
- 比如 100KB 的 JS 文件,压缩后可能只有 30KB
- 传输更快,节省带宽

为什么注释掉?
- 可能是为了简单起见
- 生产环境建议开启

四、server 块(虚拟主机)

nginx 复制代码
server {
    listen       80;
    server_name  localhost;
    ...
}

server { ... }

复制代码
作用:定义一个虚拟主机(网站)

比喻:定义餐厅里的一个"独立包间"

详解:
- 一个 Nginx 可以同时运行多个网站
- 每个 server 块就是一个网站
- 通过不同的端口或域名区分

例如:
server {
    server_name www.site1.com;   # 网站1
}
server {
    server_name www.site2.com;   # 网站2
}
server {
    listen 8080;                  # 网站3(不同端口)
}

listen 80;

复制代码
作用:监听哪个端口

比喻:餐厅开在哪条街的几号门

详解:
- 80 是 HTTP 的默认端口
- 443 是 HTTPS 的默认端口
- 浏览器访问 http://example.com 时,默认用 80 端口
- 所以 http://example.com 等于 http://example.com:80

其他写法:
listen 80;                    # 监听所有 IP 的 80 端口
listen 127.0.0.1:80;          # 只监听本机
listen 443 ssl;               # 监听 443 并启用 HTTPS
listen 80 default_server;     # 设为默认网站

server_name localhost;

复制代码
作用:这个网站响应哪个域名

比喻:餐厅的名字叫什么

详解:
- localhost 表示本机
- 可以配置实际域名,如 www.example.com
- 可以配置多个,用空格分隔

例如:
server_name www.example.com example.com;  # 两个域名指向同一网站
server_name *.example.com;                # 通配符,匹配所有子域名
server_name ~^www\d+\.example\.com$;      # 正则表达式

访问流程:
用户输入 www.example.com
    ↓
DNS 解析到服务器 IP
    ↓
请求到达 Nginx
    ↓
Nginx 看 Host 头,找到匹配的 server_name
    ↓
由对应的 server 块处理

五、location 块(路由规则)- 最重要!

nginx 复制代码
location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
}

location / { ... }

复制代码
作用:匹配 URL 路径,决定如何处理请求

比喻:根据客人要去的楼层,决定走哪部电梯

详解:
location 后面的 / 表示匹配所有路径

不同的匹配规则:
┌──────────────┬─────────────────────────────────────────┐
│   写法       │              匹配规则                   │
├──────────────┼─────────────────────────────────────────┤
│ location /   │ 匹配所有路径(兜底)                    │
│ location /api│ 匹配以 /api 开头的路径                  │
│ location = / │ 精确匹配,只匹配 /                      │
│ location ^~ /static │ 前缀匹配,优先级高              │
│ location ~ \.php$   │ 正则匹配(区分大小写)          │
│ location ~* \.(jpg|png)$ │ 正则匹配(不区分大小写)  │
└──────────────┴─────────────────────────────────────────┘

root /usr/share/nginx/html;

复制代码
作用:网站文件存放的根目录

比喻:食材仓库在哪里

详解:
- 当用户访问 http://localhost/index.html
- Nginx 会去 /usr/share/nginx/html/index.html 找文件
- 当用户访问 http://localhost/css/style.css
- Nginx 会去 /usr/share/nginx/html/css/style.css 找文件

计算公式:
实际文件路径 = root + 请求路径

例如:
root = /var/www/html
请求 = /images/logo.png
实际 = /var/www/html/images/logo.png

index index.html index.htm;

复制代码
作用:默认首页文件名

比喻:客人说"我要进门",默认带他去大厅

详解:
- 当用户访问目录(如 http://localhost/)
- Nginx 会按顺序查找:
  1. 先找 index.html
  2. 找不到再找 index.htm
  3. 都找不到就报错

可以设置多个,按顺序查找:
index index.html index.htm default.html;

try_files uri uri/ /index.html;(最关键!)

复制代码
作用:按顺序尝试查找文件,都找不到就用最后一个

比喻:
1. 先看客人要的菜有没有
2. 没有的话看看是不是套餐
3. 都不是就给他推荐招牌菜

详解:
$uri      = 用户请求的路径(如 /about)
$uri/     = 把路径当目录查找(如 /about/index.html)
/index.html = 最终兜底方案

流程图:
用户访问 /about
    ↓
1、找 /usr/share/nginx/html/about 文件
    ↓ 找不到
2、找 /usr/share/nginx/html/about/index.html 文件
    ↓ 找不到
3、返回 /usr/share/nginx/html/index.html
    ↓
Vue Router 接管,显示 /about 页面

为什么 Vue 项目需要这个?
┌─────────────────────────────────────────────────────────┐
│  Vue 是单页应用(SPA),只有一个 index.html             │
│  /login、/about、/user 这些"页面"其实都不存在           │
│  都是由 Vue Router 在前端渲染出来的                     │
│                                                         │
│  没有 try_files:                                       │
│    访问 /login → 404 Not Found(因为没有 login 文件)   │
│                                                         │
│  有 try_files:                                         │
│    访问 /login → 找不到 → 返回 index.html → Vue 渲染    │
└─────────────────────────────────────────────────────────┘

六、错误页面配置

nginx 复制代码
error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root   /usr/share/nginx/html;
}

error_page 500 502 503 504 /50x.html;

复制代码
作用:当发生这些错误时,显示指定页面

比喻:出了问题时,给客人看道歉信

详解:
500 = Internal Server Error(服务器内部错误)
502 = Bad Gateway(网关错误,通常是后端挂了)
503 = Service Unavailable(服务不可用)
504 = Gateway Timeout(网关超时)

当出现这些错误时,不显示默认的丑陋错误页面
而是显示你自定义的 /50x.html 页面

location = /50x.html { ... }

复制代码
作用:精确匹配 /50x.html 这个路径

详解:
- = 表示精确匹配,必须完全相等
- 只有访问 /50x.html 才会匹配
- /50x.html?a=1 不匹配
- /50x.html/ 不匹配

这里指定了错误页面文件的位置

七、配置块层级总结

复制代码
nginx.conf 结构图:

┌─────────────────────────────────────────────────────────┐
│  nginx.conf                                             │
│  ┌───────────────────────────────────────────────────┐  │
│  │  全局块                                           │  │
│  │  - user nginx                                     │  │
│  │  - worker_processes auto                          │  │
│  │  - error_log ...                                  │  │
│  │  - pid ...                                        │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │  events 块                                        │  │
│  │  - worker_connections 1024                        │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │  http 块                                          │  │
│  │  ┌─────────────────────────────────────────────┐  │  │
│  │  │  http 全局配置                              │  │  │
│  │  │  - include mime.types                       │  │  │
│  │  │  - sendfile on                              │  │  │
│  │  │  - keepalive_timeout 65                     │  │  │
│  │  └─────────────────────────────────────────────┘  │  │
│  │                                                   │  │
│  │  ┌─────────────────────────────────────────────┐  │  │
│  │  │  server 块(网站1)                         │  │  │
│  │  │  - listen 80                                │  │  │
│  │  │  - server_name localhost                    │  │  │
│  │  │  ┌───────────────────────────────────────┐  │  │  │
│  │  │  │  location / { ... }                   │  │  │  │
│  │  │  └───────────────────────────────────────┘  │  │  │
│  │  │  ┌───────────────────────────────────────┐  │  │  │
│  │  │  │  location /api { ... }                │  │  │  │
│  │  │  └───────────────────────────────────────┘  │  │  │
│  │  └─────────────────────────────────────────────┘  │  │
│  │                                                   │  │
│  │  ┌─────────────────────────────────────────────┐  │  │
│  │  │  server 块(网站2)                         │  │  │
│  │  │  ...                                        │  │  │
│  │  └─────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

八、项目的配置

行号 配置 作用 是否必须
1 user nginx 运行用户 推荐
2 worker_processes auto 工作进程数 必须
4 error_log ... 错误日志 推荐
5 pid ... 进程号文件 必须
8 worker_connections 1024 最大连接数 必须
12 include mime.types 文件类型 必须
13 default_type ... 默认类型 推荐
15-17 log_format ... 日志格式 可选
19 access_log ... 访问日志 推荐
21 sendfile on 高效传输 推荐
24 keepalive_timeout 65 保持连接 推荐
29 listen 80 监听端口 必须
30 server_name localhost 域名 必须
33 root ... 文件目录 必须
34 index ... 默认首页 必须
35 try_files ... SPA 关键 Vue 必须
38-40 error_page ... 错误页面 可选

现在你应该对配置文件的每一部分都有了清晰的理解!有任何具体的配置项还不明白的,随时问我。

我是 Claude Opus 4.5 模型。

没关系!这些概念确实比较抽象,让我用最通俗的大白话,一个一个给你讲清楚。


拓展 - Web 核心概念详解


概念一:静态托管

什么是"静态"?

复制代码
┌─────────────────────────────────────────────────────────┐
│                                                         │
│  【静态文件】= 写死的、不会变的文件                      │
│                                                         │
│  比如:                                                 │
│  - HTML 文件(网页骨架)                                │
│  - CSS 文件(网页样式)                                 │
│  - JS 文件(网页交互)                                  │
│  - 图片(.png, .jpg)                                   │
│  - 字体文件                                             │
│                                                         │
│  特点:你写什么,用户看到的就是什么,不会变              │
│                                                         │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                                                         │
│  【动态内容】= 根据情况变化的内容                        │
│                                                         │
│  比如:                                                 │
│  - 用户登录后显示的用户名                               │
│  - 购物车里的商品数量                                   │
│  - 数据库查询出来的文章列表                             │
│                                                         │
│  特点:需要后端程序实时计算/查询                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

什么是"托管"?

复制代码
托管 = 把文件放到服务器上,让别人能访问

生活比喻:
┌─────────────────────────────────────────────────────────┐
│                                                         │
│  你写了一本书(你的网站代码)                            │
│      ↓                                                  │
│  放到图书馆(服务器)                                   │
│      ↓                                                  │
│  别人可以来借阅(访问你的网站)                         │
│                                                         │
│  "静态托管" = 图书馆帮你保管书,别人来了直接给他看      │
│                                                         │
└─────────────────────────────────────────────────────────┘

静态托管的工作流程

复制代码
你的电脑                    服务器(Nginx)               用户浏览器
   │                            │                            │
   │  npm run build             │                            │
   │  生成 dist 文件夹          │                            │
   │         │                  │                            │
   │         └──────上传────────→│                            │
   │                            │  保存在                    │
   │                            │  /usr/share/nginx/html     │
   │                            │                            │
   │                            │←───── 请求 index.html ─────│
   │                            │                            │
   │                            │────── 返回文件内容 ────────→│
   │                            │                            │
   │                            │←───── 请求 style.css ──────│
   │                            │                            │
   │                            │────── 返回文件内容 ────────→│

一句话总结:静态托管就是把你写好的网页文件放到服务器上,让别人能通过网址访问。


概念二:单页应用(SPA)

传统网站 vs 单页应用

复制代码
【传统网站】(多页应用)

用户点击"关于我们"
    ↓
浏览器向服务器请求 about.html
    ↓
服务器返回 about.html(整个页面)
    ↓
浏览器完全刷新,显示新页面
    ↓
白屏一下,重新加载所有内容

文件结构:
├── index.html      ← 首页
├── about.html      ← 关于页面
├── contact.html    ← 联系页面
├── products.html   ← 产品页面
└── ...             ← 每个页面一个文件

【单页应用】(SPA = Single Page Application)

用户点击"关于我们"
    ↓
浏览器不刷新!
    ↓
JavaScript 把页面内容换掉
    ↓
地址栏从 / 变成 /about
    ↓
看起来像换了页面,其实还是同一个页面

文件结构:
├── index.html      ← 只有这一个 HTML!
├── app.js          ← 所有页面逻辑都在这里
└── style.css

生活比喻

复制代码
【传统网站】像翻书:
┌─────────────────────────────────────────────────────────┐
│  想看第 5 章?                                          │
│      ↓                                                  │
│  翻到第 5 章(请求新页面)                              │
│      ↓                                                  │
│  看到全新的一页(页面完全刷新)                         │
└─────────────────────────────────────────────────────────┘

【单页应用】像看魔术表演:
┌─────────────────────────────────────────────────────────┐
│  想看第 5 章?                                          │
│      ↓                                                  │
│  魔术师挥挥手(JavaScript 执行)                        │
│      ↓                                                  │
│  书上的字变了,但书还是那本书(页面不刷新)             │
└─────────────────────────────────────────────────────────┘

为什么你的 Vue 项目是单页应用?

复制代码
你用 npm run build 打包后,dist 文件夹里只有:

dist/
├── index.html          ← 唯一的 HTML 文件!
├── assets/
│   ├── index-xxx.js    ← 所有 Vue 组件编译后的代码
│   └── index-xxx.css   ← 所有样式
└── ...

不管用户访问:
- http://你的网站/           → 显示首页(index.html)
- http://你的网站/login      → 还是 index.html,Vue Router 显示登录页
- http://你的网站/about      → 还是 index.html,Vue Router 显示关于页
- http://你的网站/user/123   → 还是 index.html,Vue Router 显示用户页

所有"页面"都是由 JavaScript 动态渲染出来的!

为什么需要 try_files 配置?

复制代码
问题:

用户直接访问 http://你的网站/login
    ↓
Nginx 收到请求:"/login"
    ↓
Nginx 去找 /usr/share/nginx/html/login 文件
    ↓
找不到!(因为根本没有这个文件)
    ↓
返回 404 错误
    ↓
用户看到"页面不存在" 😢


解决方案(try_files):

用户直接访问 http://你的网站/login
    ↓
Nginx 收到请求:"/login"
    ↓
try_files $uri $uri/ /index.html
    ↓
① 先找 /login 文件 → 没有
② 再找 /login/ 目录 → 没有
③ 返回 /index.html ← 兜底!
    ↓
浏览器收到 index.html
    ↓
Vue 和 Vue Router 加载
    ↓
Vue Router 看到地址是 /login
    ↓
渲染登录页面组件 😊

一句话总结:单页应用只有一个 HTML,所有"页面"都是 JS 渲染的,所以服务器要配置"找不到就返回 index.html"。


概念三:反向代理

先理解"代理"

复制代码
【正向代理】你的代理人

场景:你想买国外的东西,但你出不去
    ↓
找个代购(代理)
    ↓
代购帮你去国外买
    ↓
代购把东西给你

技术场景:科学上网
你 → VPN(代理)→ 谷歌
         ↑
    代理帮你访问你访问不了的网站

【反向代理】服务器的代理人

场景:客人来餐厅吃饭
    ↓
前台接待(Nginx)接待客人
    ↓
前台把点的菜告诉后厨(后端服务器)
    ↓
后厨做好菜,给前台
    ↓
前台把菜端给客人

客人不知道后厨在哪、有几个厨师
客人只跟前台打交道

图解

复制代码
【没有反向代理】

用户浏览器 ──────────────────────→ 后端服务器(:3000)
                                         │
                                   暴露在外面,不安全


【有反向代理】

                              ┌──→ 后端服务器1(:3000)
                              │
用户浏览器 ───→ Nginx(:80)──┼──→ 后端服务器2(:3001)
                              │
                              └──→ 后端服务器3(:3002)
        ↑                 ↑
    用户只能看到 Nginx    后端服务器藏在后面,更安全

为什么需要反向代理?

复制代码
好处1:隐藏后端
┌─────────────────────────────────────────────────────────┐
│  用户只知道 www.example.com                             │
│  不知道后端服务器在哪个 IP、什么端口                    │
│  更安全                                                 │
└─────────────────────────────────────────────────────────┘

好处2:统一入口
┌─────────────────────────────────────────────────────────┐
│  前端:www.example.com                                  │
│  API:www.example.com/api/                              │
│  图片:www.example.com/images/                          │
│                                                         │
│  看起来是一个网站,实际上背后可能是多个服务器           │
└─────────────────────────────────────────────────────────┘

好处3:SSL 终端
┌─────────────────────────────────────────────────────────┐
│  用户 ←──HTTPS──→ Nginx ←──HTTP──→ 后端                 │
│                                                         │
│  只需要在 Nginx 配置 HTTPS                              │
│  后端不用管证书的事                                     │
└─────────────────────────────────────────────────────────┘

配置示例

nginx 复制代码
server {
    listen 80;
    server_name www.example.com;

    # 静态文件
    location / {
        root /var/www/html;
        index index.html;
    }

    # API 请求转发给后端
    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
        #           ↑
        # 把 /api/xxx 请求转发给本机 3000 端口的服务
    }
}
复制代码
用户请求:http://www.example.com/api/users
    ↓
Nginx 匹配到 location /api/
    ↓
转发给 http://127.0.0.1:3000/users
    ↓
后端返回数据给 Nginx
    ↓
Nginx 返回给用户

一句话总结:反向代理就是 Nginx 当"中间人",把用户的请求转发给后端服务器,用户不直接接触后端。


概念四:负载均衡

什么是负载均衡?

复制代码
场景:双十一,淘宝有几亿人同时访问

一台服务器能扛住吗?
    ↓
扛不住!会崩!
    ↓
怎么办?
    ↓
用很多台服务器一起扛!
    ↓
怎么分配请求?
    ↓
负载均衡!

生活比喻

复制代码
【没有负载均衡】

银行只有 1 个窗口
    ↓
100 个客人排队
    ↓
队伍排到门外
    ↓
客人等得不耐烦,走了

【有负载均衡】

银行开 5 个窗口
    ↓
大堂经理(Nginx)分配客人
    ↓
"1号去1窗口,2号去2窗口..."
    ↓
每个窗口只排 20 人
    ↓
很快就办完了

图解

复制代码
                              ┌──→ 服务器1(处理 33%)
                              │
用户请求 ───→ Nginx(负载均衡)──┼──→ 服务器2(处理 33%)
                              │
                              └──→ 服务器3(处理 33%)

分配策略

复制代码
【轮询】默认方式
请求1 → 服务器1
请求2 → 服务器2
请求3 → 服务器3
请求4 → 服务器1(又回来了)
...
像发牌一样,一人一张

【权重】按能力分配
服务器1(性能强)weight=3,处理 60%
服务器2(性能弱)weight=2,处理 40%
能力强的多干点活

【IP 哈希】同一用户固定服务器
用户A(IP: 1.1.1.1)→ 永远去服务器1
用户B(IP: 2.2.2.2)→ 永远去服务器2
保证用户的购物车、登录状态不丢失

配置示例:

复制代码
# 定义后端服务器组
upstream backend_servers {
    # 负载均衡策略:
    # 默认:轮询(round-robin)
    # ip_hash:根据 IP 分配(会话保持)
    # least_conn:最少连接
    # weight:权重

    ip_hash;  # 使用 IP 哈希

    server 192.168.1.101:8080 weight=3;  # 权重 3
    server 192.168.1.102:8080 weight=2;  # 权重 2
    server 192.168.1.103:8080 weight=1;  # 权重 1
    server 192.168.1.104:8080 backup;    # 备用服务器
}

server {
    listen 80;
    server_name www.example.com;

    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

一句话总结:负载均衡就是把很多请求分散到多台服务器,避免一台服务器被压垮。


概念五:HTTPS

HTTP vs HTTPS

复制代码
【HTTP】明文传输
┌─────────────────────────────────────────────────────────┐
│                                                         │
│  你 ──────"密码是123456"─────→ 网站                     │
│                ↑                                        │
│        黑客可以偷听到!                                 │
│        就像在公共场合大声说话                           │
│                                                         │
└─────────────────────────────────────────────────────────┘

【HTTPS】加密传输
┌─────────────────────────────────────────────────────────┐
│                                                         │
│  你 ──────"@#$%^&*加密内容"─────→ 网站                  │
│                ↑                                        │
│        黑客听到也看不懂!                               │
│        就像用密码本传递信息                             │
│                                                         │
└─────────────────────────────────────────────────────────┘

生活比喻

复制代码
HTTP = 明信片
┌─────────────────────────────────────────────────────────┐
│  邮递员、路人都能看到你写的内容                         │
└─────────────────────────────────────────────────────────┘

HTTPS = 带锁的保险箱
┌─────────────────────────────────────────────────────────┐
│  只有收件人有钥匙,别人打不开                           │
└─────────────────────────────────────────────────────────┘

HTTPS 工作原理(简化版)

复制代码
1. 你访问 https://银行.com

2. 网站出示"身份证"(SSL证书)
   证书上写着:"我确实是银行.com,不是假冒的"
   证书由权威机构(CA)签发

3. 浏览器验证证书
   "证书是真的,你确实是银行.com"

4. 双方协商一个"密码本"(加密密钥)

5. 之后所有通信都用这个"密码本"加密
   黑客即使截获也看不懂

为什么需要 HTTPS?

复制代码
✓ 数据加密 - 密码、银行卡号不会被偷
✓ 身份验证 - 确保你访问的是真网站,不是钓鱼网站
✓ 数据完整 - 确保数据没被篡改

现代浏览器对 HTTP 网站会显示"不安全"警告
搜索引擎优先收录 HTTPS 网站

示例

复制代码
server {
    listen 443 ssl http2;
    server_name www.example.com;

    # SSL 证书配置
    ssl_certificate /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # SSL 安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS(强制 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000" always;

    root /var/www/example;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

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

一句话总结:HTTPS 就是给 HTTP 加了一把锁,让数据传输更安全。


概念六:跨域(CORS)

什么是跨域?

复制代码
【同源】
你的网页:https://www.example.com
请求地址:https://www.example.com/api/users
    ↓
协议相同(https)、域名相同(www.example.com)、端口相同
    ↓
这是"同源",浏览器允许


【跨域】
你的网页:https://www.example.com
请求地址:https://api.other.com/users
    ↓
域名不同!
    ↓
这是"跨域",浏览器默认禁止!

为什么浏览器要禁止跨域?

复制代码
安全考虑!

假设没有跨域限制:

1. 你登录了银行网站,有登录状态(Cookie)

2. 你不小心打开了一个恶意网站

3. 恶意网站的 JS 代码偷偷请求:
   fetch('https://银行.com/api/转账?to=黑客&amount=100万')

4. 因为你有银行的 Cookie,请求会带上你的身份

5. 钱就被转走了!

有了跨域限制:

恶意网站的 JS 无法请求其他网站的 API
你的银行账户就安全了

生活比喻

复制代码
跨域限制 = 小区门禁

你是 A 小区的住户(www.a.com)
    ↓
你可以自由进出 A 小区(请求 www.a.com)
    ↓
但你不能随便进 B 小区(请求 www.b.com)
    ↓
除非 B 小区物业说"让他进来"(服务器允许跨域)

怎么解决跨域?

复制代码
方法:服务器告诉浏览器"我允许他访问"

服务器返回响应头:
Access-Control-Allow-Origin: https://www.example.com

意思是:
"我允许 https://www.example.com 这个网站的 JS 访问我"

浏览器看到这个头,就放行了

你的项目为什么没有跨域问题?

复制代码
开发时:
┌─────────────────────────────────────────────────────────┐
│  你的前端:http://localhost:5173                        │
│  后端 API:http://localhost:8080                        │
│                                                         │
│  端口不同,本来会跨域                                   │
│                                                         │
│  但是 Vite 开发服务器配置了代理:                       │
│  /api/* → 转发到 localhost:8080                         │
│                                                         │
│  所以前端请求 /api/xxx                                  │
│  实际上是请求 localhost:5173/api/xxx                    │
│  Vite 再转发给 localhost:8080                           │
│                                                         │
│  浏览器看到的是同源请求,不会跨域!                     │
└─────────────────────────────────────────────────────────┘

生产时(用 Nginx):
┌─────────────────────────────────────────────────────────┐
│  前端和 API 都走 www.example.com                        │
│                                                         │
│  前端:www.example.com/                                 │
│  API:www.example.com/api/                              │
│                                                         │
│  Nginx 把 /api/ 转发给后端                              │
│  用户浏览器看到的都是同一个域名                         │
│  没有跨域问题!                                         │
└─────────────────────────────────────────────────────────┘

一句话总结:跨域是浏览器的安全限制,阻止网页 JS 请求其他网站;通过服务器配置或代理可以解决。


概念七:限流

什么是限流?

复制代码
场景:
你开了一家小餐厅,最多同时接待 50 人
    ↓
突然来了 500 人
    ↓
厨房爆炸,服务员崩溃,谁都吃不上饭
    ↓
餐厅倒闭

解决方案:
在门口放个保安(限流)
    ↓
"店里已经 50 人了,请排队等候"
    ↓
控制进入的人数
    ↓
餐厅正常运营

限流的作用

复制代码
1. 保护服务器不被压垮

2. 防止恶意攻击
   - 有人写脚本疯狂请求你的网站
   - 1秒钟请求1万次
   - 想把你的服务器搞崩
   - 限流:每秒最多10次,超过的拒绝

3. 公平分配资源
   - 不让一个用户占用所有资源
   - 大家都能用

限流策略

复制代码
【按请求频率限制】
每秒最多处理 100 个请求
第 101 个请求:等一下或者返回错误

【按 IP 限制】
每个 IP 每秒最多 10 个请求
防止单个用户/攻击者发太多请求

【按用户限制】
每个登录用户每分钟最多 100 个请求
API 接口常用这种

【按并发连接限制】
同时最多 1000 个连接
超过的等着

一句话总结:限流就是控制请求数量,防止服务器被压垮或被攻击。


总结:一张图理解所有概念

复制代码
                                    互联网
                                       │
                                       ▼
                            ┌──────────────────┐
                            │                  │
                            │   用户的浏览器   │
                            │                  │
                            └────────┬─────────┘
                                     │
                                     │ HTTPS(加密传输)
                                     │
                                     ▼
┌────────────────────────────────────────────────────────────────┐
│                                                                │
│                     Nginx(门卫 + 前台)                        │
│                                                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │
│  │   限流       │  │   跨域处理   │  │  负载均衡    │         │
│  │   控制流量   │  │   允许/拒绝  │  │  分发请求    │         │
│  └──────────────┘  └──────────────┘  └──────────────┘         │
│                                                                │
│  ┌─────────────────────────┐  ┌─────────────────────────┐     │
│  │                         │  │                         │     │
│  │  静态托管               │  │  反向代理               │     │
│  │  返回 HTML/CSS/JS/图片  │  │  转发 API 请求给后端    │     │
│  │                         │  │                         │     │
│  └─────────────────────────┘  └───────────┬─────────────┘     │
│           │                               │                   │
└───────────┼───────────────────────────────┼───────────────────┘
            │                               │
            ▼                               ▼
    ┌───────────────┐             ┌───────────────────────┐
    │               │             │                       │
    │  dist 文件夹  │             │  后端服务器集群       │
    │  (Vue 打包)   │             │  ┌─────┐ ┌─────┐      │
    │               │             │  │ 1   │ │ 2   │ ...  │
    │  index.html   │             │  └─────┘ └─────┘      │
    │  app.js       │             │                       │
    │  style.css    │             │  处理 API 请求        │
    │               │             │  查询数据库           │
    └───────────────┘             └───────────────────────┘
            │
            │
            ▼
    ┌───────────────┐
    │               │
    │  单页应用     │
    │  (SPA)        │
    │               │
    │  Vue Router   │
    │  处理前端路由 │
    │               │
    └───────────────┘

对应你项目的情况

概念 你的项目怎么用的
静态托管 Nginx 托管 dist 文件夹里的 Vue 打包文件
单页应用 Vue + Vue Router,只有一个 index.html
反向代理 开发时 Vite 代理 /api,生产时 Nginx 代理
负载均衡 目前没用到(单服务器),以后可以扩展
HTTPS 目前配置文件没有,生产环境需要添加
跨域 通过代理解决,不需要额外配置
限流 目前没用到,可以根据需要添加

现在这些概念应该清楚多了吧?有任何还不理解的地方,随时问我!

相关推荐
萧曵 丶4 小时前
Nginx 高频面试题(含答案)
运维·nginx
无名的小白5 小时前
openclaw使用nginx反代部署过程 与disconnected (1008): pairing required解决
java·前端·nginx
wengad5 小时前
podman搭建nginx服务
运维·nginx·podman
regret~8 小时前
【笔记】Nginx 核心操作 + 配置解析笔记(适配 Linux+FastAPI / 前端代理场景)
linux·笔记·nginx
萧曵 丶10 小时前
Nginx常用配置
运维·nginx
有代理ip10 小时前
后端服务安全加固:Nginx 反向代理配置教程
运维·nginx·安全
养多肉11 小时前
宝塔面板绑定域名(不带端口)
服务器·nginx·安全
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.1 天前
Nginx构建PC站点:root与alias详解
运维·chrome·nginx
哆啦code梦1 天前
Kong vs Nginx:微服务网关选型指南
nginx·kong·微服务网关