[toc]
nginx反向代理笔记
基础概念
什么是反向代理
反向代理是Nginx的核心功能之一,它接收客户端的请求,然后将请求转发到后端服务器,并将后端服务器的响应返回给客户端。在这个过程中,路径的处理方式直接影响请求能否正确到达目标服务。
通过反向代理可以实现以下功能:
- 协议转换:将客户端的HTTPS请求转换为HTTP请求,或者将客户端的HTTP请求转换为HTTPS请求。从而解决了协议不匹配问题。即跨域问题。
- 端口转换:将客户端的请求端口转换为后端服务器的端口。从而解决了端口不匹配问题。即跨域问题。
- 路径重写:根据配置规则,对客户端请求的路径进行重写,从而实现路径的定制化。
- 负载均衡:将客户端请求分发到多个后端服务器,实现高可用和高吞吐量。
- 缓存:缓存后端服务器的响应,减少对后端服务器的请求次数,提高响应速度。
- 安全:隐藏后端服务器的真实IP地址,防止直接暴露在公网上。
路径斜线的重要性
在Nginx配置中,location和proxy_pass指令中的斜线/处理方式决定了URL路径的转发规则。正确的斜线配置可以避免404错误和路径混乱问题。
路径斜线的场景设定
假设前端服务访问URL地址是:http://localhost:8080/elecapi/test/home/getInfo,需要根据关键词elecapi实现请求转发到后台接口。
假设有以下四种配置场景组合。
配置1:location不加斜线、proxy_pass不加斜线
server {
listen 8080;
server_name localhost;
# 反向代理设置
location /elecapi {
proxy_pass http://192.168.0.1:13314;
}
}前端请求地址: http://localhost:8080/elecapi/test/home/getInfo实际访问地址: http://192.168.0.1:13314/elecapi/test/home/getInfo
路径解析:
- 原始请求:
/elecapi/test/home/getInfo - location匹配:
/elecapi - 剩余路径:
/test/home/getInfo - 最终路径:
/elecapi+/test/home/getInfo=/elecapi/test/home/getInfo
配置2:location加斜线、proxy_pass不加斜线
server {
listen 8080;
server_name localhost;
# 反向代理设置
location /elecapi/ {
proxy_pass http://192.168.0.1:13314;
}
}前端请求地址: http://localhost:8080/elecapi/test/home/getInfo实际访问地址: http://192.168.0.1:13314/elecapi/test/home/getInfo
路径解析:
- 原始请求:
/elecapi/test/home/getInfo - location匹配:
/elecapi/ - 剩余路径:
/test/home/getInfo - 最终路径:
/elecapi+/test/home/getInfo=/elecapi/test/home/getInfo
配置3:location不加斜线、proxy_pass加斜线
server {
listen 8080;
server_name localhost;
# 反向代理设置
location /elecapi {
proxy_pass http://192.168.0.1:13314/;
}
}前端请求地址: http://localhost:8080/elecapi/test/home/getInfo实际访问地址: http://192.168.0.1:13314/test/home/getInfo
路径解析:
- 原始请求:
/elecapi/test/home/getInfo - location匹配:
/elecapi - 剩余路径:
/test/home/getInfo - 最终路径:
/+/test/home/getInfo=/test/home/getInfo
配置4:location加斜线、proxy_pass加斜线
server {
listen 8080;
server_name localhost;
# 反向代理设置
location /elecapi/ {
proxy_pass http://192.168.0.1:13314/;
}
}前端请求地址: http://localhost:8080/elecapi/test/home/getInfo实际访问地址: http://192.168.0.1:13314/test/home/getInfo
路径解析:
- 原始请求:
/elecapi/test/home/getInfo - location匹配:
/elecapi/ - 剩余路径:
/test/home/getInfo - 最终路径:
/+/test/home/getInfo=/test/home/getInfo
路径斜线规则总结
基本规则
当proxy_pass转发地址最后一个字符不是斜线
/的时候:最终地址 = 转发地址 + location部分 + 访问URL地址(去除location部分)当proxy_pass转发地址最后一个字符是斜线
/的时候:最终地址 = 转发地址 + 访问URL地址(去除location部分)通俗理解: 当proxy_pass加上斜线
/的时候,最终的转发地址会去除location部分。没有加上斜线/的时候,会保留location部分。
记忆技巧
- proxy_pass无斜线:保留location路径
- proxy_pass有斜线:去除location路径
- location斜线:主要影响精确匹配,不影响路径处理规则
高级路径匹配场景分析
正则表达式location匹配
# 正则匹配,路径处理规则不变
location ~ ^/api/(v1|v2)/ {
proxy_pass http://backend:8080;
}
# 请求 /api/v1/users → 后端 /api/v1/users
location ~ ^/api/(v1|v2)/ {
proxy_pass http://backend:8080/;
}
# 请求 /api/v1/users → 后端 /users精确匹配location
# 精确匹配
location = /api {
proxy_pass http://backend:8080;
}
# 请求 /api → 后端 /api
location = /api {
proxy_pass http://backend:8080/;
}
# 请求 /api → 后端 /精确匹配location
location = /api {
proxy_pass http://backend:8080;
}
# 请求 /api → 后端 /api
location = /api {
proxy_pass http://backend:8080/;
}
# 请求 /api → 后端 /带路径的proxy_pass
location /app/ {
proxy_pass http://backend:8080/newapp/;
}
# 请求 /app/user → 后端 /newapp/user
location /app/ {
proxy_pass http://backend:8080/newapp;
}
# 请求 /app/user → 后端 /newappuser(注意:路径直接拼接)各种实际应用案例
微服务API网关的反向代理配置
# 用户服务
location /user-api/ {
proxy_pass http://user-service:8001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 订单服务
location /order-api/ {
proxy_pass http://order-service:8002/;
proxy_set_header Host $host;
}
# 商品服务
location /product-api/ {
proxy_pass http://product-service:8003/;
proxy_set_header Host $host;
}前后端分离项目的反向代理配置
server {
listen 80;
server_name example.com;
# 前端静态资源
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# API代理 - 去除/api前缀
location /api/ {
proxy_pass http://backend: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;
}
# 文件上传代理 - 保留/upload前缀
location /upload/ {
proxy_pass http://file-service:8080;
client_max_body_size 100M;
}
}多版本API管理的反向代理配置
# API版本控制
location /api/v1/ {
proxy_pass http://api-v1:8080/;
}
location /api/v2/ {
proxy_pass http://api-v2:8080/;
}
location /api/ {
# 默认版本
proxy_pass http://api-latest:8080/;
}常见问题与解决方案
404错误排查
问题现象: 配置正确但返回404
解决方案:
# 添加调试信息
location /api/ {
proxy_pass http://backend:8080/;
# 调试头部
add_header X-Proxy-Pass $proxy_host$proxy_port;
add_header X-Request-URI $request_uri;
add_header X-Proxy-URI $proxy_host$uri;
}添加调试信息会帮助定位问题,例如:
- X-Proxy-Pass:显示实际转发地址
- X-Request-URI:显示原始请求路径
- X-Proxy-URI:显示代理路径
路径重写问题
问题: 需要复杂的路径重写
解决方案: 使用rewrite指令
location /old-api/ {
rewrite ^/old-api/(.*)$ /new-api/$1 break;
proxy_pass http://backend:8080;
}rewrite指令的作用是根据正则表达式匹配请求路径,然后将其重写为新的路径。然后将重写后的路径传递给proxy_pass指令。
路径自动补全问题
问题: 浏览器自动补全斜线导致路径错误
解决方案:
# 强制斜线处理
location /api {
if ($request_uri ~ ^/api[^/]) {
return 301 /api/$1;
}
proxy_pass http://backend:8080/;
}性能优化配置
连接池配置(负载均衡配置)
upstream 可以将多个后端服务器组成一个组,然后根据负载均衡策略将请求分发到不同的后端服务器。
upstream backend {
server backend1:8080;
server backend2:8080;
# 连接池配置
keepalive 32;
keepalive_timeout 60s;
keepalive_requests 1000;
}
location /api/ {
proxy_pass http://backend/;
proxy_http_version 1.1;
proxy_set_header Connection "";
}keepalive 的作用是保持与后端服务器的长连接,减少连接建立和关闭的开销。
连接池优化
location /api/ {
proxy_pass http://backend/;
# 缓冲区优化
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_temp_path /tmp/nginx_proxy_temp;
}proxy_buffering 的作用是启用缓冲区,将后端服务器的响应分块返回给客户端。从而减少后端服务器的压力。
超时设置
location /api/ {
proxy_pass http://backend/;
# 超时配置
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 重试机制
proxy_next_upstream error timeout invalid_header;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
}proxy_connect_timeout 的作用是设置与后端服务器建立连接的超时时间。
安全配置
头部安全设置
location /api/ {
proxy_pass http://backend/;
# 安全头部
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# 隐藏后端信息
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}proxy_set_header 的作用是设置请求头,将客户端的请求头传递给后端服务器。并且可以在传递前对请求头进行修改。
访问控制
可以限制客户端的请求IP,从而实现访问控制。
location /admin-api/ {
proxy_pass http://backend/;
# IP白名单
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
# 基础认证
auth_basic "Admin API";
auth_basic_user_file /etc/nginx/htpasswd;
}监控与日志配置
详细日志配置
# 定义日志格式
log_format proxy_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$upstream_addr" "$upstream_status" '
'"$upstream_response_time" "$request_time"';
location /api/ {
proxy_pass http://backend/;
# 访问日志
access_log /var/log/nginx/api_access.log proxy_log;
# 错误日志
error_log /var/log/nginx/api_error.log;
}健康检查配置
健康检查的作用是检查后端服务器的健康状态,从而判断是否将请求分发到该服务器。
upstream backend {
server backend1:8080;
server backend2:8080;
# 健康检查
check interval=3000 rise=2 fall=3 timeout=1000;
}
location /api/ {
proxy_pass http://backend/;
}最佳实践总结
配置原则
- 明确路径意图:根据业务需求决定是否保留location前缀
- 一致性原则:同一项目中使用统一的路径处理规则
- 测试验证:部署前充分测试各种路径场景
- 文档记录:在配置文件中添加清晰的注释说明
推荐配置模式
# 推荐:去除API前缀,保持后端路径简洁
location /api/ {
proxy_pass http://backend/;
}
# 特殊情况:需要保留前缀时
location /external/ {
proxy_pass http://external-service;
}调试技巧
- 使用
add_header添加调试信息 - 查看Nginx错误日志
error_log - 使用
curl命令测试各种路径组合 - 监控上游服务器访问日志
通过掌握这些路径斜线处理的细节和技巧,可以避免常见的代理配置错误,构建稳定高效的Nginx反向代理环境。
