1. 为什么需要Nginx配置前后端服务?
在当今的Web开发架构中,前后端分离已成为主流模式。这种架构下,前端(通常是React、Vue等框架构建的SPA应用)和后端(如Spring Boot、Node.js等服务)独立开发部署,而Nginx作为高性能的Web服务器和反向代理,在两者之间扮演着关键角色。
我经历过多个项目从传统单体架构到前后端分离的迁移过程,Nginx的配置往往是部署环节中最容易出问题的地方。一个典型的场景是:前端开发人员打包好的静态文件需要被正确服务,同时API请求需要被代理到后端服务器,还要处理跨域、缓存、HTTPS等各种问题。
2. Nginx基础环境准备
2.1 Nginx安装与基本命令
在开始配置前,我们需要确保Nginx已正确安装。以Ubuntu系统为例:
# 更新包列表 sudo apt update # 安装Nginx sudo apt install nginx # 启动Nginx sudo systemctl start nginx # 设置开机自启 sudo systemctl enable nginx # 检查状态 sudo systemctl status nginx关键命令备忘:
- 重启Nginx:
sudo systemctl restart nginx - 重新加载配置(不中断服务):
sudo nginx -s reload - 测试配置文件:
sudo nginx -t
2.2 配置文件结构理解
Nginx的主配置文件通常位于/etc/nginx/nginx.conf,但最佳实践是在/etc/nginx/conf.d/或/etc/nginx/sites-available/中创建独立的配置文件。一个基本的配置文件结构如下:
# 全局配置块 user www-data; worker_processes auto; # 事件块 events { worker_connections 1024; } # HTTP块 http { include /etc/nginx/mime.types; # 服务器块(虚拟主机) server { listen 80; server_name example.com; # 位置块 location / { root /var/www/html; index index.html; } } }3. 前端服务配置详解
3.1 静态文件服务配置
假设你的前端项目已经构建(如Vue的npm run build),生成的静态文件位于/var/www/frontend/dist:
server { listen 80; server_name yourdomain.com; root /var/www/frontend/dist; index index.html; location / { try_files $uri $uri/ /index.html; } # 静态资源缓存配置 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, no-transform"; } }关键点说明:
try_files指令确保前端路由能正常工作(如Vue Router的history模式)- 静态资源设置长期缓存,利用浏览器缓存提升性能
- 记得设置正确的文件权限:
sudo chown -R www-data:www-data /var/www/frontend
3.2 性能优化配置
# 开启gzip压缩 gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 文件传输优化 sendfile on; tcp_nopush on; tcp_nodelay on; # 连接超时设置 keepalive_timeout 65;4. 后端服务代理配置
4.1 基础API代理配置
假设后端服务运行在http://localhost:3000:
server { listen 80; server_name api.yourdomain.com; location / { proxy_pass http://localhost: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; } }4.2 高级代理配置
location /api/ { proxy_pass http://backend_server/; # 注意结尾的斜杠 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 缓冲区配置 proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; }4.3 WebSocket代理
对于需要WebSocket支持的应用:
location /ws/ { proxy_pass http://websocket_server; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; }5. 完整前后端分离配置示例
以下是一个生产环境常用的完整配置示例,整合了前后端:
# 前端配置 server { listen 80; server_name app.yourdomain.com; root /var/www/frontend/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public"; } } # 后端API配置 server { listen 80; server_name api.yourdomain.com; location / { proxy_pass http://localhost: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; # CORS配置 add_header 'Access-Control-Allow-Origin' 'app.yourdomain.com'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } # 静态文件直接服务 location /public/ { alias /var/www/backend/public/; expires 7d; } }6. 常见问题与解决方案
6.1 跨域问题处理
虽然前后端分离架构本身就会遇到跨域问题,但通过Nginx可以优雅解决:
# 在API服务器配置中添加 location / { # ...其他proxy配置 # CORS配置 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'app.yourdomain.com'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } }6.2 静态资源404问题
常见原因及解决方案:
- 路径错误:确保
root或alias指向正确的物理路径 - 权限问题:运行
sudo chown -R www-data:www-data /your/path - 符号链接问题:在配置中添加
disable_symlinks off;
6.3 代理超时设置
对于长时间运行的API:
location /long-task/ { proxy_pass http://backend; proxy_read_timeout 300s; proxy_connect_timeout 75s; proxy_send_timeout 300s; }6.4 HTTPS配置最佳实践
使用Let's Encrypt免费证书:
server { listen 443 ssl; server_name app.yourdomain.com; ssl_certificate /etc/letsencrypt/live/app.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app.yourdomain.com/privkey.pem; # 启用HTTP/2 listen 443 ssl http2; # SSL优化配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256...'; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_stapling on; ssl_stapling_verify on; # 其他配置同HTTP版本... } # HTTP重定向到HTTPS server { listen 80; server_name app.yourdomain.com; return 301 https://$host$request_uri; }7. 高级配置技巧
7.1 负载均衡配置
当后端有多台服务器时:
upstream backend_servers { server 192.168.1.10:3000 weight=5; server 192.168.1.11:3000; server 192.168.1.12:3000 backup; # 负载均衡策略 least_conn; # 或者: ip_hash; } server { location /api/ { proxy_pass http://backend_servers; # ...其他proxy配置 } }7.2 日志分析与监控
定制访问日志格式:
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 uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; access_log /var/log/nginx/access.log main;7.3 安全加固配置
# 隐藏Nginx版本号 server_tokens off; # 防止点击劫持 add_header X-Frame-Options "SAMEORIGIN"; # XSS保护 add_header X-XSS-Protection "1; mode=block"; # 内容安全策略 add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com;"; # 禁用不安全的HTTP方法 if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$ ) { return 405; }7.4 多环境配置管理
使用环境变量和模板:
# 在/etc/nginx/conf.d/app.conf server { listen ${NGINX_PORT}; server_name ${APP_DOMAIN}; set $backend_host ${BACKEND_HOST}; location /api/ { proxy_pass http://$backend_host; } }然后通过envsubst生成最终配置:
envsubst < /etc/nginx/conf.d/app.conf.template > /etc/nginx/conf.d/app.conf8. 性能调优实战
8.1 连接池优化
events { worker_connections 4096; multi_accept on; use epoll; } http { # 文件描述符缓存 open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # 缓冲区优化 client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 4 8k; }8.2 缓存策略优化
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m inactive=60m use_temp_path=off; server { location /api/ { proxy_cache api_cache; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; # 缓存状态头 add_header X-Proxy-Cache $upstream_cache_status; } }8.3 压缩优化
gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 256; gzip_buffers 16 8k; gzip_disable "msie6";9. 实际部署中的经验分享
在多年的Nginx配置实践中,我总结了以下宝贵经验:
配置版本控制:将Nginx配置纳入Git管理,每次修改前创建分支,修改后测试并提交。使用
nginx -t验证配置语法。灰度发布策略:通过Nginx实现AB测试:
split_clients "${remote_addr}${http_user_agent}" $variant { 50% "v1"; 50% "v2"; } server { location / { if ($variant = "v2") { proxy_pass http://new_backend; } } }健康检查配置:
upstream backend { server 192.168.1.10:3000 max_fails=3 fail_timeout=30s; server 192.168.1.11:3000 max_fails=3 fail_timeout=30s; # 被动健康检查 server 192.168.1.12:3000 backup; }限流保护:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; location /api/ { limit_req zone=api_limit burst=20 nodelay; # ...其他配置 }调试技巧:
- 使用
error_log /var/log/nginx/error.log debug;获取详细错误信息 - 通过
add_header X-Debug "value";在响应头中添加调试信息 - 使用
curl -v http://localhost/-/nginx_status检查Nginx状态
- 使用
多应用管理:对于多个前端应用:
# 应用A server { listen 80; server_name app-a.com; root /var/www/app-a/dist; # ...其他配置 } # 应用B server { listen 80; server_name app-b.com; root /var/www/app-b/dist; # ...其他配置 }Web性能优化:
- 启用Brotli压缩(需要额外模块):
brotli on; brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - 预加载关键资源:
add_header Link "</css/main.css>; as=style; rel=preload";
- 启用Brotli压缩(需要额外模块):
移动端适配:
# 根据设备重定向 map $http_user_agent $mobile_redirect { default 0; "~*android|iphone|ipod" 1; } server { if ($mobile_redirect) { rewrite ^ /mobile redirect; } }国际化和多语言支持:
# 根据Accept-Language头重定向 map $http_accept_language $lang { default en; ~zh zh; ~fr fr; } server { rewrite ^/$ /$lang redirect; }应急方案:
- 维护模式配置:
location / { if (-f /var/www/maintenance.html) { return 503; } # ...正常配置 } error_page 503 @maintenance; location @maintenance { root /var/www; rewrite ^(.*)$ /maintenance.html break; } - 快速回滚:保持上一个稳定版本的配置备份,出现问题时可以快速切换
- 维护模式配置: