我们有一个运行resque
的多租户应用进行后台处理。
我们偶尔遇到的问题是,单个租户在很短的时间内完成很多的后台工作。这基本上堵塞了一段时间 - 在我们处理这个单一租户的积压工作时,其他每个租户的工作都被延迟了。
是的,我们可以添加更多工人。但这不是一个真正的解决方案"它更像是一个创可贴,但仍会导致其他租户的延迟 - 只是因为我们处理得更快而延迟更短。
是否有更多多租户友好的方式使用resque
?或者更多的多租户友好背景队列?
我们正在考虑:
resque
,使其以某种方式循环通过每个租户的队列我们只是想知道我们是否有一些错过/更好的方式...
答案 0 :(得分:0)
您可以使用Rails.cache
维护每个参与者的临时作业计数器,并根据活动作业的数量将作业分配到不同的队列。
您需要将作业子类化以支持不同的队列,并编写一个解析为该作业的正确类的方法。类似的东西:
class Worker
cattr_acessor :tenant_id
class Worker::Low < Worker
@queue = :low
end
class Worker::High < Worker
@queue = :high
end
def self.queued
"#{name}::#{resolved_queue(tenant_id)}".constantize
end
def self.resolved_queue tenant_id
count = job_count(tenant_id)
if count > 1000
'Low'
else
'High'
end
end
def self.cache_key tenant_id
"job_count/#{tenant_id}"
end
def self.job_count tenant_id
Rails.cache.fetch(cache_key(tenant_id)){0}
end
def self.job_count_increment tenant_id
Rails.cache.fetch(cache_key(tenant_id)){0}
Rails.increment(cache_key(tenant_id)){0}
end
def self.job_count_decrement tenant_id
count = Rails.cache.fetch(cache_key(tenant_id)){0}
Rails.decrement(cache_key(tenant_id)){0} if count > 0
end
end
然后在运行工作人员时调用Worker.queued(tenant_id).perform
,并确保在应用程序中的Worker.tenant_id
上设置了before_filters
。有关队列和优先级的更多信息,请参阅Resque Priorities and Queue Lists。
您应该在作业队列中调用增量并从作业中减少。
丑陋,但可行。
可以通过一些元编程使其更加干燥 - 将这些方法提取到模块中,然后确保在模块include上生成队列子类。