主题
nginx.conf
自动匹配 CPU 核心数
worker_processes auto;events
shell
events {
worker_connections 1024;
multi_accept on;
use epoll; # Linux epoll,windows select
}windows select
location 匹配优先级
shell
# 优先级从高到低
# 1. 精确匹配 (=)
location = /exact {
# 只匹配 /exact
}
# 2. 优先匹配 (^~) - 匹配后跳过正则
location ^~ /static {
# 匹配 /static 开头,不检查正则
}
# 3. 正则匹配 (~ 大小写敏感, ~* 大小写不敏感)
location ~ \.js$ {
# 匹配 .js 结尾
}
location ~* \.(jpg|png)$ {
# 匹配图片文件
}
# 4. 普通匹配
location /api {
# 匹配 /api 开头
}
# 5. 默认匹配
location / {
# 匹配所有
}匹配规则:
- 如果匹配到 ^~ 前缀
- 立即停止匹配
- 不再检查任何正则
所有 /demo 开头的请求都由这个 location 处理
shell
location ^~ /demo {
root html;
# Vue Router history 模式
try_files $uri $uri/ /demo/index.html;
}与
shell
location /demo {
root html;
try_files $uri $uri/ /demo/index.html;
}location /api 普通字符串匹配
日志
shell
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time';
access_log logs/access.log main;
error_log logs/error.log warn;SSL/TLS 配置
shell
listen 443 ssl http2;
server_name xxxx;
# SSL 证书
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;浏览器缓存
shell
# 静态资源长期缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
access_log off;
log_not_found off;
}
# HTML 短期缓存
location ~* \.(html|htm)$ {
expires 5m;
add_header Cache-Control "public, must-revalidate";
}
# API 不缓存
location /api/ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
}vue服务
shell
server {
listen 80;
server_name xxxx;
root html;
index index.html;
# 使用 ^~ 确保所有子路径都由此处理
location ^~ /demo {
root html;
index index.html;
# Vue Router history 模式支持
try_files $uri $uri/ /demo/index.html;
# 静态资源缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
}
}SSE/流式响应配置
shell
location /aiapi/cs/chat {
proxy_pass http://xxx:8100/aiapi/cs/chat;
include proxy_settings.conf;
proxy_buffering off;
proxy_cache off;
proxy_set_header Content-Type "text/event-stream";
proxy_set_header Cache-Control "no-cache";
add_header X-Accel-Buffering "no";
}性能优化
慢请求判断:
- 如果 $upstream_response_time 大 → 后端问题
- 如果 $request_time - $upstream_response_time 大 → 网络/文件大小问题
- 如果两者都大 → 全链路都有问题
shell
curl -w "\n
DNS: %{time_namelookup}s
TCP: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s\n" \
-o /dev/null -s https://xxxx/app.f5826951.jsDNS: 0.030905s
TCP: 0.032735s
TLS: 0.078743s
TTFB: 0.098947s
Total: 0.105596s
DNS: 0.030905s (30.9ms) ← DNS 查询
TCP: 0.032735s (32.7ms) ← TCP 三次握手
TLS: 0.078743s (78.7ms) ← TLS/SSL 加密握手
TTFB: 0.098947s (98.9ms) ← 从发送请求到收到第一个字节
Total: 0.105596s (105.6ms) ← 完整请求总耗时
阶段 耗时 说明
DNS: 30.9ms DNS 查询
TCP 32.7ms 建立 TCP 连接(三次握手) 32.7 - 30.9 = 1.8ms
TLS 46.0ms TLS 握手(加密协商) 78.7 - 32.7 = 46.0ms
TTFB 20.2ms 服务器处理时间 98.9 - 78.7 = 20.2ms
Content 6.6ms 下载内容时间 105.6 - 98.9 = 6.7ms
总耗时 105.6ms 完整请求时间
0ms 32.7ms 78.7ms 98.9ms 105.6ms
│ │ │ │ │
├─ TCP ────┤── TLS ────┤─ TTFB ────┤─ Content ──┤
│ 32.7ms │ 46.0ms │ 20.2ms │ 6.7ms │
│ │ │ │ │
└───────────┴────────────┴───────────┴────────────┘直接nginx负载静态文件
后续文件直接
shell
location ^~ /mglibs {
root html;
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
}accept-ranges: bytes
cache-control: max-age=31536000
cache-control: public, immutable
content-length: 143643
content-type: text/plain
date: Wed, 12 Aug 2026 02:57:04 GMT
etag: "6a7bdde3-2311b"
expires: Thu, 12 Aug 2027 02:57:04 GMT
last-modified: Wed, 12 Aug 2026 02:43:47 GMT
server: nginxshell
$ curl -I https://xxxx/mglibs/axios/1.11.0/axios.min.js
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 12 Aug 2026 05:58:47 GMT
Content-Type: application/javascript
Content-Length: 54487
Last-Modified: Wed, 12 Aug 2026 02:43:47 GMT
Connection: keep-alive
ETag: "6a7bdde3-d4d7"
Expires: Thu, 12 Aug 2027 05:58:47 GMT
Cache-Control: max-age=31536000
Cache-Control: public, immutable
Accept-Ranges: bytes开启gzip
响应头中没有content-encoding字段(如gzip或br),说明Nginx没有对该JS文件启用压缩。 149KB的未压缩JS文件在移动网络下传输,加上可能存在的网络波动,耗时57秒是可以解释的。
未启用gzip压缩 152kB
shell
accept-ranges: bytes
content-length: 152856
content-type: application/javascript
date: Thu, 13 Aug 2026 04:36:07 GMT
etag: "6a79a75c-25518"
last-modified: Mon, 10 Aug 2026 10:26:36 GMT
server: nginx启用gzip压缩
http {
gzip on;
gzip_vary on;
gzip_comp_level 9;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss;
}
响应头:
content-encoding: gzip
content-type: application/javascript
date: Thu, 13 Aug 2026 06:33:28 GMT
etag: W/"6a79a75c-25518"
last-modified: Mon, 10 Aug 2026 10:26:36 GMT
server: nginx
vary: Accept-Encoding获取资源文件压缩后的大小
shell
curl -s -H "Accept-Encoding: gzip" xxxxx/js/chunk-vendors.bb3caf12.js -o /dev/null -w "压缩后大小: %{size_download} bytes\n"
: 51067 bytes配置生效依据
shell
Content-Encoding: gzip
Vary: Accept-Encoding
ETag: W/"..." 弱校验,符合Gzip规范[13/Aug/2026:10:07:07 +0800] "GET /xxx/css/chunk-vendors.d82739c0.css HTTP/2.0" 200 66583 [13/Aug/2026:14:51:33 +0800] "GET /xxx/css/chunk-vendors.d82739c0.css HTTP/2.0" 200 32756
sendfile 零拷贝
开启后:硬盘 → 内核缓冲区 → 网卡
未开启:硬盘 → 内核缓冲区 → 用户缓冲区(Nginx) → 内核Socket缓冲区 → 网卡
当 sendfile 和 gzip 同时启用时,Nginx 会自动判断文件大小,对小文件使用 sendfile,对大文件使用传统方式配合压缩。
server {
sendfile on;
}
### 强制请求头
```shell
location ^~ /xxx {
root html;
if ($request_uri ~ \.js$) {
add_header Content-Type "application/javascript" always;
}
if ($request_uri ~ \.css$) {
add_header Content-Type "text/css" always;
}
if ($request_uri ~ \.html$) {
add_header Content-Type "text/html" always;
}
try_files $uri $uri/ /xxx/index.html;
}安全
封禁IP - 对整站所有请求生效
shell
server {
deny xxx.xxx.xxx.xxx;
...
}