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


78

在服务器端,使用Sinatra和一个stream块。

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 1024upstream部分和中尝试proxy_set_header Connection keep-alive;location

没有任何帮助:(

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

Answers:


189

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

这是EventSource通过Nginx进行的“魔术三重奏” :

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

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

您可能还需要添加

proxy_buffering off;
proxy_cache off;

这不是官方的方式。

我最后通过“尝试和错误” +“搜索”来结束了这个:)


2
效果很好。伙计,那很难调试。非常感谢!
克里斯·凯斯

2
让服务器响应“ X-Accel-Buffering:no”标题有很大帮助!(参见:wiki.nginx.org/X-accel#X-Accel-Buffering
难道

15
那对我没有用,直到我还添加了以下内容:-proxy_buffering off; proxy_cache关闭;
马尔科姆(Malcolm Sparks)

4
您的反复试验+我的第一个Google匹配=我爱堆栈溢出。谢谢!
克里斯·雷

2
您只是做了OFFICIAL WAY,干得好!nginx.org/zh-CN/docs/http/ngx_http_upstream_module.html#keepalive
航剑


7

不要自己从头开始写这个。Nginx是一个出色的事件服务器,并且具有可以为您处理SSE的模块,而不会影响上游服务器的性能。

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

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

与让ruby Web服务器处理这些“长轮询” SSE连接相比,此方法具有更大的可伸缩性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.