【问题标题】:Rails extremely slow on simple static renderRails 在简单的静态渲染上非常慢
【发布时间】:2013-07-19 16:48:40
【问题描述】:

我对 Rails 比较陌生,但决定在这个平台上开发我的新项目。我正在使用基于 Ruby 2.0 和 Unicorn 的新 Rails 4 框架作为通过 Nginx 提供的应用程序服务器。 经过一些初步开发后,我将我的应用程序部署到了 Amazon EC2 小型服务器上,并且对缓慢的性能感到震惊,并使用简单的 ab 实用程序对其进行了测试。为您提供更多详细信息:

独角兽配置文件​​:

# config/unicorn.rb
env = ENV["RAILS_ENV"] || "development"

worker_processes 1

listen 8080, :backlog => 64

preload_app true

timeout 30

pid "/tmp/unicorn.mysite.pid"


if env == "production"

  working_directory "/mypath/current"

  user 'ubuntu', 'ubuntu'
  shared_path = "/mypath/shared"

  stderr_path "#{shared_path}/log/unicorn.stderr.log"
  stdout_path "#{shared_path}/log/unicorn.stdout.log"
end

before_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
  end

  old_pid = "/tmp/unicorn.mysite.pid.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
  end

end

routes.rb:

root to: "home#index"

home_controller.rb:

def index
    render "index", layout: false
end

index.html.erb 主要是静态的 3kb 文件
没有数据库查询,Unicorn 在生产模式下运行,Rails 中启用了部分缓存。

ab -n 1000 -c 100 http://myinstance.amazon.com/ 返回 30-40 个请求/每秒的性能,平均 3-4 秒的响应时间(请记住我使用的是小型 1cpu 实例),增加到四个时甚至更少.奇怪的是,当我尝试在亚马逊的中型实例上测试应用程序时,它并没有提高性能,暗示它可能受到磁盘 io 的限制。好吧,当我在 PHP 和 node.js 堆栈上复制相同的简单应用程序时,与上述 Rails 相比,性能显着提高(每秒处理更多请求,响应时间更短)。

Rails 应用程序正常吗?任何提示如何提高性能?也许一些配置调整?我尝试搜索,但我看到的大部分关于 Rails 代码改进的一般信息在此处不适用,因为示例过于简单。

更新 #1 我应要求提供了 production.log 的片段,它们的不同之处在于:

I, [2013-07-20T13:21:44.830189 #1852]  INFO -- : Started GET "/" for xx.xx.xx.xx at 2013-07-20 13:21:44 +0000
I, [2013-07-20T13:21:44.831420 #1852]  INFO -- : Processing by HomeController#index as */*
I, [2013-07-20T13:21:44.832519 #1852]  INFO -- :   Rendered layouts/_head.html.erb (0.5ms)
I, [2013-07-20T13:21:44.834213 #1852]  INFO -- :   Rendered layouts/_header.html.erb (1.5ms)
I, [2013-07-20T13:21:44.834966 #1852]  INFO -- :   Rendered layouts/_footer.html.erb (0.0ms)
I, [2013-07-20T13:21:44.835143 #1852]  INFO -- :   Rendered home/index.html.erb (3.2ms)
I, [2013-07-20T13:21:44.835356 #1852]  INFO -- : Completed 200 OK in 4ms (Views: 3.5ms | ActiveRecord: 0.0ms)

到:

I, [2013-07-20T13:21:44.689225 #1852]  INFO -- : Started GET "/" for xx.xx.xx.xx at 2013-07-20 13:21:44 +0000
I, [2013-07-20T13:21:44.690629 #1852]  INFO -- : Processing by HomeController#index as */*
I, [2013-07-20T13:21:44.716144 #1852]  INFO -- :   Rendered layouts/_head.html.erb (24.7ms)
I, [2013-07-20T13:21:44.718191 #1852]  INFO -- :   Rendered layouts/_header.html.erb (1.7ms)
I, [2013-07-20T13:21:44.718919 #1852]  INFO -- :   Rendered layouts/_footer.html.erb (0.0ms)
I, [2013-07-20T13:21:44.719042 #1852]  INFO -- :   Rendered home/index.html.erb (27.7ms)
I, [2013-07-20T13:21:44.719280 #1852]  INFO -- : Completed 200 OK in 28ms (Views: 28.2ms | ActiveRecord: 0.0ms)


更新 #2 我试图发出 10000 个后续请求,而服务器只是在中间超时

ab -n 10000 -c 100 http://myinstance.amazon.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking myinstance.amazon.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
apr_socket_recv: Connection timed out (110)
Total of 3457 requests completed

【问题讨论】:

  • 您能包含一段 production.log 吗? (服务器启动和一些请求)
  • 我在帖子中添加了几条生产日志
  • 您在服务器上以生产模式运行 rails 吗?并在运行ab 之前启动应用程序? worker_processes 1 也意味着您一次只能处理 1 个请求 - 尝试至少达到 2 个,你可以更高,但我认为建议每个处理器 1 个 - 也可以考虑 puma 而不是 unicorn - 请参阅 @ 987654321@
  • 用 puma 试过,用线程数玩了一点,通常它在单模式下提供与独角兽相似的性能。在具有集群的多核实例上可能会胜过它。但是单cpu的性能还是慢得要命,每秒40个左右的请求。最糟糕的是,大约 2% 的请求在 20 秒后得到处理!这将转化为任何电子商务中失去的机会和客户

标签: ruby-on-rails performance


【解决方案1】:

这似乎是相当预期的结果。您比较了 3 个不同的东西:全功能框架 (Rails)、平台 (Node.js) 和语言 (PHP)。

让我们看看我们是如何分割响应时间的:

[total time] = [web server processing  time] + [framework infrastructure time] 
             + [language interpreter time] + [your app logic time]

当然,如果您的应用程序什么都不做,可以忽略最后一个组件。

当您运行 PHPNode.js 应用程序时,总和中只剩下 2 个组件[web server processing time] + [language interpreter time],因此它可以处理请求非常快。 Rails 在此处添加 3d 组件 [framework infrastructure time]

如果您的应用程序将开始做一些更高级的事情,那么花在框架和网络服务器上的时间对总时间的影响可能较小(相对而言)。尽管 JavaScript 将胜过 Ruby

为了更客观,您最好在 Node.js(如 Express.js)或 PHP(如 Yii 或 Zend Framework)之上添加一些内容。或者使用更轻量级的东西而不是 Rails 来更快地处理小请求(例如 Sinatra)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多