V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ChrisFreeMan
V2EX  ›  程序员

请问大佬们如何正确配置 Nginx 使其能够启用 SSE(server-sent-events)

  •  
  •   ChrisFreeMan · 62 天前 · 1707 次点击
    这是一个创建于 62 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在本地测试完全没有问题,本地的 nginx 监听 80 端口转发到 express 也是完全没有问题,但是直到启用 ssl ,开启 443 端口后,服务端发送消息,客户端就无法接收了,完全找不到头绪,网上的例子都试了就是没有用 以下是我的 nginx 配置

    server {
      listen 443 ssl http2;
      listen [::]:443 http2 ssl;
      server_name  www.mydomain.com;
    
      ssl_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/www.mydomain.com/privkey.pem;
    
      access_log off;
    
      location / {
        proxy_pass http://127.0.0.1:3000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
        chunked_transfer_encoding off;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
    }
    
    

    我的服务端代码

    eventRouter.get('/event/:userID', async (req, res) => {
      const headers: OutgoingHttpHeaders = {
        'Content-Type': 'text/event-stream',
        'Connection': 'keep-alive',
        "Cache-Control": 'no-cache',
        "X-Accel-Buffering": 'no'
      }
      res.writeHead(200, headers)
      res.write(JSON.stringify({ type: 'handshake' } satisfies IEventMessage))
    }
    

    有知道的大佬吗,实在不行我滚回 long-loop 了

    13 条回复    2024-07-21 18:06:13 +08:00
    LuckyLauncher
        1
    LuckyLauncher  
       62 天前
    proxy_set_header Connection "";
    直接把 keep-alive 干掉了?
    ChrisFreeMan
        2
    ChrisFreeMan  
    OP
       62 天前
    @LuckyLauncher 刚才验证了下,并不相干呢
    cnleon
        3
    cnleon  
       62 天前
    你客户端支持 http2 吗?还有可以抓一下 nginx 到服务器端之间的包。对比一下和 80 的区别。
    ysc3839
        4
    ysc3839  
       62 天前 via Android
    去掉 proxy_read_timeout chunked_transfer_encoding 试试?
    ChrisFreeMan
        5
    ChrisFreeMan  
    OP
       62 天前
    @ysc3839 没有影响,我能收到那个 200 的返回,但是就是收不到写入的数据。
    ChrisFreeMan
        6
    ChrisFreeMan  
    OP
       62 天前
    @cnleon 客户端是 nodejs 的 fetch ,应该是默认启用的,抓包还没试过,我最后再试试
    ilylx2008
        7
    ilylx2008  
       62 天前
    location /sse {
    proxy_set_header Host $http_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 Content-Type text/event-stream;
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;
    proxy_cache off;
    proxy_buffering off;
    #rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://go;
    }
    ilylx2008
        8
    ilylx2008  
       62 天前
    我用了 sse 后发现还是一步到位直接 websocket 更好点,方便扩展。
    ChrisFreeMan
        9
    ChrisFreeMan  
    OP
       62 天前
    @ilylx2008 嗯嗯感谢回复,我也打算换掉这个方案了。上面的配置试了也还是一样,本人能力有限搞不定。
    kk2syc
        10
    kk2syc  
       61 天前
    location /sse {
    proxy_pass https://example.com/sse;

    proxy_buffering off;

    proxy_set_header Cache-Control 'no-cache';
    proxy_set_header Connection 'keep-alive';

    proxy_set_header Host $http_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;
    }
    }
    kk2syc
        11
    kk2syc  
       61 天前
    Nginx 的 $http_host 、$host 、$proxy_host 是有区别的
    ChrisFreeMan
        12
    ChrisFreeMan  
    OP
       61 天前
    @kk2syc 以上都试过了无效,我已经切到 long-polling 方案了,对即时性要求不高,而且不用第三方库就可以实现,简单可靠。
    ChrisFreeMan
        13
    ChrisFreeMan  
    OP
       61 天前
    @kk2syc 顺便感谢回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2769 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:43 · PVG 14:43 · LAX 23:43 · JFK 02:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.