Files
k8s-docs/k8s/xiongxiao.me/docs/08-nginx-proxy-modes.md
2025-11-26 17:02:14 +08:00

6.4 KiB
Raw Permalink Blame History

title, description, tags, createdAt
title description tags createdAt
Nginx 代理模式选择指南 详细说明 Nginx Stream 模式和 HTTP 反向代理模式的区别、适用场景及常见问题解决方案
nginx
proxy
traefik
stream
reverse-proxy
mime-type
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 头信息的场景

配置示例:

# /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 头的场景

配置示例:

# /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 配置

# 如果使用了 stream 模式配置
sudo rm /etc/nginx/nginx.conf.d/stream/traefik.conf
# 或删除 nginx.conf 中的 stream {} 块

步骤 2: 应用 HTTP 反向代理配置

# 复制配置文件
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: 验证

# 检查 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-IPX-Forwarded-For

解决:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Q2: WebSocket 连接失败

原因: 没有配置协议升级

解决:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Q3: HTTPS 证书错误

原因:

  • HTTP 反向代理模式需要占位证书
  • 或者 Traefik 后端使用自签名证书

解决:

# 创建占位证书
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 反向代理模式。

推荐配置

生产环境标准配置

# /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;
}

参考资源