在Ruby中使用线程进行度量标准收集的显着开销?

时间:2014-06-13 19:05:35

标签: ruby multithreading

我有一台收集和分析使用指标的服务器。我希望我的架构的各个部分能够通过REST API定期向服务器发送指标。

我不想在传输指标时阻止执行,所以我考虑过创建一个会剥离线程的方法:

require 'net/http'

module Metrics
  def self.time(time_to_process)
    Thread.new do
      uri = URI.parse(url)
      http = Net::HTTP.new(uri.host, uri.port)
      # ...do a bunch of setup...
      response = http.request(request)
    end
  end
end

......并且在应用程序内部。

def app_method
  # ...do stuff, measure time
  Metrics.time(time_to_process)
end

由于应用程序代码是单线程的,并且app_method执行需要一两秒钟,因此我预计任何时候都不会有超过10-100个度量标准收集线程,因此OS线程限制不是一个大问题。

然而,我想知道在内存和CPU时间方面有什么开销来分拆新线程(不计算实际进行Net :: HTTP调用所需的内存/ CPU)?这种方法有明显的缺点吗?

2 个答案:

答案 0 :(得分:2)

简短的答案是肯定的 - 启动一个新的线程ad-hoc有内存和CPU开销非常重要!

每当您想要执行后台作业时,避免创建新线程的行业标准是使用thread pools,它们只是提前创建的一些线程,等待接收消息,并相应地完成工作。

查看类似的解决方案(如newrelic),大多数使用后台进程(或代理)负责实际将信息发送到服务器,而应用程序向代理发送轻量级消息,并在方便时聚合并批量发送。

在rails系统中,不建议从头开始构建后台作业,您应该考虑使用像sidekiq这样的宝石及其建议的体系结构来为您执行此操作。其中大部分都不依赖于主应用程序中的Threads,而是依赖于他们自己的进程(有时是他们自己的机器),使用队列中的消息与应用程序通信(使用{{例如{3}}。

答案 1 :(得分:1)

我认为你的新线程用例实际上非常好。我已创建新线程以允许应用程序快速响应,并在后台执行某些操作。

正如Uri在他的回答中所提到的,更强大和可扩展的方法是使用后台工作者,例如Sidekiq。但这需要更多的开销和复杂性。

一个重要的考虑因素是失败。如果后台作业失败,您希望发生什么?日志记录?重新开始?如果答案是重启或一些更复杂的功能,那么背景工作者如Sidekiq可能会更好。

关于资源,我认为启动新线程不会消耗太多资源。但这取决于你的用例。一次1个新线程不会被注意到,但100可能太过分了。每个线程消耗多少CPU和资源?

New Relic是测试此内容并监控应用程序CPU和内存使用情况的好方法。

以下是一些有用的有用信息:How many threads is too many?