Nginx简介
Nginx(发音同 engine x)是一款基于异步框架的轻量级/高性能的Web 服务器/反向代理服务器/缓存服务器/电
子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·赛
索耶夫)所开发,最初供俄国大型网站Rambler.ru及搜寻引擎Rambler使用。
Nginx特点
- 优点:
高并发量:基于 epoll/kqueue 模型开发,支持高并发量,官方说其支持高达 5w 并发连接数的响应
内存消耗少:善于处理静态文件,相较于其他web(比如:apache),占用更少的内存及资源
简单稳定:配置简单(一个conf文件),运行简单(nginx命令),而且运行稳定
模块化程度高:功能模块插件化设计,可以自由配置相应的功能。
支持Rwrite重写规则:能够根据域名、URL等请求关键点,实现定制化的高质量分发。
低成本:Nginx的负载均衡功能很强大而且免费开源,相较于几十万的硬件负载均衡器成本相当低。
支持多系统:Nginx代码完全用C语言从头写成,可以在各系统上编译并使用。
- 缺点:
动态处理差:nginx善于处理静态文件,但是处理动态页面相较于Apache之类重量级的web软件能力稍欠缺。
rewrite弱:虽然nginx支持rewrite功能多,但是相较于Apache之类重量级的web软件能力稍欠缺。
安装
CentOS
# 1. 尝试直接使用 yum 安装
yum install nginx -y
# 2. 如果上面失败,可能需要先安装 EPEL 源 (CentOS 7 常用)
yum install epel-release -y
yum install nginx -y
[root@sovzn ~]# nginx -v
nginx version: nginx/1.20.1
[root@sovzn ~]# # 验证状态
[root@sovzn ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: inactive (dead)
[root@sovzn ~]# # 启动
[root@sovzn ~]# sudo systemctl start nginx
[root@sovzn ~]# systemctl status nginx
[root@sovzn ~]# # 设置开机自启
[root@sovzn ~]# sudo systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
[root@sovzn ~]#
[root@sovzn ~]# 检查配置文件
[root@sovzn ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@sovzn ~]#
核心操作命令
| 操作 | 命令 | 说明 |
|---|---|---|
| 启动 | systemctl start nginx |
启动 Nginx 服务。如果未运行,则立即运行。 |
| 停止 | systemctl stop nginx |
停止 Nginx 服务。会中断当前正在处理的连接。 |
| 重启 | systemctl restart nginx |
先停止再启动。会中断连接,通常用于重大配置变更或升级。 |
| 重载 | systemctl reload nginx |
推荐用于修改配置后。重新加载配置文件,不中断现有连接(平滑过渡)。 |
| 查看状态 | systemctl status nginx |
查看服务是否运行、进程号、日志片段等。 |
| 开机自启 | systemctl enable nginx |
设置服务器重启后自动启动 Nginx。 |
| 禁止自启 | systemctl disable nginx |
取消开机自动启动。 |
工作目录
| 目录用途 | 包管理器安装 (yum/dnf/apt) (CentOS/Ubuntu/Debian) | 源码编译安装 (默认) (make install) | 说明 |
|---|---|---|---|
| 主配置文件 | /etc/nginx/nginx.conf |
/usr/local/nginx/conf/nginx.conf |
核心配置入口 |
| 额外配置目录 | /etc/nginx/conf.d/ |
/usr/local/nginx/conf/conf.d/ (需手动创建) |
存放 server 块配置,方便管理 |
| 网站根目录 | /usr/share/nginx/html |
/usr/local/nginx/html |
放置 index.html 等静态文件的地方 |
| 日志目录 | /var/log/nginx/ |
/usr/local/nginx/logs/ |
存放 access.log 和 error.log |
| 进程 PID 文件 | /run/nginx.pid 或 /var/run/nginx.pid |
/usr/local/nginx/logs/nginx.pid |
记录主进程 ID |
| 临时文件目录 | /var/cache/nginx/ /var/lib/nginx/ |
/usr/local/nginx/client_body_temp/ /usr/local/nginx/proxy_temp/ 等 |
缓存、请求体临时存储 |
| 可执行文件 | /usr/sbin/nginx |
/usr/local/nginx/sbin/nginx |
启动命令所在 |
如何准确查看当前的目录:
# 小写v只看版本信息,大写V可查看所有配置信息
nginx -V
nginx version: nginx/1.24.0
built by gcc ...
configure arguments:
--prefix=/usr/local/nginx <-- 这是您的【安装根目录】
--conf-path=/etc/nginx/nginx.conf <-- 这是【配置文件】路径
--http-log-path=/var/log/nginx/access.log <-- 【日志】路径
--pid-path=/var/run/nginx.pid <-- 【PID】路径
...
/etc/nginx/conf.d
/etc/nginx/conf.d 是 Nginx 的 子配置文件目录。
它的主要作用是:模块化管理网站配置,让你不需要把所有网站的配置都写在一个巨大的主文件里。
它的工作原理:
主配置文件 (
/etc/nginx/nginx.conf) 中通常包含这样一行代码:1include /etc/nginx/conf.d/*.conf;这行代码的意思是:“把
/etc/nginx/conf.d/目录下所有以.conf结尾的文件,都加载进来作为配置的一部分。”启动时加载顺序:
- Nginx 启动时,先读
/etc/nginx/nginx.conf(全局配置,如用户、进程数、日志路径等)。 - 读到
include指令时,它会按字母顺序读取conf.d下的所有.conf文件。 - 这些文件里的内容(通常是
server { ... }块)会被合并到主配置中生效。
- Nginx 启动时,先读
为什么要用它?
多网站管理:如果你在一台服务器上跑了 3 个网站(比如 a.com, b.com, c.com),你可以在 conf.d 下分别创建:
a.com.conf
server {
listen 80;
server_name www.a.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
b.com.conf
server {
listen 80;
server_name www.b.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
c.com.conf
server {
listen 80;
server_name www.c.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
- 好处:修改
a.com的配置时,不会误删b.com的代码;删除某个网站时,直接删掉对应的文件即可,非常干净。
配置文件详解
核心结构概览
Nginx 配置文件采用 模块化块状结构,主要由以下四个部分组成,层级关系如下:
# 1. 全局块 (Main Context)
# 影响 Nginx 整体运行的配置(用户、进程数、日志路径等)
# 2. Events 块 (Events Context)
# 配置网络连接处理模式(最大连接数、事件驱动模型)
# 3. HTTP 块 (HTTP Context)
# 配置 HTTP 服务器相关特性(反向代理、缓存、负载均衡、虚拟主机等)
# ├── HTTP 全局配置 (Gzip, Log format, Include mime.types)
# ├── Server 块 1 (虚拟主机 A: www.example.com)
# │ └── Location 块 (路由规则)
# ├── Server 块 2 (虚拟主机 B: api.example.com)
# └── Upstream 块 (负载均衡服务器组)
全局块 (Main Context)
位置:文件最顶部,events 块之前。
作用:配置运行用户、工作进程数、日志路径、PID 文件等。
# 运行 Nginx 的用户和用户组 语法: user <username> <groupname>;
# (安全建议:使用专用用户如 nginx 或 www-data)
user nginx nginx;
# 如果没有 Nginx会自建用户和组
[root@sovzn html]# id nginx
uid=997(nginx) gid=993(nginx) groups=993(nginx)
[root@sovzn html]#
# 工作进程数 (建议设置为等于 CPU 核心数,或设为 auto 自动检测)
worker_processes auto;
# 全局错误日志路径及级别 (级别: debug, info, notice, warn, error, crit)
error_log /var/log/nginx/error.log warn;
# PID 文件存放路径 (记录主进程 ID)
pid /var/run/nginx.pid;
# 限制打开文件描述符数量 (需配合系统 ulimit 使用)
worker_rlimit_nofile 65535;
Events 块 (Events Context)
位置:events { ... }
作用:配置网络连接处理模式,直接影响并发性能。
events {
# 单个 worker 进程允许的最大连接数
# 理论最大连接数 = worker_processes * worker_connections
worker_connections 10240;
# 事件驱动模型 (Linux 推荐 epoll, FreeBSD 推荐 kqueue)
use epoll;
# 允许多个工作进程同时接受新连接 (提高高并发下的吞吐量)
multi_accept on;
}
HTTP 块 (HTTP Context)
位置:http { ... }
作用:配置所有 HTTP 相关的功能,是配置最复杂的部分。
HTTP 全局配置
http {
# 引入 MIME 类型配置文件 (决定不同后缀文件的 Content-Type)
include /etc/nginx/mime.types;
default_type application/octet-stream;
# --- 日志格式定义 ---
# $remote_addr: 客户端 IP
# $time_local: 访问时间
# $request: 请求行
# $status: 状态码
# $body_bytes_sent: 发送字节数
# $http_referer: 来源页
# $http_user_agent: 用户代理
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; # 防止网络阻塞,配合 sendfile 使用
tcp_nodelay on; # 禁止 Nagle 算法,降低延迟 (适合短连接)
# 连接超时设置
keepalive_timeout 65; # 长连接超时时间
client_header_timeout 10;
client_body_timeout 10;
# 上传文件大小限制
client_max_body_size 100M;
# 开启 Gzip 压缩 (节省带宽)
gzip on;
gzip_min_length 1k; # 最小压缩文件大小
gzip_types text/plain application/json application/javascript text/css application/xml;
gzip_vary on; # 添加 Vary: Accept-Encoding 头
# --- 引入其他配置文件 (最佳实践:将站点配置拆分) ---
include /etc/nginx/conf.d/*.conf;
}
Server 块 (虚拟主机)
位置:嵌套在 http 块内。
作用:定义一个具体的网站或域名服务。
server {
# 监听端口 (可指定 IP,默认监听所有 IP)
listen 80;
# 监听 IPv6 (如需)
# listen [::]:80;
# 域名匹配 (支持多个域名,空格分隔,支持泛域名 *.example.com)
server_name example.com www.example.com;
# 网站根目录
root /usr/share/nginx/html;
# 默认首页文件
index index.html index.htm;
# --- 字符集 ---
charset utf-8;
# --- Location 路由规则 (核心) ---
# 1. 精确匹配 (=)
location = /favicon.ico {
log_off on;
expires 30d;
}
# 2. 前缀匹配 (无符号 或 ^~) - 最常用
# 匹配所有以 / 开头的请求
location / {
# 在配置的根目录尝试查找文件,如果不存在则作为目录查找,再不存在则转发给 @fallback
try_files $uri $uri/ @fallback;
}
# 3. 正则匹配 (~ 区分大小写, ~* 不区分)
# 匹配图片资源,设置长期缓存
location ~* \.(gif|jpg|jpeg|png|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 4. 命名 Location (@name) - 用于内部重定向
location @fallback {
return 404;
# 或者转发给后端:proxy_pass http://backend;
}
# --- 错误页面配置 ---
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
在 Nginx 配置中,
root和alias都用于将请求的 URL 路径映射到服务器上的文件系统路径,但它们的映射规则有本质区别。简单来说,**root是路径拼接,而alias是路径替换**。
核心区别
root(路径拼接): 会将location匹配到的路径追加到root指令指定的目录后面。alias(路径替换): 会用alias指令指定的目录替换掉location匹配到的路径部分。
场景示例
假设服务器上存在以下两个目录:
/var/www/html/var/www/images
使用 root:
location /static/ {
root /var/www/html;
}
当用户请求 http://example.com/static/logo.png 时,Nginx 会去查找:/var/www/html + /static/logo.png = /var/www/html/static/logo.png
使用 alias:
location /static/ {
alias /var/www/images/;
}
当用户请求 http://example.com/static/logo.png 时,Nginx 会去查找:/var/www/images/ + logo.png = /var/www/images/logo.png
注意,URL 中的 /static/ 部分被 alias 指定的路径完全替换了。
| 特性 | root |
alias |
|---|---|---|
| 作用方式 | 拼接请求路径 | 替换 location 前缀 |
| 最终路径 | root路径 + location路径 + 剩余URI |
alias路径 + 剩余URI |
| 常见用途 | 整个站点的根目录,或保持URL与目录结构一致 | 将特定URL路径映射到任意目录 |
| 作用域 | http, server, location |
仅限 location |
| 末尾斜杠 | 不强制要求 | 强烈建议加上,否则易出错 |
Upstream 块 (负载均衡)
位置:通常嵌套在 http 块内,server 块外。
作用:定义后端服务器组。
upstream backend_servers {
# 负载均衡策略 (默认是轮询 round_robin)
# 1. 加权轮询 (权重越高,分配越多)
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=1;
# 2. ip_hash (根据客户端 IP 哈希,解决 Session 共享问题)
# ip_hash;
# 3. 备用服务器 (当其他服务器挂掉时启用)
server 192.168.1.12:8080 backup;
# 4. 失败判定 (可选)
# max_fails=3 fail_timeout=30s;
}
# 在 Server 块中使用
server {
location /api/ {
proxy_pass http://backend_servers;
# 传递真实客户端 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;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
常用场景配置
静态网站 + HTTPS 强制跳转
# HTTP 强制跳转 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
反向代理
代理到 Node.js/Java/Go 应用
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000; # 后端应用地址
# 关键:传递真实信息
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;
# WebSocket 支持 (如果需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
限制访问 (防爬虫/限流)
http {
# 定义限流区域 (每秒允许 10 个请求)
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
# 应用限流
location /login {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
# 禁止特定 User-Agent (简单爬虫屏蔽)
if ($http_user_agent ~* (Scrapy|curl|wget)) {
return 403;
}
# 禁止特定 IP
deny 192.168.1.100;
allow all;
}
}
斜杠核心详解
Location与Proxy_pass斜杠核心详解
Location匹配核心规则
核心原则:最长前缀匹配
谁更精确、前缀更长,谁的优先级更高,不存在宽泛路径覆盖精准路径的情况,这是前后端分离配置(/对应前端、/api/对应后端)不冲突的根本原因。
location /:通用匹配,匹配所有请求路径,优先级最低location /api:前缀匹配,匹配所有以**/api**开头的路径(如/api、/api/、/apiabc、/api/user),范围宽泛,易误匹配location /api/:精准前缀匹配,仅匹配以**/api/**开头的路径(如/api/user、/api/admin/list),无多余匹配,是生产环境标准写法
匹配优先级对比(由高到低)
location /api/(精准)> location /api(宽泛)> location /(通用)
示例:请求/api/user,优先匹配/api/,完全不走/的前端配置,无覆盖冲突。
Proxy_pass斜杠核心规则
核心逻辑
请求先匹配到对应location后,再看proxy_pass末尾是否带路径/斜杠,分两种核心场景:
- proxy_pass无后缀斜杠/路径:原样转发,不做任何路径替换
- proxy_pass有后缀斜杠/路径:字符串替换,将请求中匹配到location的前缀部分,替换为
proxy_pass后缀的路径
场景1:location /api + proxy_pass无后缀斜杠
location /api {
# 仅域名+端口,无任何后缀路径
proxy_pass http://localhost:8080;
}
- 匹配规则:匹配所有
/api开头的请求 - 转发规则:原样拼接完整请求路径
- 示例:请求
/api/user→ 后端接收http://localhost:8080/api/user
场景2:location /api + proxy_pass后缀带/(踩坑场景)
location /api {
# 后缀带/
proxy_pass http://localhost:8080/;
}
- 匹配规则:匹配所有
/api开头的请求 - 转发规则:将
/api替换为/,纯字符串替换,不智能合并斜杠 - 示例:请求
/api/user→ 替换后/ + /user = //user,后端路径报错(双斜杠bug)
场景3:location /api/ + proxy_pass无后缀斜杠(生产常用)
location /api/ {
proxy_pass http://localhost:8080;
}
- 匹配规则:仅匹配
/api/开头的请求 - 转发规则:原样转发完整路径
- 示例:请求
/api/user→ 后端接收http://localhost:8080/api/user
场景4:location /api/ + proxy_pass后缀带/(生产最常用)
location /api/ {
proxy_pass http://localhost:8080/;
}
- 匹配规则:仅匹配
/api/开头的请求 - 转发规则:将
/api/替换为/,切掉接口前缀 - 示例:请求
/api/user→ 后端接收http://localhost:8080/user
proxy_pass后缀自定义路径(非仅/)
proxy_pass后缀可自定义任意路径(如/admin、/user、/manage/api),替换规则完全一致,是多服务代理的常用玩法:
location /api/ {
# 后缀自定义为/admin/
proxy_pass http://localhost:8080/admin/;
}
- 示例:请求
/api/user/list→ 将/api/替换为/admin/→ 后端接收/admin/user/list
核心流程总结(一句话记牢)
- 先匹配:按最长前缀原则,确定请求走哪个location
- 再转发:
- proxy_pass无后缀斜杠/路径:原模原样转发请求路径
- proxy_pass有后缀斜杠/路径:把匹配到的location前缀,替换成代理后缀的路径
生产环境避坑准则
- 接口代理禁止用
location /api,必须用location /api/,避免误匹配和双斜杠bug - 需保留接口前缀:
proxy_pass不加后缀斜杠 - 需切掉接口前缀:
proxy_pass加后缀斜杠 - 前后端分离标准配置(无冲突、无覆盖)
server {
listen 80;
server_name localhost;
# 前端静态资源:通用匹配,优先级最低
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html; # 解决前端路由刷新404
}
# 后端接口:精准匹配,优先级更高,无覆盖
location /api/ {
# 切掉/api/转发,根据后端需求选择加/或不加
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Location核心匹配符号与优先级
Nginx 通过不同的修饰符来区分匹配模式,其优先级顺序如下:
| 优先级 | 符号/类型 | 含义 | 匹配逻辑 |
|---|---|---|---|
| 1 (最高) | = |
精确匹配 | 请求 URI 必须与路径完全一致(例如 location = / 仅匹配根路径)。 |
| 2 | ^~ |
优先前缀匹配 | 若路径匹配成功,立即停止搜索正则表达式,直接使用此配置。 |
| 3 | ~ |
正则匹配(区分大小写) | 使用正则表达式匹配,且严格区分大小写(如 .jpg 与 .JPG 不同)。 |
| 3 | ~* |
正则匹配(不区分大小写) | 使用正则表达式匹配,忽略大小写。 |
| 4 | (无修饰符) | 标准前缀匹配 | 普通的路径前缀匹配(如 location /images)。如果有多个匹配,取最长的那个。 |
| 5 (最低) | / |
通用匹配 | 兜底规则,匹配所有请求。 |
匹配流程逻辑
Nginx 处理请求时并非按配置文件顺序执行,而是遵循以下逻辑:
- 精确匹配检查:首先检查
=修饰符。如果命中,立即结束查找。 - 前缀匹配检查:
- 检查所有前缀字符串(包括
^~和普通前缀)。 - 如果
^~匹配成功,立即结束查找。 - 如果没有
^~,Nginx 会暂存最长的那个普通前缀匹配。
- 检查所有前缀字符串(包括
- 正则匹配检查:按配置文件中的顺序检查
~和~*。如果找到匹配项,使用正则配置;否则使用第 2 步暂存的最长前缀匹配。 - 兜底:如果以上都没命中,则使用
/通用匹配。
示例
# 规则 A: 精确匹配根路径
location = / {
# 返回 "Rule A"
}
# 规则 B: 精确匹配 /login
location = /login {
# 返回 "Rule B"
}
# 规则 C: 优先前缀匹配 /static/
location ^~ /static/ {
# 返回 "Rule C"
}
# 规则 D: 正则匹配,区分大小写 (gif, jpg, png, js, css)
location ~ \.(gif|jpg|png|js|css)$ {
# 返回 "Rule D"
}
# 规则 E: 正则匹配,不区分大小写 (.png)
location ~* \.png$ {
# 返回 "Rule E"
}
# 规则 F: 通用匹配 (兜底)
location / {
# 返回 "Rule F"
}
案例 1:访问根路径
请求 URL:http://domain.com/
匹配结果:规则 A
分析:location = / 是精确匹配,优先级最高,完全吻合。
案例 2:访问登录页
请求 URL:http://domain.com/login
匹配结果:规则 B
分析:location = /login 精确匹配成功。
案例 3:访问静态资源目录
请求 URL:http://domain.com/static/css/style.css
匹配结果:规则 C
分析:
虽然 .css 后缀也能匹配规则 D,但 ^~ 修饰符的优先级(第 2 级)高于正则匹配(第 3 级)。
Nginx 发现 ^~ /static/ 匹配成功后,停止搜索正则,直接返回规则 C。
案例 4:访问普通图片(小写后缀)
请求 URL:http://domain.com/uploads/image.jpg
匹配结果:规则 D
分析:
没有精确匹配,也没有 ^~ 前缀匹配。
进入正则检查:规则 D ~ \.(jpg)$ 匹配成功。
注意:虽然规则 E 也能匹配 png,但这里是 jpg,且规则 D 在配置中通常先于 E 被扫描(或者即使顺序相反,jpg 也不符合 E 的 png 条件)。
案例 5:访问大写后缀图片(大小写敏感测试)
请求 URL:http://domain.com/uploads/image.JPG
匹配结果:规则 F
分析:
规则 D (~) 是区分大小写的,.JPG 不匹配 .jpg,所以规则 D 失败。
规则 E (~* .png$) 只匹配 png,所以失败。
最终落入通用匹配,命中规则 F。
案例 6:访问大写 PNG 图片(不区分大小写测试)
请求 URL:http://domain.com/uploads/image.PNG
匹配结果:规则 E
分析:
规则 D 失败(区分大小写,D 里没有 .PNG)。
规则 E (~* \.png$) 是不区分大小写的,成功匹配 .PNG。
案例 7:访问未知路径
请求 URL:http://domain.com/abc/test
匹配结果:规则 F
分析:
没有精确匹配。
没有前缀匹配。
没有正则匹配。
最终命中兜底的 location /。
Location中的 try_files
核心定义
try_files 是 Nginx 中用于处理请求路由的核心指令,其核心思想是“按优先级尝试,优雅降级”。
- 功能:按顺序检查一个或多个文件、目录是否存在。
- 行为:返回第一个找到的资源。
- 兜底:如果所有资源都不存在,则执行最后一个参数指定的“回退”(fallback)操作。
try_files file1 file2 ... fallback;
完整配置示例
1 server {
2 listen 80;
3 server_name example.com;
4
5 # 1. 指定物理根目录(地基)
6 root /var/www/myapp;
7
8 # 2. 指定默认首页文件(配合目录匹配使用)
9 index index.html;
10
11 location / {
12 # 3. 核心逻辑:按顺序检查
13 try_files $uri $uri/ /index.html;
14 }
15}
工作流程
- 检查第一个参数:Nginx 根据
root拼接完整路径,检查文件是否存在。 - 命中即停:如果文件存在,立即返回,后续参数不再检查。
- 顺序检查:如果文件不存在,继续检查下一个参数。
- 执行回退:如果所有检查都失败,执行最后一个
fallback参数。
经典应用场景
单页应用(SPA)路由支持
1 location / {
2 # 1. 尝试找文件 ($uri)
3 # 2. 尝试找目录 ($uri/)
4 # 3. 都找不到,返回 /index.html,交给前端路由处理 $uri表示按名称匹配文件,$uri/ 表示按名称匹配路径
5 try_files $uri $uri/ /index.html;
6}
- **请求
/about**:服务器上无/about文件,也无/about/目录,最终返回/index.html,前端 JS 接管并渲染”关于”页面。
网站维护模式
1 location / {
2 # 1. 检查维护页面是否存在
3 # 2. 若不存在,再正常处理请求
4 # 3. 若请求也找不到,返回404
5 try_files /system/maintenance.html $uri $uri/ =404;
6}
- 开启维护:只需将
maintenance.html上传到/system/目录,所有请求都会被拦截并返回维护页。 - 关闭维护:删除该文件,网站即刻恢复正常。
静态资源与后端代理分离
1 location / {
2 # 1. 尝试找静态文件
3 # 2. 找不到,转发给 @backend 处理
4 try_files $uri $uri/ @backend;
5}
6
7 location @backend {
8 proxy_pass http://127.0.0.1:3000;
9}
重要注意事项
- 查找范围:
try_files只在root或alias指令指定的目录范围内查找文件,不会扫描整个服务器硬盘。 - 顺序至关重要:Nginx 严格按照从左到右的顺序检查,找到即停。因此,优先级高的检查项必须放在前面。
fallback是必选项:最后一个参数必须存在,否则配置会出错。- 性能影响:每个文件检查都会产生一次磁盘 I/O 操作。虽然很快,但在极高并发下,过多的检查项可能会带来轻微的性能损耗。
- 内部重定向:当
fallback是一个 URI 或命名 location 时,会发生内部重定向,这意味着$uri变量的值会改变,并进入新的location块进行处理。
Nginx 临时跳转(302)
核心定义
302 Found 是一种外部重定向,意为“资源暂时搬家了”。
- 对用户:浏览器地址栏会变成新地址。
- 对浏览器:这是一个临时指令。浏览器不会永久缓存这个跳转规则。下次访问旧地址时,浏览器依然会向服务器发起请求,询问“现在去哪?”。
- 默认行为:在 Nginx 的
return指令中,如果省略状态码,默认就是 302。
实现方式
使用 return 指令(推荐)
这是最简单、性能最高的方法。
location /old-page {
# 显式写法(推荐,清晰)
return 302 https://www.example.com/new-page;
# 简写写法(默认也是 302)
# return https://www.example.com/new-page;
# return /error;
}
#location /error {
# return 400;
#}
使用 rewrite 指令
适合配合正则表达式进行复杂的路径匹配。
1 location /old-page {
2 # redirect 关键字等同于 302
3 rewrite ^/old-page$ https://www.example.com/new-page redirect;
4}
302 与 301 的终极对比
301 也能实现跳转功能,但是……浏览器会把它“写死”在缓存里。
但代价是浏览器会认为这个变动是永久的,如果不清楚缓存,就算删除了跳转配置,访问旧地址时还会跳转到以前配置的新地址
| 特性 | 302 (临时跳转) | 301 (永久跳转) |
|---|---|---|
| 浏览器缓存 | 不缓存 (或缓存时间极短) | 积极缓存 (会“写死”在浏览器里) |
| 服务器交互 | 每次都会问服务器:“今天去哪?” | 首次之后,浏览器自己跳,不问服务器 |
| SEO 权重 | 不传递。搜索引擎保留原 URL 的权重 | 传递。搜索引擎将权重转移给新 URL |
| 后悔成本 | 低。服务器改配置,立马生效 | 高。需用户手动清浏览器缓存才能取消 |
常见应用场景
- 网站临时维护:将用户临时引导至“维护中”页面,维护结束后删除配置即可恢复。
- A/B 测试:临时将部分流量跳转到新版本页面进行测试。
- 兼容旧链接:旧 URL 失效时,临时指向新链接,避免 404 错误。
- 登录后跳转:用户访问需登录页面时,临时跳转至登录页,登录成功后再跳回。
开发与调试建议
- 黄金法则:开发和测试阶段,永远优先使用 302!
- 原因:避免浏览器缓存 301 带来的麻烦,防止修改配置后浏览器依然“固执”地执行旧跳转。
- 清除 301 缓存方法
- 使用浏览器的无痕/隐私窗口访问。
- 在开发者工具的 Network 面板中勾选
Disable cache。 - 手动清除浏览器“缓存的图片和文件”。
autoindex
- 功能:当访问的目录中不存在默认首页文件(如
index.html)时,自动生成并显示该目录的文件列表页面。- 默认状态:
off(关闭),出于安全考虑,Nginx 默认不列出目录内容。
| 指令 | 默认值 | 作用 | 推荐配置 |
|---|---|---|---|
autoindex |
off |
开启或关闭目录列表功能 | on |
autoindex_exact_size |
on |
显示文件精确字节数 (on) 或人类可读格式 (KB/MB/GB) (off) |
off |
autoindex_localtime |
off |
显示文件时间为服务器本地时间 (on) 或 UTC 时间 (off) |
on |
autoindex_format |
html |
定义列表输出格式 (html, json, xml, jsonp) |
html |
利用 autoindex 是搭建简易文件下载服务器(下载站点)最常用、最快捷的方法。
server {
listen 80;
server_name download.example.com;
# 1. 定义文件存储的物理路径
root /data/files;
location / {
# --- 基础列表功能 ---
autoindex on; # 开启目录列表
autoindex_exact_size off; # 关闭精确字节,显示为 KB/MB/GB(更人性化)
autoindex_localtime on; # 显示服务器本地时间(而非 GMT 时间)
# --- 解决中文乱码 ---
# 如果文件名包含中文,浏览器可能会乱码,强制设置字符集
charset utf-8,gbk;
# --- 强制下载功能 (关键点) ---
# 默认情况下,txt/pdf/jpg 会在浏览器打开。
# 下面的配置强制特定后缀的文件弹出“下载”对话框
if ($request_filename ~* ^.*?\.(txt|doc|pdf|zip|rar|jpg|png)$) {
add_header Content-Disposition 'attachment;';
}
}
}
- Post link: http://sovzn.github.io/2026/03/22/Nginx/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.



若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues