1. 为什么需要Nginx配置前后端服务
现代Web应用开发中,前后端分离架构已成为主流模式。这种架构下,前端代码(通常是React、Vue等框架构建的静态资源)和后端服务(如Node.js、Java Spring Boot等)需要协同工作,但又需要保持各自的独立性。
Nginx作为高性能的Web服务器和反向代理,在前后端分离架构中扮演着关键角色。我经历过多个项目从混乱部署到规范配置的演进过程,发现合理的Nginx配置能解决以下典型问题:
- 前端路由与后端API的路径冲突(比如前端有/about路由,后端也有/api/about接口)
- 跨域请求带来的开发和生产环境差异
- 静态资源缓存策略与代码更新的矛盾
- 不同环境(开发/测试/生产)的配置差异管理
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境准备与Nginx安装
2.1 选择合适的Nginx版本
当前主流Linux发行版的默认仓库可能提供较旧版本的Nginx。在生产环境中,我建议使用官方仓库的最新稳定版:
bash复制# Ubuntu/Debian系统
sudo apt install curl gnupg2 ca-certificates lsb-release
echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo apt update
sudo apt install nginx
# CentOS/RHEL系统
sudo yum install yum-utils
sudo vi /etc/yum.repos.d/nginx.repo
# 添加以下内容:
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
sudo yum install nginx
注意:开发环境可以使用较新版本,但生产环境建议锁定特定小版本(如nginx-1.25.3),避免自动升级引入意外变更。
2.2 目录结构与权限配置
Nginx默认安装后,关键目录结构如下:
code复制/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 附加配置目录
├── sites-available/ # 可用站点配置(Ubuntu风格)
├── sites-enabled/ # 启用站点链接(Ubuntu风格)
├── modules-available/ # 模块配置
└── modules-enabled/ # 启用模块链接
建议的权限设置:
bash复制sudo chown -R root:root /etc/nginx/
sudo chmod -R 644 /etc/nginx/
sudo find /etc/nginx/ -type d -exec chmod 755 {} \;
3. 前后端服务的基础配置
3.1 前端静态资源配置
假设前端构建产物位于/var/www/frontend/dist,基础配置如下:
nginx复制server {
listen 80;
server_name example.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, immutable";
}
}
关键点解析:
try_files指令确保前端路由能正确处理- 静态资源设置长期缓存(利用文件hash解决更新问题)
- 现代前端框架需要
/index.html回退
3.2 后端API代理配置
假设后端服务运行在http://localhost:3000,添加以下配置:
nginx复制location /api/ {
proxy_pass http://localhost:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
}
经验之谈:
- 代理路径后的
/必须注意:proxy_pass http://localhost:3000/会去掉/api前缀 - WebSocket需要
Upgrade头设置 - 生产环境建议配置keepalive连接
4. 高级配置与优化技巧
4.1 多环境配置管理
实际项目中,我通常使用环境变量配合模板生成最终配置:
nginx复制# /etc/nginx/conf.d/app.conf.template
server {
listen ${NGINX_PORT};
server_name ${DOMAIN};
set $backend_host ${BACKEND_HOST};
# ...其余配置
}
使用envsubst工具生成最终配置:
bash复制export NGINX_PORT=8080
export DOMAIN=example.com
export BACKEND_HOST=backend-service:3000
envsubst < /etc/nginx/conf.d/app.conf.template > /etc/nginx/conf.d/app.conf
4.2 性能优化参数
nginx复制http {
# 文件描述符缓存
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
# 压缩配置
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1024;
gzip_comp_level 6;
# 连接优化
keepalive_timeout 65;
keepalive_requests 100;
# 静态文件发送优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
4.3 安全加固配置
nginx复制server {
# 禁用不必要的HTTP方法
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$ ) {
return 405;
}
# 安全头设置
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# 隐藏Nginx版本信息
server_tokens off;
# 限制上传大小
client_max_body_size 10m;
}
5. 常见问题排查与解决
5.1 502 Bad Gateway错误
典型原因和解决方案:
-
后端服务未运行
bash复制# 检查后端进程 ps aux | grep node # 或java等对应后端进程 # 测试后端接口 curl -v http://localhost:3000/health -
权限问题
bash复制# 检查Nginx用户权限 sudo -u nginx curl http://localhost:3000/ # 临时放宽SELinux setsebool -P httpd_can_network_connect 1 -
端口冲突
bash复制
netstat -tulnp | grep :3000
5.2 前端路由刷新404
确保有以下配置:
nginx复制location / {
try_files $uri $uri/ /index.html;
}
同时检查:
- 前端构建的
publicPath配置 - 路由base路径设置(如Vue Router的
base选项)
5.3 跨域问题处理
虽然代理配置通常能解决跨域,特殊场景可能需要:
nginx复制location /api/ {
# ...其他proxy配置
# CORS处理
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
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;
}
add_header 'Access-Control-Allow-Origin' '*';
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';
}
6. 实际项目配置示例
6.1 Vue + Node.js项目完整配置
nginx复制upstream backend {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/frontend/dist;
index index.html;
# 前端静态资源
location / {
try_files $uri $uri/ /index.html;
# 安全头
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com;";
}
# 后端API
location /api/ {
proxy_pass http://backend/;
proxy_http_version 1.1;
proxy_set_header Connection "";
# 传递真实IP
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支持
location /socket.io/ {
proxy_pass http://backend/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 禁止访问.git等隐藏文件
location ~ /\. {
deny all;
}
}
6.2 React + Spring Boot配置差异点
主要区别在于:
- Spring Boot通常需要处理
/actuator端点 - 可能需要配置静态资源映射
nginx复制location /actuator/ {
proxy_pass http://backend/actuator/;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}
# 静态资源直接由Spring Boot处理时
location /static/ {
proxy_pass http://backend/static/;
expires 7d;
}
7. 部署与持续集成实践
7.1 配置验证与重载
每次修改配置后:
bash复制# 检查语法
sudo nginx -t
# 优雅重载
sudo nginx -s reload
建议在CI/CD流程中加入检查:
yaml复制# .gitlab-ci.yml示例
validate_nginx:
stage: test
script:
- docker run --rm -v $(pwd)/nginx:/etc/nginx nginx nginx -t
7.2 Docker化部署方案
Dockerfile示例:
dockerfile复制FROM nginx:1.25-alpine
# 移除默认配置
RUN rm -rf /etc/nginx/conf.d/*
# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 复制前端构建产物
COPY dist/ /var/www/frontend/dist/
EXPOSE 80 443
docker-compose.yml示例:
yaml复制version: '3'
services:
frontend:
build: .
ports:
- "80:80"
- "443:443"
depends_on:
- backend
restart: unless-stopped
backend:
image: node:18
working_dir: /app
volumes:
- ./backend:/app
command: npm start
environment:
- NODE_ENV=production
- PORT=3000
restart: unless-stopped
7.3 监控与日志分析
配置访问日志格式:
nginx复制http {
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;
}
使用GoAccess分析:
bash复制goaccess /var/log/nginx/access.log --log-format=COMBINED
对于生产环境,建议集成Prometheus监控:
nginx复制location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
