93

在服务器端使用带有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 1024upstreamsection 和proxy_set_header Connection keep-alive;in 中尝试过location

没有什么帮助:(

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

4

3 回答 3

224

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

EventSource这是一个通过 Nginx 工作的“神奇三重奏” :

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

将它们放入location部分中,它应该可以工作。

您可能还需要添加

proxy_buffering off;
proxy_cache off;

这不是官方的做法。

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

于 2012-12-02T20:05:13.663 回答
20

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

于 2015-10-29T12:20:19.813 回答
11

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

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

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

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

于 2015-02-14T20:42:55.463 回答