1. 项目概述
作为一名长期奋战在Web服务部署一线的工程师,我经常需要面对前后端分离架构的部署难题。Nginx作为高性能的Web服务器和反向代理,在前后端服务配置中扮演着关键角色。今天我要分享的是如何通过Nginx优雅地配置前后端服务,实现高效、安全的Web应用部署。
这个配置方案适用于现代Web开发中最常见的前后端分离架构场景。前端可能是React、Vue等框架构建的SPA应用,后端则是Node.js、Java Spring Boot、Python Django等各类服务。通过合理的Nginx配置,我们可以实现静态资源的高效分发、API请求的智能路由、负载均衡以及安全防护等关键功能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心需求解析
2.1 前后端分离架构的特点
现代Web应用通常采用前后端分离的架构设计,这种架构带来了几个显著的部署需求:
- 前端静态资源(HTML、JS、CSS等)需要高效分发
- 后端API请求需要正确路由到对应的服务端口
- 需要处理跨域请求(CORS)问题
- 可能需要支持WebSocket等实时通信协议
- 需要考虑缓存策略和性能优化
2.2 Nginx的核心作用
在前后端分离架构中,Nginx主要承担以下角色:
- 静态资源服务器:直接提供前端构建产物
- 反向代理:将API请求转发到后端服务
- 负载均衡器:在后端多实例情况下分配请求
- 安全网关:提供HTTPS、请求过滤等安全功能
3. 基础配置实现
3.1 基本目录结构与文件组织
一个典型的生产环境Nginx配置目录结构如下:
code复制/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 额外配置目录
│ └── myapp.conf # 应用特定配置
├── sites-available/ # 可用站点配置
├── sites-enabled/ # 启用站点配置(通常是符号链接)
└── ssl/ # SSL证书存放目录
3.2 最小化配置示例
以下是一个最基本的Nginx配置,同时服务前端静态文件和代理后端API:
nginx复制server {
listen 80;
server_name example.com;
# 前端静态文件配置
location / {
root /var/www/frontend/dist;
try_files $uri $uri/ /index.html;
index index.html;
}
# 后端API代理配置
location /api/ {
proxy_pass http://localhost:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
这个配置实现了:
- 将前端构建产物放在
/var/www/frontend/dist目录下 - 所有
/api/开头的请求会被代理到本地的3000端口 - 前端路由使用
try_files回退到index.html,支持SPA的路由
4. 高级配置技巧
4.1 性能优化配置
为了提升Nginx的性能表现,我们可以添加以下配置:
nginx复制# 在http块中添加
http {
# 启用gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 静态文件缓存控制
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ 1y;
}
server {
# ...其他配置...
# 静态资源缓存头
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
}
location ~* \.(?:css|js)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
}
}
4.2 安全加固配置
安全是生产环境不可忽视的方面,以下是一些关键的安全配置:
nginx复制server {
# ...其他配置...
# 禁止隐藏文件访问
location ~ /\. {
deny all;
access_log off;
log_not_found 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' 'unsafe-eval' https://cdn.example.com; img-src 'self' data: https://*.example.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com";
# 禁用不安全的HTTP方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
}
5. HTTPS配置实战
5.1 获取SSL证书
我们可以使用Let's Encrypt免费证书,通过certbot工具获取:
bash复制sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
5.2 Nginx HTTPS配置
获取证书后,Nginx的HTTPS配置如下:
nginx复制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;
# SSL协议配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
# HSTS头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# ...其他配置与HTTP版本相同...
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
6. 多环境配置管理
6.1 开发、测试、生产环境区分
在实际项目中,我们通常需要为不同环境配置不同的Nginx设置:
nginx复制# 在nginx.conf中
http {
# 通过map定义环境变量
map $host $env {
default "production";
"~*dev\.example\.com" "development";
"~*test\.example\.com" "test";
}
# 包含环境特定配置
include /etc/nginx/conf.d/*.conf;
}
然后在conf.d目录中创建环境特定的配置文件:
nginx复制# conf.d/development.conf
server {
listen 80;
server_name dev.example.com;
location / {
root /var/www/frontend-dev/dist;
# 开发环境禁用缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
location /api/ {
proxy_pass http://localhost:3100/;
}
}
6.2 日志配置优化
合理的日志配置可以帮助我们更好地监控和排查问题:
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 buffer=32k flush=5m;
error_log /var/log/nginx/error.log warn;
server {
# 特定server的日志
access_log /var/log/nginx/example.com.access.log main;
error_log /var/log/nginx/example.com.error.log;
# 静态资源不记录访问日志
location ~* \.(?:jpg|jpeg|gif|png|ico|css|js)$ {
access_log off;
}
}
}
7. 常见问题与解决方案
7.1 跨域问题(CORS)
虽然Nginx反向代理可以避免大部分跨域问题,但有时仍需要显式配置CORS:
nginx复制location /api/ {
proxy_pass http://localhost:3000/;
# 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';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
7.2 前端路由刷新404问题
对于单页应用(SPA),刷新非根路由时可能会出现404错误,解决方案是:
nginx复制location / {
root /var/www/frontend/dist;
try_files $uri $uri/ /index.html;
}
7.3 上传文件大小限制
默认情况下,Nginx限制上传文件大小为1MB,可以通过以下配置调整:
nginx复制server {
# ...
client_max_body_size 20M; # 设置为20MB
# ...
}
7.4 WebSocket支持
要代理WebSocket连接,需要添加以下配置:
nginx复制location /ws/ {
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;
}
8. 性能调优实战
8.1 静态资源缓存策略
合理的缓存策略可以显著提升网站性能:
nginx复制location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff2?|eot|ttf|otf)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
# 开启gzip
gzip_static on;
# 文件找不到时不记录错误日志
log_not_found off;
}
8.2 连接优化参数
调整以下参数可以优化Nginx的连接处理能力:
nginx复制http {
# 保持连接超时时间
keepalive_timeout 65;
# 单个连接最大请求数
keepalive_requests 1000;
# 发送文件时使用sendfile
sendfile on;
# 优化数据包发送
tcp_nopush on;
# 禁用Nagle算法
tcp_nodelay on;
# 客户端请求头缓冲区大小
client_header_buffer_size 4k;
# 大型客户端请求头缓冲区数量
large_client_header_buffers 4 16k;
}
8.3 反向代理优化
对于后端服务的代理连接,可以进行以下优化:
nginx复制location /api/ {
proxy_pass http://backend;
# 连接超时设置
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
# 缓冲区设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
# 其他优化
proxy_http_version 1.1;
proxy_set_header Connection "";
}
9. 负载均衡配置
当后端服务有多个实例时,可以使用Nginx的负载均衡功能:
9.1 基础负载均衡配置
nginx复制upstream backend {
server 127.0.0.1:3000 weight=5;
server 127.0.0.1:3001;
server 127.0.0.1:3002 backup;
# 负载均衡算法
least_conn;
# 健康检查
check interval=3000 rise=2 fall=3 timeout=1000;
}
server {
location /api/ {
proxy_pass http://backend;
}
}
9.2 高级负载均衡策略
Nginx支持多种负载均衡算法:
- 轮询(默认):请求按时间顺序分配到不同服务器
- 加权轮询:根据服务器权重分配请求
- IP哈希:根据客户端IP分配,保持会话一致性
- 最少连接:优先分配给当前连接数最少的服务器
- 响应时间:优先分配给响应时间短的服务器
nginx复制upstream backend {
# IP哈希算法
ip_hash;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
# 会话保持
sticky cookie srv_id expires=1h domain=.example.com path=/;
}
10. 监控与日志分析
10.1 Nginx状态监控
启用Nginx状态页面可以监控服务器状态:
nginx复制server {
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
访问/nginx_status将显示类似如下的信息:
code复制Active connections: 3
server accepts handled requests
100 100 200
Reading: 0 Writing: 1 Waiting: 2
10.2 日志分析与可视化
我们可以使用工具如GoAccess进行日志分析:
bash复制goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED
或者使用ELK(Elasticsearch, Logstash, Kibana)栈进行更复杂的日志分析。
11. 容器化部署配置
11.1 Docker环境下的Nginx配置
在Docker环境中部署Nginx时,配置文件通常放在/etc/nginx/nginx.conf,我们可以通过挂载卷来覆盖默认配置:
dockerfile复制FROM nginx:alpine
# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 复制前端静态文件
COPY dist/ /var/www/frontend/dist/
EXPOSE 80 443
11.2 Kubernetes Ingress配置
在Kubernetes中,我们可以使用Nginx Ingress Controller:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
number: 3000
12. 实战经验分享
在实际部署过程中,我积累了一些宝贵的经验:
-
配置版本控制:将Nginx配置文件纳入Git版本控制,方便回滚和团队协作。
-
配置检查:每次修改配置后,务必运行
nginx -t测试配置是否正确。 -
灰度发布:可以通过Nginx的
split_clients模块实现AB测试或灰度发布:
nginx复制split_clients "${remote_addr}${http_user_agent}" $variant {
50% "v1";
50% "v2";
}
server {
location / {
if ($variant = "v2") {
rewrite ^ /v2$uri last;
}
root /var/www/frontend/dist;
}
location /v2/ {
alias /var/www/frontend-v2/dist/;
try_files $uri $uri/ /v2/index.html;
}
}
-
性能测试:使用工具如
wrk或ab进行压力测试,找出性能瓶颈。 -
错误页面定制:提供友好的错误页面提升用户体验:
nginx复制error_page 404 /404.html;
location = /404.html {
root /var/www/errors;
internal;
}
- IP限制:对管理接口进行IP限制:
nginx复制location /admin/ {
allow 192.168.1.0/24;
allow 10.0.0.1;
deny all;
proxy_pass http://backend;
}
- 请求限流:防止恶意请求或突发流量:
nginx复制limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
- 多域名处理:一个Nginx实例服务多个域名:
nginx复制server {
listen 80;
server_name example.com;
location / {
root /var/www/example.com;
}
}
server {
listen 80;
server_name another.com;
location / {
root /var/www/another.com;
}
}
- HTTP/2优化:启用HTTP/2可以显著提升性能:
nginx复制server {
listen 443 ssl http2;
# ...其他SSL配置...
}
- 日志轮转:配置logrotate防止日志文件过大:
bash复制# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
/etc/init.d/nginx reload > /dev/null
endscript
}
