【问题标题】:Rails network calls extremely slow from Sneakers worker来自 Sneakers 工作人员的 Rails 网络调用速度极慢
【发布时间】:2017-04-03 09:41:33
【问题描述】:

我现在遇到了一个问题,我很乐意接受人们可能提出的任何想法。

问题:在 Sneakers worker 中运行时,网络调用非常慢(Redis、HTTP)。例如,在 redis 中设置一个键大约需要 20 秒,而 HTTP get 调用大约需要 38 秒。从 rails c 开始,相同的 redis 调用需要

设置:我会尽量简洁。

  • 一切都在 Docker 中运行(Rails + worker、Redis、Postgres 等)
  • Rails 4.2.7 是主要的网络应用,使用 puma 作为网络服务器
  • 有两个后台作业通过 Sneakers 处理并通过 RabbitMQ 消息触发。这些“工作者”包括对继承自 ActiveRecord 的类的调用,这些类执行实际活动(即进行 HTTP 调用或与 Redis 交互)
  • 我已经简化并且只在 Worker 类中进行 HTTP 调用(它没有做其他任何事情)。我也将其移至前台进行调试。

Puma 配置为以“单一”模式运行(无工作人员,1 个线程)。这是我目前的运动鞋配置:

# config/initializers/02_sneakers.rb
  Sneakers.configure  daemonize: false,
                      amqp: "amqp://rabbitmq",
                      # log: "log/sneakers.log",
                      log: STDOUT,
                      pid_path: "tmp/pids/sneakers.pid",
                      threads: 2,
                      workers: 1,
                      durable: true,
                      vhost: '/',
                      exchange: 'exchange',
                      exchange_type: 'direct'

Sneakers.logger.level = Logger::DEBUG

还有我的工人:

class StepWorker
  include Sneakers::Worker
  from_queue "queue", env: nil, timeout_job_after: 5.minutes, durable: true, ack: true

  def work(raw_event)
    logger.info { 'StepWorker received params: ' + raw_event }
    message = JSON.parse(raw_event)

    response = ""
    time = Benchmark.measure {
      response = RestClient.get('http://store/', { accept: :json })
    }
    logger.info { "response: #{response.length} in #{time.real}" }

    ack!
  end
end

我也有一个issue 和一些人一起在运动鞋上。任何想法都非常感谢!

【问题讨论】:

    标签: ruby-on-rails ruby rabbitmq


    【解决方案1】:

    我错过了上述问题中的一个关键细节,它导致了问题的根源并排除了运动鞋。

    发送的有效负载约为 10MB,rails 可以在大约 27ms 内查询,但需要 30 秒才能呈现为 JSON 并传输(为什么这么慢是另一个与 conf / docker 相关的问题)。

    由于负载大小,Redis 随后会超时(但是 10MB 的吞吐量不应该这么慢)。

    时间问题(无法重现)是由于在测试 HTTP 时缺少禁用分页。没有分页,大小达到 10MB,事情开始分崩离析。

    所以,这里的答案是问题与运动鞋无关,但它因此变得非常复杂。移除 Sneakers 并直接运行命令会是一个更好的起点:

    irb(main):002:0> time = Benchmark.measure {
    irb(main):003:1*   response = RestClient.get('http://store?pagination=false', { accept: :json })
    irb(main):004:1> }
    => #<Benchmark::Tms:0x00555f80bd3708 @label="", @real=39.22218326000075, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.030000000000000027, @total=0.030000000000000027>
    irb(main):006:0> 
    irb(main):007:0* time = Benchmark.measure {
    irb(main):008:1*   StashService.set("cool", JSON.parse(response))
    irb(main):009:1> }
    Redis::TimeoutError: Connection timed out
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:111:in `rescue in _write_to_socket'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:104:in `_write_to_socket'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:131:in `block in write'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:130:in `loop'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:130:in `write'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/connection/ruby.rb:374:in `write'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/client.rb:271:in `block in write'
        from /usr/local/bundle/gems/redis-3.3.2/lib/redis/client.rb:250:in `io'
    ...
    4.2.7/lib/rails/commands/commands_tasks.rb:68:in `console'
        from /usr/local/bundle/gems/railties-4.2.7/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from /usr/local/bundle/gems/railties-4.2.7/lib/rails/commands.rb:17:in `<top (required)>'
        from bin/rails:4:in `require'
        from bin/rails:4:in `<main>'
    

    【讨论】:

    • 只是为了添加另一条信息。通过更改development.rb 中的以下内容,我的性能问题得到了解决(敲木头):config.assets.debug = false
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多