这是我为解决问题而设置的一个简单的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异常。
这是我迄今为止所做的尝试:
搜索互联网也提供了很少的帮助。
我不知所措,需要一些指导。
这里是两个curl调用的输出,有和没有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
~/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时,为什么不能将整个内容流式传输?
答案 0 :(得分:19)
事实证明,我需要的是我的位置指令中的这一行,以便通过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引入了分块传输编码,允许持久连接上的内容进行流式传输而不是缓冲。
所以我遇到了问题。
TIL