Nginx的proxy_pass需按协议类型选用对应指令:HTTP用proxy_pass,gRPC用grpc_pass,PHP用fastcgi_pass,TCP/UDP用stream模块proxy_pass;路径拼接、请求头透传(Host/X-Real-IP/X-Forwarded-Proto)、连接隔离(keepalive_timeout 0)等边界控制缺一不可。

proxy_pass 本身不“透传数据”,而是通过精准控制请求路径、协议头、连接层行为,让异构上游系统能正确接收并理解原始语义。关键不在转发动作本身,而在边界定义是否清晰、上下文是否完整。
按协议类型选对代理指令
HTTP/HTTPS、gRPC、FastCGI、TCP/UDP 是完全不同的通信契约,混用会导致解析失败或静默丢包:
- HTTP 类服务(REST API、Web 应用):用 proxy_pass http://upstream_name,配合 proxy_set_header 补全 Host、X-Real-IP 等四类基础头
- gRPC 服务(二进制协议、HTTP/2):必须改用 grpc_pass grpc://upstream_name,且后端需支持 HTTP/2;禁用 rewrite 拼接路径,否则会破坏 gRPC 的 path 格式
- 传统 CGI/FPM 接口(PHP、Perl):用 fastcgi_pass upstream_name,搭配 fastcgi_param 显式传递 SCRIPT_FILENAME、PATH_INFO 等 CGI 变量
- TCP/UDP 类服务(数据库代理、设备管理端口、自研二进制网关):启用 stream 模块,用 proxy_pass upstream_name 在连接建立阶段透传,完全跳过 HTTP 解析
路径拼接必须零歧义
location 和 proxy_pass 的斜杠组合直接决定后端收到的 URI,稍错就导致 404 或路由错乱:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- proxy_pass http://127.0.0.1:8000/(末尾带 /):location /api/ 匹配 /api/users → 后端收到 /users
- proxy_pass http://127.0.0.1:8000(末尾无 /):同样请求 → 后端收到 /api/users
- location 用正则(如 ~ ^/v[1-9]/)时:proxy_pass 必须写完整 URL,且不能省略 URI 部分,例如 proxy_pass http://127.0.0.1:8001$request_uri;
客户端上下文必须全量透传
异构系统常依赖原始请求信息做鉴权、日志、重定向,Nginx 默认不传,漏一项就可能出问题:
- Host 头:设 proxy_set_header Host $host,避免后端因域名不匹配返回 404
- 真实 IP:用 X-Real-IP $remote_addr 传最外层地址;X-Forwarded-For $proxy_add_x_forwarded_for 支持多级代理链式追加
- 协议类型:设 X-Forwarded-Proto $scheme,让后端知道当前是 http 还是 https,影响 Location 跳转链接生成
- WebSocket 升级:若代理 WebSocket,必须加 proxy_http_version 1.1、Upgrade $http_upgrade、Connection "upgrade"
连接生命周期要严格隔离
长连接复用在同构场景是优化,在异构间却是隐患——不同协议栈对 keepalive 行为理解不同:
- 对 gRPC 或 FastCGI 类服务,建议显式关闭连接复用:keepalive_timeout 0
- 用 proxy_protocol on 向上游透传原始客户端地址(尤其在 TLS 终结前或四层 LB 后),避免 IP 信息丢失
- stream 模块中启用 ssl_preread on,可基于 SNI 域名做 TLS 层路由,实现 HTTPS 域名到不同 TCP 后端的分发

















