--- title: Nginx 代理模式选择指南 description: 详细说明 Nginx Stream 模式和 HTTP 反向代理模式的区别、适用场景及常见问题解决方案 tags: - nginx - proxy - traefik - stream - reverse-proxy - mime-type createdAt: 2025-11-26 --- # Nginx 代理模式选择指南 ## 问题现象 当使用 Stream 模式转发时,浏览器会报错: ``` Refused to execute script from 'https://npm.xiongxiao.me/-/static/Home.854787d3346e44ccc262.js' because its MIME type ('') is not executable, and strict MIME type checking is enabled. ``` ## 原因分析 Nginx Stream 模式工作在 **TCP/UDP 层**(OSI 第 4 层),只做字节流转发,**不解析 HTTP 协议**,因此: - ❌ 不会处理 HTTP 头信息(包括 Content-Type) - ❌ 不会设置 X-Forwarded-* 头 - ❌ 不支持 WebSocket 协议升级 - ❌ MIME 类型信息丢失 - ✅ 转发效率更高(无需解析 HTTP) ## 两种模式对比 ### 1. Stream 模式 (nginx-stream-proxy.conf) **工作层级**: OSI 第 4 层 (TCP/UDP) **特点**: - ✅ 性能最优,CPU 占用低 - ✅ 适合纯 TCP/UDP 转发 - ❌ 不处理 HTTP 头 - ❌ 不支持基于 HTTP 的负载均衡 - ❌ 无法查看 HTTP 请求细节 **适用场景**: - MySQL/PostgreSQL 数据库转发 - Redis/MongoDB 等数据库代理 - SSH/SFTP 端口转发 - 纯 TCP 协议转发 - 不需要 HTTP 头信息的场景 **配置示例**: ```nginx # /etc/nginx/nginx.conf 的 stream {} 块中 stream { upstream traefik_http { server 127.0.0.1:30080; } server { listen 80; proxy_pass traefik_http; } } ``` ### 2. HTTP 反向代理模式 (nginx-traefik-proxy.conf) ⭐ 推荐 **工作层级**: OSI 第 7 层 (HTTP/HTTPS) **特点**: - ✅ 完整的 HTTP 协议支持 - ✅ 保留所有 HTTP 头信息(包括 Content-Type) - ✅ 支持 WebSocket - ✅ 可以设置自定义头 - ✅ 支持 SSL/TLS 终止 - ✅ 可以记录详细访问日志 - ⚠️ 性能略低于 Stream 模式(差异很小) **适用场景**: - Web 应用反向代理 ⭐ - API 网关 - 静态资源服务 - WebSocket 应用 - 需要处理 HTTP 头的场景 **配置示例**: ```nginx # /etc/nginx/conf.d/traefik-proxy.conf server { listen 80; server_name _; # 关键:保留 HTTP 头信息 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; location / { proxy_pass http://127.0.0.1:30080; } } ``` ## 解决方案 ### 当前问题:MIME Type 错误 **原因**: 使用了 Stream 模式,导致 Content-Type 头丢失 **解决方法**: 切换到 HTTP 反向代理模式 #### 步骤 1: 停止当前 Nginx 配置 ```bash # 如果使用了 stream 模式配置 sudo rm /etc/nginx/nginx.conf.d/stream/traefik.conf # 或删除 nginx.conf 中的 stream {} 块 ``` #### 步骤 2: 应用 HTTP 反向代理配置 ```bash # 复制配置文件 sudo cp nginx-traefik-proxy.conf /etc/nginx/conf.d/traefik-proxy.conf # 创建 SSL 证书目录和占位证书(如果需要) sudo mkdir -p /etc/nginx/ssl sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/nginx/ssl/placeholder.key \ -out /etc/nginx/ssl/placeholder.crt \ -subj "/CN=placeholder" # 测试配置 sudo nginx -t # 重载 Nginx sudo nginx -s reload ``` #### 步骤 3: 验证 ```bash # 检查 HTTP 响应头 curl -I http://npm.xiongxiao.me # 应该能看到正确的 Content-Type # Content-Type: application/javascript; charset=utf-8 ``` ## 性能对比 ### Stream 模式 - **延迟**: ~0.1ms - **吞吐量**: 接近网卡上限 - **CPU 占用**: 极低 - **内存占用**: 极低 ### HTTP 反向代理模式 - **延迟**: ~0.5-1ms - **吞吐量**: 95%+ 网卡性能 - **CPU 占用**: 低 - **内存占用**: 低 **结论**: 对于 Web 应用,性能差异可以忽略不计,HTTP 反向代理模式是更好的选择。 ## 常见问题 ### Q1: 为什么 Traefik 后端应用会收到错误的 IP? **原因**: 没有设置 `X-Real-IP` 和 `X-Forwarded-For` 头 **解决**: ```nginx proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ``` ### Q2: WebSocket 连接失败 **原因**: 没有配置协议升级 **解决**: ```nginx proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; ``` ### Q3: HTTPS 证书错误 **原因**: - HTTP 反向代理模式需要占位证书 - 或者 Traefik 后端使用自签名证书 **解决**: ```nginx # 创建占位证书 sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/nginx/ssl/placeholder.key \ -out /etc/nginx/ssl/placeholder.crt \ -subj "/CN=placeholder" # 信任后端自签名证书 proxy_ssl_verify off; ``` ### Q4: 什么时候用 Stream 模式? **答**: 仅在以下场景使用 Stream 模式: - 转发非 HTTP 协议(MySQL、Redis、SSH 等) - 需要最极致的性能(每毫秒都很重要的场景) - 纯 TCP/UDP 负载均衡 **对于所有 Web 应用,请使用 HTTP 反向代理模式。** ## 推荐配置 ### 生产环境标准配置 ```nginx # /etc/nginx/conf.d/traefik-proxy.conf server { listen 80; listen [::]:80; server_name _; # 保留客户端信息 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; # WebSocket 支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 缓冲设置(根据实际调整) proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; location / { proxy_pass http://127.0.0.1:30080; proxy_redirect off; } # 日志 access_log /var/log/nginx/traefik-proxy.access.log; error_log /var/log/nginx/traefik-proxy.error.log warn; } ``` ## 参考资源 - [Nginx Stream Module 文档](http://nginx.org/en/docs/stream/ngx_stream_core_module.html) - [Nginx HTTP Proxy Module 文档](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) - [Traefik 官方文档](https://doc.traefik.io/traefik/)