我有一个收集和分析使用指标的服务器。我希望架构的各个部分能够通过 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 个指标收集线程在运行,因此操作系统线程限制并不大关心。
但是我想知道分拆新线程所需的内存和 CPU 时间开销是多少(不计算实际执行 Net::HTTP 调用所需的内存/CPU)?这种方法有明显的缺点吗?
最佳答案
简短的回答是肯定的 - 启动一个新的临时线程会产生非常显着的内存和 CPU 开销!
每当您想要执行后台作业时避免创建新线程的行业标准是使用 thread pools ,它们只是预先创建的一些线程,等待接收消息并相应地执行工作。
查看类似的解决方案(例如 newrelic 的解决方案),大多数都使用后台进程(或代理),负责实际将信息发送到服务器,而应用程序则发送轻量级信息向代理发送消息,代理在方便时聚合并批量发送这些消息。
在 Rails 系统中,不建议从头开始构建后台作业,您应该考虑使用像 sidekiq 这样的 gem 及其建议的架构来为您执行此操作。其中大多数也不依赖于主应用程序中的线程,而是依赖于它们自己的进程(有时在它们自己的机器上),通过队列上的消息与应用程序进行通信(使用像 Redis 这样的存储库)例如)。
关于ruby - 在 Ruby 中使用线程进行指标收集会产生大量开销吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24212309/