Skip to content
🗂️ 文章分类: 服务器  
🏷️ 文章标签: Nginx  
📝 文章创建时间: 2023-02-14
🔥 文章最后更新时间:2026-02-06

[toc]

nginx反向代理笔记

基础概念

什么是反向代理

反向代理是Nginx的核心功能之一,它接收客户端的请求,然后将请求转发到后端服务器,并将后端服务器的响应返回给客户端。在这个过程中,路径的处理方式直接影响请求能否正确到达目标服务。

通过反向代理可以实现以下功能:

  • 协议转换:将客户端的HTTPS请求转换为HTTP请求,或者将客户端的HTTP请求转换为HTTPS请求。从而解决了协议不匹配问题。即跨域问题。
  • 端口转换:将客户端的请求端口转换为后端服务器的端口。从而解决了端口不匹配问题。即跨域问题。
  • 路径重写:根据配置规则,对客户端请求的路径进行重写,从而实现路径的定制化。
  • 负载均衡:将客户端请求分发到多个后端服务器,实现高可用和高吞吐量。
  • 缓存:缓存后端服务器的响应,减少对后端服务器的请求次数,提高响应速度。
  • 安全:隐藏后端服务器的真实IP地址,防止直接暴露在公网上。

路径斜线的重要性

在Nginx配置中,locationproxy_pass指令中的斜线/处理方式决定了URL路径的转发规则。正确的斜线配置可以避免404错误和路径混乱问题。

路径斜线的场景设定

假设前端服务访问URL地址是:http://localhost:8080/elecapi/test/home/getInfo,需要根据关键词elecapi实现请求转发到后台接口。

假设有以下四种配置场景组合。

配置1:location不加斜线、proxy_pass不加斜线

nginx
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不加斜线

nginx
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加斜线

nginx
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加斜线

nginx
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

路径斜线规则总结

基本规则

  1. 当proxy_pass转发地址最后一个字符不是斜线/的时候:

    最终地址 = 转发地址 + location部分 + 访问URL地址(去除location部分)
  2. 当proxy_pass转发地址最后一个字符是斜线/的时候:

    最终地址 = 转发地址 + 访问URL地址(去除location部分)
  3. 通俗理解: 当proxy_pass加上斜线/的时候,最终的转发地址会去除location部分。没有加上斜线/的时候,会保留location部分。

记忆技巧

  • proxy_pass无斜线:保留location路径
  • proxy_pass有斜线:去除location路径
  • location斜线:主要影响精确匹配,不影响路径处理规则

高级路径匹配场景分析

正则表达式location匹配

nginx
# 正则匹配,路径处理规则不变
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

nginx
# 精确匹配
location = /api {
    proxy_pass http://backend:8080;
}
# 请求 /api → 后端 /api

location = /api {
    proxy_pass http://backend:8080/;
}
# 请求 /api → 后端 /

精确匹配location

nginx
location = /api {
    proxy_pass http://backend:8080;
}
# 请求 /api → 后端 /api

location = /api {
    proxy_pass http://backend:8080/;
}
# 请求 /api → 后端 /

带路径的proxy_pass

nginx
location /app/ {
    proxy_pass http://backend:8080/newapp/;
}
# 请求 /app/user → 后端 /newapp/user

location /app/ {
    proxy_pass http://backend:8080/newapp;
}
# 请求 /app/user → 后端 /newappuser(注意:路径直接拼接)

各种实际应用案例

微服务API网关的反向代理配置

nginx
# 用户服务
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;
}

前后端分离项目的反向代理配置

nginx
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管理的反向代理配置

nginx
# 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

解决方案:

nginx
# 添加调试信息
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指令

nginx
location /old-api/ {
    rewrite ^/old-api/(.*)$ /new-api/$1 break;
    proxy_pass http://backend:8080;
}

rewrite指令的作用是根据正则表达式匹配请求路径,然后将其重写为新的路径。然后将重写后的路径传递给proxy_pass指令。

路径自动补全问题

问题: 浏览器自动补全斜线导致路径错误

解决方案:

nginx
# 强制斜线处理
location /api {
    if ($request_uri ~ ^/api[^/]) {
        return 301 /api/$1;
    }
    proxy_pass http://backend:8080/;
}

性能优化配置

连接池配置(负载均衡配置)

upstream 可以将多个后端服务器组成一个组,然后根据负载均衡策略将请求分发到不同的后端服务器。

nginx
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 的作用是保持与后端服务器的长连接,减少连接建立和关闭的开销。

连接池优化

nginx
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 的作用是启用缓冲区,将后端服务器的响应分块返回给客户端。从而减少后端服务器的压力。

超时设置

nginx
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 的作用是设置与后端服务器建立连接的超时时间。

安全配置

头部安全设置

nginx
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,从而实现访问控制。

nginx
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;
}

监控与日志配置

详细日志配置

nginx
# 定义日志格式
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;
}

健康检查配置

健康检查的作用是检查后端服务器的健康状态,从而判断是否将请求分发到该服务器。

nginx
upstream backend {
    server backend1:8080;
    server backend2:8080;
    
    # 健康检查
    check interval=3000 rise=2 fall=3 timeout=1000;
}

location /api/ {
    proxy_pass http://backend/;
}

最佳实践总结

配置原则

  1. 明确路径意图:根据业务需求决定是否保留location前缀
  2. 一致性原则:同一项目中使用统一的路径处理规则
  3. 测试验证:部署前充分测试各种路径场景
  4. 文档记录:在配置文件中添加清晰的注释说明

推荐配置模式

nginx
# 推荐:去除API前缀,保持后端路径简洁
location /api/ {
    proxy_pass http://backend/;
}

# 特殊情况:需要保留前缀时
location /external/ {
    proxy_pass http://external-service;
}

调试技巧

  1. 使用add_header添加调试信息
  2. 查看Nginx错误日志error_log
  3. 使用curl命令测试各种路径组合
  4. 监控上游服务器访问日志

通过掌握这些路径斜线处理的细节和技巧,可以避免常见的代理配置错误,构建稳定高效的Nginx反向代理环境。