【问题标题】:Rails 4, Puma, Nginx - ActionController::Live Streaming dies after first chunk sentRails 4,Puma,Nginx - ActionController::Live Streaming 在发送第一个块后死亡
【发布时间】:2014-04-20 14:18:41
【问题描述】:

这是我为解决我的问题而设置的一个基本 Rails 4 项目:

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

我在 /home/stream 设置了一条路由,它应该以 1 秒的间隔将一行文本流式传输 5 次。

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

当我使用 tcp:// 运行 puma 时,没有 nginx,流式传输可以完美运行。

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

我得到了 5 行流式传输,没问题。

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

它也不会像用户断开连接时那样抛出 IOError 异常。

这是我迄今为止尝试过的:

  • 主 conf 文件中 nginx 指令的不同组合和 服务器配置。
  • 更改导轨设置。
  • 各种 puma 配置设置。
  • 在控制器方法中设置各种不同的标头,希望这是一个缓存问题。

搜索互联网也提供了很少的帮助。

我不知所措,需要一些指导。

这是两个 curl 调用的输出,有和没有 nginx。

没有 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

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

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 /home/stream HTTP/1.0" 200

在每个 curl 调用中都不同,并且与实际流式传输的文本量有关。

关于这里发生了什么的任何想法?为什么使用 nginx 时 rails 不能流式传输整个内容?

【问题讨论】:

    标签: ruby-on-rails nginx ruby-on-rails-4 streaming puma


    【解决方案1】:

    已解决

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

    proxy_http_version 1.1;

    我在研究 nginx 上游模块中的 keepalive 指令时发现了这个修复:

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

    这段文字特别提示我:

    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;

    根据维基百科,http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

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

    所以这是我的问题。

    直到

    【讨论】:

    • 我仍然不明白的是,在修复之前 curl 报告的响应标头显示“HTTP/1.1 200 OK”、“Transfer-Encoding: chunked”和“Connection: keep-alive "
    • 我只收到第一个事件,之后流关闭并且 curl 给了我这个:curl: (18) transfer closed with outstanding read data remaining,知道可能是什么问题吗?
    • 谢谢!这正是我遇到的问题。
    猜你喜欢
    • 2014-10-28
    • 1970-01-01
    • 2016-05-05
    • 2013-09-29
    • 2014-04-05
    • 2015-01-25
    • 1970-01-01
    • 2016-05-11
    • 2018-01-22
    相关资源
    最近更新 更多