通过Nginx发送EventSource / Server-Sent事件

时间:2012-12-02 19:12:20

标签: ruby nginx sinatra

在服务器端使用带有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

没有任何帮助:(

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

3 个答案:

答案 0 :(得分:137)

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

这是一个“魔术三重奏”让EventSource通过Nginx工作:

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

将它们放入location部分,它应该有效。

您可能还需要添加

proxy_buffering off;
proxy_cache off;

这不是官方的做法。

我通过“试验和错误”+“谷歌搜索”结束了这一点:)

答案 1 :(得分:5)

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

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

它的工作方式是订户(使用SSE的浏览器)连接到Nginx,连接在那里停止。发布者(你的Nginx背后的服务器)将在相应的路由上向Nginx发送一个POST,在那一刻,Nginx将立即转发到浏览器中等待的EventSource监听器。

这种方法比ruby webserver处理这些&#34;长轮询&#34;更具可扩展性。 SSE连接。

答案 2 :(得分:5)

另一种选择是在您的回复中包含“X-Accel-Buffering&#39;带有值的标题&#39; no&#39;。 Nginx专门对待它, 见http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering