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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13672743/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 05:34:00  来源:igfitidea点击:

EventSource / Server-Sent Events through Nginx

rubynginxsinatra

提问by Lukas Mayer

On server-side using Sinatra with a streamblock.

在服务器端使用带有stream块的Sinatra 。

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

On client side:

在客户端:

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

When i using app directly, via http://localhost:9292/, everything works perfect. The connection is persistent and all messages are passed to all clients.

当我直接使用应用程序时,通过http://localhost:9292/,一切正常。连接是持久的,所有消息都传递给所有客户端。

However when it goes through Nginx, http://chat.dev, the connection are dropped and a reconnection fires every second or so.

但是,当它通过 Nginx 时http://chat.dev,连接会断开,并且每隔一秒左右就会重新连接一次。

Nginx setup looks ok to me:

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

Tried keepalive 1024in upstreamsection as well as proxy_set_header Connection keep-alive;in location.

试图keepalive 1024upstream段以及proxy_set_header Connection keep-alive;location

Nothing helps :(

没有任何帮助:(

No persistent connections and messages not passed to any clients.

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

回答by

Your Nginx config is correct, you just miss few lines.

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

Here is a "magic trio" making EventSourceworking through Nginx:

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

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

Place them into locationsection and it should work.

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

You may also need to add

您可能还需要添加

proxy_buffering off;
proxy_cache off;

That's not an official way of doing it.

这不是官方的做法。

I ended up with this by "trial and errors" + "googling" :)

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

回答by E1.

Another option is to include in your response a 'X-Accel-Buffering' header with value 'no'. Nginx treats it specially, see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering

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

回答by Martin Konecny

Don't write this from scratch yourself. Nginx is a wonderful evented server and has modules that will handle SSE for you without any performance degradation of your upstream server.

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

Check out https://github.com/wandenberg/nginx-push-stream-module

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

The way it works is the subscriber (browser using SSE) connects to Nginx, and the connection stops there. The publisher (your server behind Nginx) will send a POST to Nginx at a corresponding route and in that moment Nginx will immediately forward to the waiting EventSource listener in the browser.

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

This method is much more scalable than having your ruby webserver handle these "long-polling" SSE connections.

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