EventSource / 服务器通过 Nginx 发送的事件

问题描述 投票:0回答:4

在服务器端使用带有

stream
块的Sinatra。

get '/stream', :provides => 'text/event-stream' do
  stream :keep_open do |out|
    connections << out
    out.callback { connections.delete(out) }
  end
end

在客户端:

var es = new EventSource('/stream');
es.onmessage = function(e) { $('#chat').append(e.data + "\n") };

当我通过

http://localhost:9292/
直接使用应用程序时,一切都很完美。连接是持久的,所有消息都传递给所有客户端。

然而,当它通过 Nginx 时,

http://chat.dev
,连接断开,大约每秒触发一次重新连接。

Nginx 设置对我来说没问题:

upstream chat_dev_upstream {
  server 127.0.0.1:9292;
}

server {
  listen       80;
  server_name  chat.dev;

  location / {
    proxy_pass http://chat_dev_upstream;
    proxy_buffering off;
    proxy_cache off;
    proxy_set_header Host $host;
  }
}

keepalive 1024
部分尝试了
upstream
以及
proxy_set_header Connection keep-alive;
中的
location

没有任何帮助:(

没有持久连接和消息不传递给任何客户端。

ruby nginx sinatra
4个回答
254
投票

你的 Nginx 配置是正确的,你只是错过了几行。

这是通过 Nginx 制作

EventSource
的“魔术三重奏”:

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

将它们放入

location
部分,它应该可以工作。

您可能还需要添加

proxy_buffering off;
proxy_cache off;

这不是官方的做法。

我通过“反复试验”+“谷歌搜索”得到了这个:)


30
投票

另一个选项是在您的响应中包含一个值为“no”的“X-Accel-Buffering”标头。 Nginx 对其进行了特殊处理, 见http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering


11
投票

不要自己从头开始写这个。 Nginx 是一个很棒的事件服务器,它的模块可以为您处理 SSE,而不会降低上游服务器的性能。

查看https://github.com/wandenberg/nginx-push-stream-module

它的工作方式是订阅者(使用SSE的浏览器)连接到Nginx,然后连接就停止了。发布者(您的 Nginx 后面的服务器)将在相应的路由上向 Nginx 发送 POST,此时 Nginx 将立即转发给浏览器中等待的 EventSource 侦听器。

此方法比让您的 ruby 网络服务器处理这些“长轮询”SSE 连接更具可扩展性。


0
投票

嗨,将此评论从 Did 提升为答案:这是我通过 Nginx 使用 HttpStreamingResponse 从 Django 流式传输时唯一需要添加的内容。上面的所有其他开关都没有帮助,但这个标头有帮助。

让服务器响应“X-Accel-Buffering: no”标头很有帮助! (参见:wiki.nginx.org/X-accel#X-Accel-Buffering)—— 2013 年 7 月 1 日 16:24 做的

© www.soinside.com 2019 - 2024. All rights reserved.