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

62 天前
 ChrisFreeMan

我在本地测试完全没有问题,本地的 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 了

1707 次点击
所在节点    程序员
13 条回复
LuckyLauncher
62 天前
proxy_set_header Connection "";
直接把 keep-alive 干掉了?
ChrisFreeMan
62 天前
@LuckyLauncher 刚才验证了下,并不相干呢
cnleon
62 天前
你客户端支持 http2 吗?还有可以抓一下 nginx 到服务器端之间的包。对比一下和 80 的区别。
ysc3839
62 天前
去掉 proxy_read_timeout chunked_transfer_encoding 试试?
ChrisFreeMan
62 天前
@ysc3839 没有影响,我能收到那个 200 的返回,但是就是收不到写入的数据。
ChrisFreeMan
62 天前
@cnleon 客户端是 nodejs 的 fetch ,应该是默认启用的,抓包还没试过,我最后再试试
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
62 天前
我用了 sse 后发现还是一步到位直接 websocket 更好点,方便扩展。
ChrisFreeMan
62 天前
@ilylx2008 嗯嗯感谢回复,我也打算换掉这个方案了。上面的配置试了也还是一样,本人能力有限搞不定。
kk2syc
62 天前
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
62 天前
Nginx 的 $http_host 、$host 、$proxy_host 是有区别的
ChrisFreeMan
61 天前
@kk2syc 以上都试过了无效,我已经切到 long-polling 方案了,对即时性要求不高,而且不用第三方库就可以实现,简单可靠。
ChrisFreeMan
61 天前
@kk2syc 顺便感谢回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1058808

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX