ruby(puma、unicorn、webrick)的HTTP/1.1 100延迟1秒
当我向新创建的rails应用程序发送请求时(使用ruby(puma、unicorn、webrick)的HTTP/1.1 100延迟1秒,ruby,http,Ruby,Http,当我向新创建的rails应用程序发送请求时(使用rails new),它工作得很快: ~ 冬 time curl -v -X POST --data key=value http://localhost:3000/ok Note: Unnecessary use of -X or --request, POST is already inferred. * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1)
rails new
),它工作得很快:
~ 冬 time curl -v -X POST --data key=value http://localhost:3000/ok
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3000 (#0)
> POST /ok HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.51.0
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 9 out of 9 bytes
< HTTP/1.1 200 OK
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: application/json; charset=utf-8
< ETag: W/"a29ee2b15c494311c52521766e44af56"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 99e6d922-dcd6-4e25-89a2-35fa735a401e
< X-Runtime: 0.003076
< Transfer-Encoding: chunked
<
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
{"status":"ok"}curl -v -X POST --data key=value http://localhost:3000/ok 0.00s user 0.00s system 23% cpu 0.014 total
应用程序_controller.rb:
class ApplicationController < ActionController::Base
# protect_from_forgery with: :exception
def ok
render json: {status: 'ok'}
end
end
我在几个不同的linux机器上测试了这一点,同样,类似的php
代码也可以毫不延迟地工作
此外,我尝试调试puma服务器,发现它在此处冻结:
# reactor.rb, line 29
while true
begin
ready = IO.select sockets, nil, nil, @sleep_for # waits one second here
< ... >
#reactor.rb,第29行
虽然是真的
开始
ready=IO。选择套接字,nil,nil,@sleep_for#在这里等待一秒钟
< ... >
sockets
参数包含Puma::Client
实例,我不知道如何将此类的对象传递给IO。选择
有没有办法消除一秒钟的等待 我认为问题实际上在于基准工具(curl
)而不是Ruby应用程序
似乎准备和发送多部分/mime(表单)请求需要更多的时间
我写了一个快速机架应用程序来确认这个问题。将以下代码放入config.ru
:
require 'json'
app = proc do |env|
req = Rack::Request.new(env)
s = req.params.to_json
[200, {"Content-Length": s.bytesize}, [s]]
end
run app
require 'json'
app = proc do |env|
# req = Rack::Request.new(env)
s = "GO!" # req.params.to_json
[200, {"Content-Length": s.bytesize}, [s]]
end
run app
我使用碘运行了应用程序,有8个线程:
$ iodine -t 8 -v
卷曲测试:
$time curl-X POST--data key=value
{“键”:“值”}
实际0.064s
用户0m0.004s
sys 0m0.003s
$time curl--form key=value
{“键”:“值”}
实0m1.021s
用户0m0.004s
系统0m0.004s
解析请求时存在问题
接下来,我删除了请求解析,只返回了一个静态字符串(新的config.ru
):
结果:
$ time curl --form key=value http://localhost:3000/
GO!
real 0m1.019s
user 0m0.004s
sys 0m0.003s
$ time curl -X POST --data key=value http://localhost:3000/
GO!
real 0m0.012s
user 0m0.004s
sys 0m0.003s
换句话说,即使Ruby不执行数据解析(multipart/mime没有被解析),问题仍然存在
我继续用谷歌进行测试…:
$time curl -X POST --data key=value http://google.com/
...
real 0m0.090s
user 0m0.004s
sys 0m0.004s
$ time curl --form key=value http://google.com/
...
real 0m1.083s
user 0m0.004s
sys 0m0.004s
问题在于curl
,准备和发送请求需要更多的时间。这是由于curl和
简言之,curl在发送帖子之前最多会等待1秒,以便服务器响应100 Continue:
time curl --form key=value http://google.com/
> real 0m1.067s
Vs:
sinatra还影响了您使用的http服务器/如何启动rails?以及可能的服务器实现注意事项,这可能是一个机架问题(机架是解析请求的POST正文的机架)。。。你有没有用或测试过这个?它们都是用C编写的,因此它们可能提供更快的HTTP解析。较大的POST数据(这取决于服务器)可能会最终存储在临时文件中,以最小化内存占用。这将影响性能,有利于对其他客户端的响应(假设并发);我没有尝试乘客,因为我们不可能在我们的生产环境中使用它。这真的很棘手,我确信rails中的某个地方出现了问题…非常感谢!
$time curl -X POST --data key=value http://google.com/
...
real 0m0.090s
user 0m0.004s
sys 0m0.004s
$ time curl --form key=value http://google.com/
...
real 0m1.083s
user 0m0.004s
sys 0m0.004s
time curl --form key=value http://google.com/
> real 0m1.067s
time curl --expect100-timeout 0.001 --form key=value http://google.com/
> real 0m0.086s