来自Sneakers工作人员

时间:2016-11-19 17:15:18

标签: ruby-on-rails ruby rabbitmq

我现在有一个问题,并且会对人们可能有的任何想法感到非常满意。

问题:在Sneakers工作者中运行时,网络调用非常慢(Redis,HTTP)。例如,在redis中设置密钥大约需要20秒,而HTTP调用大约需要38秒。从rails c相同的redis调用< 1秒钟,HTTP呼叫大约一秒钟。

设置:尽可能简洁。

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

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

# 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。任何想法都非常感谢!

1 个答案:

答案 0 :(得分:0)

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

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

Redis随后因有效载荷大小而超时(但10MB吞吐量不应该太慢)。

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

所以,这里的答案是问题与运动鞋无关,但由于它的原因,它非常复杂。删除运动鞋并直接运行命令将是一个更好的起点:

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>'