一、什么是动静分离?
动静分离(Separation of Dynamic and Static Content)指的是让 Nginx 针对动态请求(如 PHP、Java、Python 等后端生成的页面或接口)和静态资源(如图片、JS、CSS、HTML 等文件)分别采用不同的处理方式和后端,提高性能和可扩展性。
核心目标:
- 静态资源直接由 Nginx 高效处理,减轻后端压力。
- 动态请求转发到后端应用服务器(如 PHP-FPM、Tomcat、Gunicorn 等)。
- 可结合 CDN、缓存进一步优化静态资源访问。
二、典型动静分离架构
+-----------------------+
| 用户浏览器 |
+-----------------------+
|
v
+-----------------------+
| Nginx |
|-----------------------|
| 静态资源 | 动态请求 |
+-----------------------+
| |
+-------------+ +-----------------+
| 静态文件 | | 后端应用服务器 |
+-------------+ +-----------------+
三、Nginx 动静分离配置详解
1. 基本配置模板
假设你的静态资源都在 /var/www/static/,动态请求以 .php 结尾。
server {
listen 80;
server_name www.example.com;
# 静态资源处理
location /static/ {
root /var/www;
expires 30d;
add_header Cache-Control public;
}
location ~* \.(jpg|jpeg|png|gif|css|js|ico|woff|svg|html)$ {
root /var/www/static;
expires 7d;
add_header Cache-Control public;
}
# 动态请求转发到后端
location ~ \.php$ {
root /var/www/html;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# 其他动态后端如 Java、Python
# location /api/ {
# proxy_pass http://127.0.0.1:8080;
# }
}
2. 动静分离的关键点
- 静态资源用 root/alias,直接由 Nginx 处理,不经过后端。
- 动态请求通过 fastcgi_pass 或 proxy_pass 转发到后端应用。
- 可以用正则 location 匹配静态文件扩展名。
- 静态资源可设置 expires/cache-control 头,提升缓存命中率。
3. 进阶配置:防止静态资源被动态处理
有时候静态资源目录和动态目录有交集,要防止误处理:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
try_files优先尝试静态文件,找不到时再走动态后端。
4. 多后端动静分离
适合微服务或多语言后端:
server {
listen 80;
server_name www.example.com;
# 静态资源
location /assets/ {
root /data/static;
expires 30d;
}
# PHP 动态
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm.sock;
root /data/php;
...
}
# Java 动态
location /javaapi/ {
proxy_pass http://127.0.0.1:8081;
}
}
四、动静分离优化建议
- 静态资源建议部署在独立目录甚至独立域名(如 static.example.com),方便 CDN 加速和缓存。
- 静态资源开启 gzip 压缩:
gzip on; gzip_types text/css application/javascript image/svg+xml; - 合理设置缓存头,提高前端和 CDN 命中率。
- 动态内容建议关闭缓存,防止数据串号。
- 可以结合 OpenResty/Lua 动态控制缓存和后端分流。
五、动静分离常见问题排查
- 静态资源 404?
- 检查 root/alias 路径,文件是否存在,权限是否正确。
- 动态请求被当成静态处理?
- 检查 location 优先级,正则 location 要在普通 location 后面。
- 缓存未生效?
- 检查 expires、cache-control 头部是否正确设置。
- 静态资源未走 CDN?
- 检查静态资源是否分离至独立域名,CDN 配置是否正确。
六、动静分离与 CDN、微服务结合
- 静态资源可以通过 CDN 分发,进一步提升全球访问速度。
- 动态请求可以根据 URI、参数、Cookie 等分流到不同后端服务,支持微服务架构。
- 结合缓存和动静分离,可极大提升网站性能和稳定性。
七、动静分离完整示例(含 CDN)
server {
listen 80;
server_name www.example.com;
# 静态资源独立域名
location /static/ {
root /data/static;
expires 30d;
add_header Cache-Control "public";
}
# 动态(PHP)
location ~ \.php$ {
root /data/php;
fastcgi_pass unix:/run/php-fpm.sock;
...
}
# 动态(API微服务)
location /api/ {
proxy_pass http://127.0.0.1:9000;
}
# 主页优先静态,找不到再转动态
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
八、参考资料
九、更复杂的目录结构与 alias 用法
有时静态资源和动态文件目录结构复杂,alias 能灵活映射请求路径到实际文件系统路径。
示例:alias 映射
location /assets/ {
alias /data/project/static/; # 注意 alias 结尾要加斜杠
expires 30d;
add_header Cache-Control public;
}
/assets/logo.png实际访问/data/project/static/logo.pngalias用于将请求路径和磁盘目录做非线性映射,适合多项目或多版本场景。
注意事项
alias和root不能混用,配置时要确保路径拼接正确。- 用
alias时,fastcgi_param SCRIPT_FILENAME需手动拼接真实路径。
十、静态资源版本管理(防止缓存脏数据)
前端常用文件名加 hash(如 main.abc123.js),Nginx 动静分离时建议:
- 静态资源路径
/static/v1.0.1/main.abc123.js - 每次发布新版本,路径或文件名变化,自动绕过 CDN 或浏览器缓存。
Nginx 配置建议
location ~* /static/.+\.(js|css|png|jpg|jpeg|gif|svg|woff|ttf)$ {
root /data/static;
expires 30d;
add_header Cache-Control public;
}
这样每次文件名变化,缓存自动失效,无需手动刷新。
十一、CDN集成动静分离
1. 静态资源走 CDN
- 静态资源建议用独立域名,如
static.example.com - CDN 配置只回源 Nginx 的静态资源路径
2. 动态请求不走 CDN
- 动态接口、页面走主域名,Nginx反向代理到后端应用
3. Nginx 配置示例
# 静态资源
server {
listen 80;
server_name static.example.com;
location / {
root /data/static;
expires 30d;
add_header Cache-Control public;
}
}
# 动态站点
server {
listen 80;
server_name www.example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /data/php;
fastcgi_pass unix:/run/php-fpm.sock;
...
}
}
CDN只配置
static.example.com,动静彻底分离,资源缓存和加速效果最佳。
十二、动静分离自动化与监控
1. 自动化部署
- 前端构建后自动上传静态资源到 Nginx 静态目录或对象存储/CDN
- 后端代码独立部署,Nginx配置不需频繁调整
2. 监控建议
- 监控静态资源访问量、404率、缓存命中率
- 监控动态接口响应时间、后端健康状态
- 用 Nginx
access.log分别记录静态与动态请求,便于分析
3. 日志分流示例
access_log /var/log/nginx/static_access.log main if=$is_static;
access_log /var/log/nginx/dynamic_access.log main if=$is_dynamic;
需要在 Lua 或 map 中动态设置
$is_static、$is_dynamic
十三、性能调优建议
-
静态资源开启多进程和 sendfile
sendfile on; tcp_nopush on; aio on; -
开启 HTTP/2 支持静态资源多路复用
listen 443 ssl http2; -
静态资源开启 gzip 压缩和 brotli(如支持)
gzip on; gzip_types text/css application/javascript image/svg+xml;Brotli 需安装模块。
-
合理配置 worker_processes、worker_connections
worker_processes auto; worker_connections 10240; -
静态资源用 CDN,动态接口用缓存(如 Redis)优化后端性能
十四、动静分离常见问题进阶分析
- alias 配置错误导致 404?
- 检查 alias 路径,确保请求路径和文件系统路径拼接正确。
- 静态资源被动态 location 捕获?
- location 匹配顺序:精确 > 正则 > 通配,正则 location 放最后。
- 静态资源更新后 CDN 仍返回旧文件?
- 文件名加 hash,或配置 CDN 强制刷新。
- 动态接口被缓存导致数据串号?
- 动态 location 禁止缓存,或用缓存键区分用户、参数。
十五、动静分离与微服务、API网关结合
- Nginx 可作为 API 网关,动静分离后,动态接口可进一步按 URI、Header、参数分流到不同微服务后端。
- 静态资源可统一走 CDN,动态接口支持灰度发布、限流、鉴权等高级功能。
十六、完整动静分离生产配置模板
# 静态资源独立域名
server {
listen 80;
server_name static.example.com;
location / {
root /data/static;
expires 30d;
add_header Cache-Control public;
gzip on;
gzip_types text/css application/javascript image/svg+xml;
}
}
# 动态站点
server {
listen 80;
server_name www.example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /data/php;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /api/ {
proxy_pass http://127.0.0.1:9000;
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;
}
}
十七、多站点动静分离
如果你有多个业务站点(如主站、博客、活动页等),可以用 Nginx 的 server_name 和多 server 块实现动静分离:
# 静态资源统一域名
server {
listen 80;
server_name static.example.com;
location / {
root /data/static;
expires 30d;
add_header Cache-Control public;
}
}
# 主站
server {
listen 80;
server_name www.example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /data/php;
fastcgi_pass unix:/run/php-fpm.sock;
...
}
}
# 博客
server {
listen 80;
server_name blog.example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /data/blog;
fastcgi_pass unix:/run/php-fpm.sock;
...
}
}
优势:
- 静态资源统一管理和缓存
- 各业务站点独立,易于维护和扩展
十八、前端 SPA 和 SSR 场景动静分离
现代前端(Vue/React/Angular)项目常用 SPA(单页应用)或 SSR(服务端渲染),动静分离方式略有不同:
SPA 场景
- 所有静态资源(HTML、JS、CSS、图片等)由 Nginx 静态目录或 CDN 提供
- 路由全部由前端 JS 控制,Nginx 配置如下:
location / {
try_files $uri $uri/ /index.html;
}
这样所有未命中的路径都返回
index.html,由前端路由处理。
SSR 场景
- 静态资源仍由 Nginx 或 CDN 提供
- 动态页面请求转发到 Node.js/Go/PHP 等后端服务:
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
location ~* \.(js|css|png|jpg|svg)$ {
root /data/static;
expires 30d;
add_header Cache-Control public;
}
十九、静态资源高可用与回源
1. 多机部署静态资源
- 静态资源目录同步到多台 Nginx 服务器(用 rsync、CI/CD、对象存储等)
- 结合负载均衡和健康检查,确保高可用
2. CDN 回源配置
- CDN 首选缓存静态资源,缓存失效时自动回源 Nginx
- Nginx 配置合理的
expires和cache-control,提升 CDN 命中率
3. 回源防盗链
location / {
valid_referers none blocked *.example.com;
if ($invalid_referer) {
return 403;
}
}
防止第三方盗链静态资源,保护带宽和版权
二十、动静分离安全加固
- 静态资源目录禁止执行脚本
location /static/ { root /data/static; location ~ \.php$ { deny all; } } - 防止目录遍历
autoindex off; - 限制静态资源上传类型和大小(如用于图片直传)
client_max_body_size 2M;
二十一、动静分离与对象存储结合
- 前端构建产物上传到 OSS、COS、S3 等对象存储
- CDN 配置对象存储为源站,Nginx 仅做动态接口反向代理
- 资源更新自动同步到对象存储,彻底解耦静态与动态
典型架构:
用户 -> CDN -> 对象存储(静态) + Nginx(动态)
二十二、企业级运维与自动化建议
- 静态资源自动发布脚本
- 前端构建后自动上传到 Nginx 静态目录或对象存储
- 自动刷新 CDN 缓存
- 灰度发布静态资源
- 采用版本号或 hash 路径,支持灰度和回滚
- 日志分流与监控
- access.log 分静态、动态,分析性能和异常
- 配合 ELK/Prometheus 监控 QPS、响应时间、错误率
- 高可用架构
- 静态多机部署+负载均衡,动态多后端+健康检查
- 自动化同步和故障切换
- 安全审计
- 定期扫描静态资源目录,防止上传恶意脚本
- Nginx 配置严格访问控制
二十三、动静分离实战总结
- 静态资源建议独立域名+CDN+对象存储,极致加速和高可用
- 动态接口建议反向代理到后端,关闭缓存,配合微服务架构
- 复杂场景用 alias、try_files、正则 location 灵活配置
- 自动化运维和安全加固是大规模动静分离架构的必备
6234

被折叠的 条评论
为什么被折叠?



