Rails 4,Puma,Nginx-发送第一个块后,ActionController :: Live Streaming死亡 [英] Rails 4, Puma, Nginx - ActionController::Live Streaming dies after first chunk sent

查看:75
本文介绍了Rails 4,Puma,Nginx-发送第一个块后,ActionController :: Live Streaming死亡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我设置的一个简单的Rails 4项目,用于解决我的问题:

Here's a bare-bones Rails 4 project I've set up to troubleshoot my problem:

https://github.com/rejacobson/rails4-streamtest

我在/home/stream处设置了一条路由,该路由应以1秒为间隔流送一行文本5次.

I have a route set up at /home/stream that should stream a line of text 5 times in 1 second intervals.

def stream
  5.times do |n|
    puts "Streaming: #{n}"
    response.stream.write "Streaming: #{n+1}"
    sleep 1
  end
rescue IOError => e
  puts 'Connection closed'
ensure
  response.stream.close
end

当我在不使用nginx的情况下使用tcp://运行puma时,流式传输可以正常工作.

When I run puma using tcp://, without nginx, the streaming works perfectly.

curl -N http://localhost:3000/home/stream

我将5行流回去,没问题.

And I get the 5 lines streamed back, no problem.

当我介绍nginx时,curl将输出第一行,但此后立即退出.我确实继续在服务器和日志上看到来自puts调用的输出,因此我知道请求仍在5.times循环中处理.

When I introduce nginx, curl will output the first line but immediately exit after that. I do continue to see output from the puts calls on the server and logs, so I know the request is still processing in the 5.times loop.

它也不会引发IOError异常,就像用户断开连接一样.

It also doesn't throw an IOError exception like it would if the user cut the connection.

这是我到目前为止尝试过的:

Here's what I've tried so far:

  • 主conf文件和 服务器配置.
  • 更改滑轨设置.
  • 各种彪马配置设置.
  • 在controller方法中设置各种不同的标头,希望这是一个缓存问题.
  • Different combinations of nginx directives in the main conf file and the server conf.
  • Changing rails settings.
  • Various puma config settings.
  • Setting all kinds of different headers in the controller method in the hopes that it was a caching issue.

搜索互联网也几乎没有帮助.

Searching the internet has provided very little help as well.

我很茫然,需要一些指导.

I'm at a loss and require some direction.

这是两个带有和不带有nginx的curl调用的输出.

Here's the output of both curl calls, with and without nginx.

~/projects/streamtest ▰ master ▰
ryan mirage ▰▰▰▰ curl -i -N http://192.168.1.100:3000/home/stream
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Set-Cookie: request_method=GET; path=/
X-Request-Id: 9ce86358-4476-404a-97e5-769c16ec7b0c
X-Runtime: 0.978099
Transfer-Encoding: chunked

Streaming: 1Streaming: 2Streaming: 3Streaming: 4Streaming: 5

puma.stdout

puma.stdout

Streaming: 0
Streaming: 1
Streaming: 2
Streaming: 3
Streaming: 4
[8048] 192.168.1.100 - - [14/Mar/2014 21:04:50] "GET /home/stream HTTP/1.1" 200 - 6.0661

使用nginx

~/projects/streamtest ▰ master ▰
ryan mirage ▰▰▰▰ curl -i -N http://192.168.1.100:3000/home/stream
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Sat, 15 Mar 2014 04:02:40 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
ETag: "a505e0aa3b11b25301a9a704252a519a"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: request_method=GET; path=/
X-Request-Id: 8983d199-026b-4082-a5f1-f1d6c886a3d6
X-Runtime: 0.016516

Streaming: 1

puma.stdout

puma.stdout

Streaming: 0
[7558] 192.168.1.100 - - [14/Mar/2014 21:02:40] "GET /home/stream HTTP/1.0" 200 - 0.0214
Streaming: 1
Streaming: 2
Streaming: 3
Streaming: 4

有趣的是,我刚刚注意到,它是get request日志行的位置:

What's interesting, and I've just noticed it, is that the location of the get request log line:

获取/home/stream HTTP/1.0" 200

"GET /home/stream HTTP/1.0" 200

在每个curl调用中都不同,并且与实际流送的文本量有关.

is different in each curl call, and is placed in relation to how much text is actually streamed.

关于这里发生的事情有什么想法吗?为什么在使用Nginx时Rails无法流式传输整个内容?

Any ideas as to what's going on here? Why can't rails stream the entire thing when using nginx?

推荐答案

已解决

事实证明,我所需要的只是位置指令中的这一行,以便通过nginx进行流式处理:

Solved

It turns out all that I needed was this line in my location directive to get streaming working through nginx:

proxy_http_version 1.1;

proxy_http_version 1.1;

在研究Nginx的上游模块中的keepalive指令时,我发现了此修复程序:

I discovered this fix when investigating the keepalive directive in nginx's upstream module:

http://nginx.org/en/docs/http/ngx_http_upstream_module. html#keepalive

这一段文字特别吸引我:

This piece of text in particular clued me in:

For HTTP, the proxy_http_version directive should be set to "1.1" and the "Connection" header field should be cleared:

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

nginx似乎默认为proxy_http_version 1.0;

It seems that nginx defaults to, proxy_http_version 1.0;

并且据Wikipedia所述, http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

And according to Wikipedia, http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

HTTP/1.1引入了分块传输编码,以允许流传输而不是缓冲持久连接上的内容.

HTTP/1.1 introduced chunked transfer encoding to allow content on persistent connections to be streamed rather than buffered.

所以这是我的问题.

TIL

这篇关于Rails 4,Puma,Nginx-发送第一个块后,ActionController :: Live Streaming死亡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆