通过Nginx实现EventSource/服务器推送事件

114

使用 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;
  }
}

尝试在upstream部分添加keepalive 1024,并在location中添加proxy_set_header Connection keep-alive;

但这些都没有起作用 :(

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

4个回答

266

你的Nginx配置是正确的,只是缺少几行代码。

这里有一个“魔法三人组”,可以让EventSource通过Nginx正常工作:

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

将它们放入“位置”部分,它应该就可以正常工作了。
您可能还需要添加。
proxy_buffering off;
proxy_cache off;

那不是官方的做法。

我最终通过“试错”和“谷歌搜索”得到了这个结果 :)


9
让服务器响应“X-Accel-Buffering: no”头信息可以大有帮助!(参见:http://wiki.nginx.org/X-accel#X-Accel-Buffering) - Did
18
直到我加入以下内容后才起作用:proxy_buffering off; proxy_cache off; - Malcolm Sparks
6
你的试错 + 我的第一个谷歌搜索结果 = 我喜欢Stack Overflow。谢谢! - Chris Ray
2
你刚刚完成了官方的方式,干得好! http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - Weihang Jian
3
我只需在响应头中添加“X-Accel-Buffering: no”就使其正常工作。 - KKS
显示剩余8条评论

38

2
谢谢,这帮我解决了问题,而无需更改nginx配置。 - Thanh Trung

14

不要从头开始自己编写此内容。 Nginx是一个优秀的事件驱动服务器,并且有模块可以在不降低上游服务器性能的情况下为您处理SSE。

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

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

与让您的Ruby Web服务器处理这些“长轮询”SSE连接相比,这种方法具有更大的可扩展性。


你如何确保高可用性?例如部署两个nginx实例,当你向其中一个发送消息时,它将发布到订阅了这两个实例的客户端。 - The Fool

5

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

让服务器响应“X-Accel-Buffering: no”头部可以帮助很多!(参见:wiki.nginx.org/X-accel#X-Accel-Buffering)- Did 2013年7月1日16:24


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接