一 概念
Nginx 是一个高性能的 HTTP 服务器和反向代理服务器,核心作用是高效处理网络请求、转发流量、提供静态资源服务。它最常出现在以下场景中:
-
反向代理
这是 Nginx 最核心的用途之一。客户端请求先到 Nginx,再由它转发给后端的应用服务器(如 Tomcat、Node.js、Python、Java 服务),然后把结果返回给客户端。这样做的好处是隐藏后端真实地址、统一入口、方便做负载均衡和 HTTPS 卸载。 -
负载均衡
当后端有多台服务器时,Nginx 可以把请求按轮询、加权、IP 哈希等策略分发到不同机器上,提升整体吞吐量和可用性。常见于 Web 集群、微服务网关前置层。 -
静态资源服务
Nginx 处理静态文件(HTML、CSS、JS、图片、视频)的效率非常高,常用来直接托管前端打包后的文件,或者作为 CDN 边缘节点。相比让应用服务器处理静态文件,Nginx 更省资源、响应更快。 -
HTTPS termination(SSL 卸载)
证书配置在 Nginx 上,由它负责加解密,后端应用只处理明文 HTTP。这样简化了后端配置,也集中管理了证书。 -
缓存与压缩
Nginx 可以缓存后端响应,减少后端压力;也可以对返回内容做 gzip/brotli 压缩,节省带宽。 -
限流、防盗链、访问控制
通过 limit_req、limit_conn 做请求频率和连接数限制;通过 valid_referers 防盗链;通过 allow/deny 做 IP 白名单黑名单。 -
动静分离
把静态请求和动态请求分开处理:静态走 Nginx 本地或专用静态服务器,动态转发给后端应用。这是很经典的架构模式。
典型使用场景举例:
网站入口网关:所有流量先经过 Nginx,再分发到后端服务
前后端分离项目:Nginx 托管前端 dist 文件,同时代理 /api 到后端
微服务 API 网关前置:配合 Kong、Traefik 或直接由 Nginx 做路由
高并发静态站点:直接作为 Web 服务器提供页面和资源
内网服务对外暴露:通过反向代理 + HTTPS 统一出口
简单说,Nginx 在现代架构里通常扮演流量入口 + 静态服务器 + 反向代理 + 负载均衡器这几个角色,是 Web 基础设施中非常常见的一层。
二 配置文件命令解读
1 server {listen 443 ssl http2;}
这里的关键是:listen 443 ssl http2; 里的 ssl 和 http2 都是加在这个监听端口上的"能力开关",不是协议名本身。
所以 listen 443 ssl http2; = 在 443 端口上,提供"加密 + HTTP/2"的服务。
先拆开看这条指令的结构:
443 —— 端口号
ssl —— 告诉 Nginx:这个端口上的连接要用 TLS/SSL 加密来处理
http2 —— 告诉 Nginx:这个端口支持 HTTP/2 协议
- ssl 是什么意思?
443 端口是 HTTPS 的默认端口,但端口号本身并不自动带来加密。你完全可以让 443 端口跑明文 HTTP。
ssl 这个参数的作用是:让 Nginx 在这个监听端口上启用 TLS 层。启用后,Nginx 会:
在建立连接时先做 TLS 握手(交换证书、协商密钥)之后所有数据都在加密通道里传输使用同一个 server 块里配置的 ssl_certificate 和 ssl_certificate_key
所以 ssl 是给这个端口"套上加密层"的开关。没有它,就算你写了 ssl_certificate,Nginx 也不会在这个端口上用证书。
一个直观的对比:
listen 443; # 443 端口,但走明文 HTTP
listen 443 ssl; # 443 端口,走 TLS 加密(即 HTTPS)
- http2 是什么意思?
http2 是让这个端口支持 HTTP/2 协议。HTTP/2 是 HTTP/1.1 的升级版,主要改进:
多路复用:一个 TCP 连接上可以并行传多个请求,不用排队
头部压缩:减少重复的请求头开销
二进制分帧:传输效率更高
服务端推送(Nginx 支持有限)
在 Nginx 里,HTTP/2 是基于 TLS 之上运行的(浏览器基本只支持加密的 HTTP/2,即 h2)。所以通常写成 listen 443 ssl http2;,先有 ssl 再有 http2。
- 这两个参数合起来的效果
listen 443 ssl http2;
可以翻译成一句话:
监听 443 端口;进来的连接先经过 TLS 加密(ssl);加密通道里跑的是 HTTP/2 协议(http2)。
数据流向大致是:
客户端
│ ① TCP 连接到 443
▼
Nginx 443 端口
│ ② TLS 握手(因为开了 ssl)
▼
加密通道
│ ③ 在通道里用 HTTP/2 解析请求(因为开了 http2)
▼
交给对应的 server / location 处理
- 几个容易混淆的点
ssl 和 http2 都是写在 listen 后面的参数,不是独立的指令。
如果你写 listen 443 ssl; 而没有 http2,那这个端口就是 HTTPS + HTTP/1.1。
较新版本的 Nginx(1.25.1+)推荐把 HTTP/2 单独写成 http2 on; 指令,而不是放在 listen 后面。两种写法目前都还能用:
- 新旧写法
旧写法(仍然兼容)
listen 443 ssl http2;
新写法(Nginx 1.25.1+ 推荐)
listen 443 ssl;
http2 on;
http2 不能单独用在明文端口上(listen 80 http2; 在浏览器里基本没用),因为主流浏览器只支持基于 TLS 的 HTTP/2。
2 server name
server_name 到底是什么?server_name 不是变量,而是虚拟主机的匹配规则。
它的作用是:当有请求到达这个端口时,Nginx 会看请求头里的 Host 字段(也就是用户访问的域名),然后拿它去和各个 server 块里的 server_name 做比对,决定用哪个 server 块来处理这个请求。
server {
listen 443 ssl http2;
server_name example.com www.example.com;
...
}
意思是:如果用户访问的是 example.com 或 www.example.com,就用我这个 server 块来处理。
所以 server_name 更像是这个虚拟主机的"域名标签"或"匹配条件",而不是一个可以被后面引用的变量。
它和变量最大的区别:
变量(比如 $host、$remote_addr)是可以在配置里被引用、参与计算的。
server_name 只是一个声明,告诉 Nginx "我负责这些域名",后面不能写 $server_name 去取它的值来当普通变量用(虽然 Nginx 内部有个 $server_name 变量,但那是另一回事,取的是匹配到的名字,不是让你在这里赋值)。
- 那"括号"是指什么?
看到的 { } 是 Nginx 配置的块(block)语法,不是域名的一部分。
server {
...
}
这一对花括号包起来的部分,叫做一个 server 块,也就是一个"虚拟主机"的配置。花括号的作用是划定作用范围:
写在 server { } 里面的指令,只对这个虚拟主机生效。
写在 http { } 里面的,对所有虚拟主机生效。
写在 location { } 里面的,只对匹配到的路径生效。
所以花括号是配置的分组边界,跟域名没有关系。域名是写在 server_name 后面的那串字符。
- 用个类比理解
可以把 Nginx 想象成一栋写字楼(http 块):
楼里有很多间办公室,每间就是一个 server { } 块(虚拟主机)。
每间办公室门口挂个牌子,写着"我负责接待 example.com 和 www.example.com 的访客"——这个牌子就是 server_name。
访客(请求)进楼后,前台看他要找哪个域名,就把他领到对应牌子的办公室。
花括号就是这间办公室的四面墙,划定了"这间屋里的事只在这间屋里算数"。
- 补充几个实际要点
server_name 可以写多个域名,用空格隔开,表示这个 server 块同时负责这几个域名。
可以写通配符:server_name *.example.com;
可以写正则:server_name ~^www\d+.example.com$;
如果所有 server_name 都没匹配上,Nginx 会用这个端口上的默认 server(第一个出现的,或者用 default_server 标记的那个)来处理。
server_name 后面不写分号以外的符号,多个域名之间只空格,不加逗号。
server_name example.com www.example.com; # 正确
server_name example.com, www.example.com; # 错误,逗号会被当成域名的一部分
一句话总结:
server_name 是虚拟主机的域名匹配规则,不是变量;{ } 是配置块的范围边界,不是括号。
两者都不是"域就是括号"这种关系——域名写在 server_name 后面,花括号只是把一组配置圈起来。
配置文件示例
# =========================================================
# Nginx 主配置文件示例
# 路径通常为 /etc/nginx/nginx.conf
# =========================================================
# 运行 Nginx 的用户和用户组
# 一般用 www-data(Ubuntu/Debian)或 nginx(CentOS/RHEL)
user www-data;
# 工作进程数
# auto 表示自动根据 CPU 核心数设置,通常等于 CPU 核数
worker_processes auto;
# 每个 worker 可打开的文件描述符数量
# 高并发场景需要调大,需同时调整系统 ulimit
worker_rlimit_nofile 65535;
# 错误日志路径和级别
# 级别可选:debug | info | notice | warn | error | crit | alert | emerg
error_log /var/log/nginx/error.log warn;
# PID 文件路径
pid /var/run/nginx.pid;
# =========================================================
# events 块:连接处理相关配置
# =========================================================
events {
# 每个 worker 允许的最大并发连接数
worker_connections 10240;
# 使用 epoll 事件模型(Linux 下性能最好)
use epoll;
# 一个 worker 同时接受多个新连接
multi_accept on;
}
# =========================================================
# http 块:所有 HTTP 相关配置
# =========================================================
http {
# ---------- 基础配置 ----------
# 引入 MIME 类型映射,告诉浏览器文件类型
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式定义
# $remote_addr 客户端 IP
# $remote_user 客户端用户(一般为空)
# $time_local 本地时间
# $request 请求行
# $status 响应状态码
# $body_bytes_sent 响应体字节数
# $http_referer 来源页面
# $http_user_agent 客户端 UA
# $http_x_forwarded_for 经过代理后的真实 IP 链
# $request_time 请求处理总时间
# $upstream_response_time 后端响应时间
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time urt=$upstream_response_time';
# 访问日志路径和使用的格式
access_log /var/log/nginx/access.log main;
# 开启 sendfile,零拷贝提升静态文件传输效率
sendfile on;
# 配合 sendfile 使用,减少网络报文数量
tcp_nopush on;
# 不缓存小包,降低延迟
tcp_nodelay on;
# 长连接超时时间,单位秒
keepalive_timeout 65;
# 客户端请求头超时时间
client_header_timeout 15;
# 客户端请求体超时时间
client_body_timeout 15;
# 发送响应超时时间
send_timeout 15;
# 隐藏 Nginx 版本号,提升安全性
server_tokens off;
# 客户端请求体最大大小(影响上传文件大小)
client_max_body_size 50m;
# 请求头缓冲区大小
client_header_buffer_size 4k;
# 大请求头缓冲区
large_client_header_buffers 4 16k;
# ---------- 文件缓存 ----------
# 打开文件缓存,减少磁盘 IO
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# ---------- Gzip 压缩 ----------
# 开启 gzip 压缩,减少传输体积
gzip on;
# 最小压缩长度,小于该值不压缩
gzip_min_length 1k;
# 压缩缓冲区
gzip_buffers 4 16k;
# 压缩级别 1-9,越高越耗 CPU
gzip_comp_level 5;
# 需要压缩的 MIME 类型
gzip_types text/plain text/css text/xml
application/json application/javascript
application/xml application/xml+rss
image/svg+xml;
# 是否在响应头中添加 Vary: Accept-Encoding
gzip_vary on;
# 对代理请求也启用压缩
gzip_proxied any;
# 禁用 IE6 的 gzip
gzip_disable "MSIE [1-6]\.";
# ---------- 限流配置 ----------
# 定义限流区域:按客户端 IP 限制请求频率
# zone=req_limit:10m 表示区域名和共享内存大小
# rate=10r/s 表示每秒最多 10 个请求
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 定义连接数限制区域:按 IP 限制并发连接数
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# ---------- 负载均衡配置 ----------
# 定义后端服务器组,组名 backend_servers
upstream backend_servers {
# 负载均衡策略,默认轮询
# 可选:least_conn(最少连接)、ip_hash(按 IP 哈希)
least_conn;
# 后端服务器列表
# weight=1 权重,越大分配请求越多
# max_fails=3 最大失败次数
# fail_timeout=30s 失败后暂停时间
server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 weight=1 max_fails=3 fail_timeout=30s;
# 备用服务器,主服务器全部不可用时启用
# server 127.0.0.1:8082 backup;
# 长连接保持,减少握手开销
keepalive 32;
}
# ---------- 代理通用配置 ----------
# 代理请求头,传递真实客户端信息
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;
# 代理连接超时
proxy_connect_timeout 30s;
# 代理读取超时
proxy_read_timeout 60s;
# 代理发送超时
proxy_send_timeout 60s;
# 开启代理缓冲
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
proxy_busy_buffers_size 16k;
# 后端返回错误时,尝试下一台服务器
proxy_next_upstream error timeout http_502 http_503 http_504;
# =========================================================
# 虚拟主机 1:HTTP 跳转到 HTTPS
# =========================================================
server {
listen 80;
server_name example.com www.example.com;
# 所有 HTTP 请求永久重定向到 HTTPS
return 301 https://$host$request_uri;
}
# =========================================================
# 虚拟主机 2:HTTPS 主站
# =========================================================
server {
# 监听 443 端口,开启 SSL【Secure Sockets Layer中文:(安全套接字层)】 和 HTTP/2
# Hyper Text Transfer Protocol Secure(超文本传输安全协议)
listen 443 ssl http2;
server_name example.com www.example.com;
# ---------- SSL 证书配置 ----------
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 ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# 优先使用服务端加密套件
ssl_prefer_server_ciphers on;
# SSL 会话缓存,提升握手效率
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 开启 HSTS,强制浏览器使用 HTTPS
add_header Strict-Transport-Security "max-age=31536000" always;
# 防止点击劫持
add_header X-Frame-Options SAMEORIGIN always;
# 禁止 MIME 类型嗅探
add_header X-Content-Type-Options nosniff always;
# ---------- 限流应用 ----------
# 应用请求频率限制,burst=20 允许突发 20 个请求
# nodelay 表示突发请求立即处理,不排队
limit_req zone=req_limit burst=20 nodelay;
# 限制单 IP 并发连接数
limit_conn conn_limit 20;
# ---------- 根路径:静态前端 ----------
location / {
# 前端打包后的静态文件目录
root /var/www/frontend/dist;
index index.html;
# 尝试找文件,找不到则回退到 index.html
# 适用于 Vue/React 等 SPA 前端路由
try_files $uri $uri/ /index.html;
}
# ---------- 静态资源缓存 ----------
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
root /var/www/frontend/dist;
# 浏览器缓存 30 天
expires 30d;
# 添加缓存控制头
add_header Cache-Control "public, immutable";
# 关闭访问日志,减少日志量
access_log off;
}
# ---------- API 反向代理 ----------
location /api/ {
# 转发到后端服务器组
proxy_pass http://backend_servers/;
# 传递真实客户端信息
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";
# 不缓存 API 响应
proxy_buffering off;
}
# ---------- 后端管理接口,限制 IP ----------
location /admin/ {
# 只允许指定网段访问
allow 192.168.1.0/24;
allow 10.0.0.0/8;
# 其他全部拒绝
deny all;
proxy_pass http://backend_servers/admin/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# ---------- 健康检查接口 ----------
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
# ---------- 禁止访问隐藏文件 ----------
location ~ /\. {
deny all;
}
}
# =========================================================
# 虚拟主机 3:静态资源站点(可选)
# =========================================================
server {
listen 80;
server_name static.example.com;
root /var/www/static;
index index.html;
# 开启目录浏览(按需开启,生产慎用)
# autoindex on;
location / {
try_files $uri $uri/ =404;
}
# 图片、视频等大文件缓存
location ~* \.(mp4|webm|ogg|mp3|wav|flac|aac)$ {
expires 7d;
add_header Cache-Control "public";
}
}
}