Skip to content

外部 Nginx 反向代理配置

当在 IPAM 容器前端再部署一层外部 Nginx 反向代理(用于 HTTPS 卸载、域名转发等场景)时,必须对 SSE(Server-Sent Events)路径做特殊配置,否则监控页面会出现连接超时、数据延迟等问题。

背景说明

IPAM 的实时监控功能(主机监控、网络监控等)通过 SSE 向浏览器推送数据:

浏览器 ──HTTPS──▶ 外部 Nginx 代理 ──▶ 容器 Nginx (12380) ──▶ Go 后端 (12389)
  • 容器内部 Nginx 已内置 SSE 支持(proxy_buffering off),无需额外配置
  • 外部 Nginx 代理 默认启用响应缓冲,会缓存 SSE 流式数据,导致浏览器无法实时接收

⚠️ 关键点:问题出现在外层代理,而非容器内部 Nginx。即使容器配置正确,外层代理仍会阻断 SSE 实时推送。

问题现象

现象说明
SSE 连接建立耗时数十秒浏览器 Network 面板显示 /api/monitor/* 请求长时间 pending
监控数据不更新或严重延迟首帧数据延迟到达,曲线停滞
刷新监控页面白屏SPA 路由未回退到 index.html,前端资源 404

解决方案

1. SSE 路径关闭缓冲

对外部 Nginx 代理的 /api/ 路径关闭 proxy_bufferingproxy_cache,并提升 HTTP 版本与读超时:

nginx
location /api/ {
    proxy_pass http://127.0.0.1:12380;
    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;

    # SSE 必须:关闭缓冲与缓存,确保流式数据实时到达浏览器
    proxy_buffering off;
    proxy_cache off;

    # HTTP/1.1 长连接,避免每次请求重新握手
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    # SSE 长连接读超时(秒),需大于监控会话最长时长
    proxy_read_timeout 86400;
}

如仅需对监控接口生效,可将 location 改为 location /api/monitor/,其余 /api/ 路径保留默认缓冲以提升普通 API 性能。

2. SPA 路由回退

非 API 路径需回退到 index.html,否则直接访问 /monitor/host 等前端路由会返回 404:

nginx
location / {
    proxy_pass http://127.0.0.1:12380;
    # 或直接代理到容器,由容器 Nginx 处理 try_files
}

容器内部 Nginx 已配置 try_files $uri $uri/ /index.html;,外层代理只需将非 API 请求转发到容器即可。

3. 完整配置示例

nginx
server {
    listen 443 ssl http2;
    server_name ipam.example.com;

    ssl_certificate     /etc/nginx/ssl/ipam.crt;
    ssl_certificate_key /etc/nginx/ssl/ipam.key;

    # API 请求(含 SSE):关闭缓冲,确保实时推送
    location /api/ {
        proxy_pass http://127.0.0.1:12380;
        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_buffering off;
        proxy_cache off;
        proxy_http_version 1.1;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }

    # 其余请求(前端静态资源、SPA 路由)
    location / {
        proxy_pass http://127.0.0.1:12380;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

验证方法

  1. 检查响应头:SSE 响应应包含 Content-Type: text/event-stream

    bash
    curl -I -H "Accept: text/event-stream" https://ipam.example.com/api/monitor/host
  2. 浏览器 Network 面板:访问监控页面,观察 /api/monitor/* 请求

    • ✅ 正常:请求状态 pending(保持长连接),但首帧数据在秒级到达
    • ❌ 异常:请求 pending 数十秒无数据,或 TTFB 超过 5 秒
  3. 对比内外层延迟

    bash
    # 直连容器(应秒级响应)
    curl -N http://127.0.0.1:12380/api/monitor/host -H "Authorization: Bearer <token>"
    
    # 经外层代理(同样应秒级响应)
    curl -N https://ipam.example.com/api/monitor/host -H "Authorization: Bearer <token>"

    若直连秒级、代理数十秒,则外层 Nginx 缓冲未关闭。

故障排查

现象排查方向
SSE 仍延迟确认外层 Nginx 已 nginx -t && nginx -s reload;检查是否有 CDN/WAF 在前再缓存
监控页刷新白屏检查外层 location / 是否正确转发到容器 12380;确认容器 Nginx 有 try_files
502/504 错误确认容器正常运行:docker ps | grep ipam-frontend;检查 proxy_read_timeout 是否过短
首帧快但后续断连检查 proxy_read_timeout 是否小于监控会话时长;确认中间无防火墙切断长连接

相关文档

基于 MIT 许可发布