Допустим, мне нужно сделать сложные вычисления для 100 пользователей. Моя текущая конфигурация выглядит так:
производитель
class Producer
class << self
def publish(target, options = {})
connection = Bunny.new(some_params).start
channel = connection.create_channel
exchange = channel.fanout("#{target}_exchange", durable: true)
exchange.publish(options.to_json)
end
end
end
MassComplexCalculations рабочий
module UsersWorkers
class MassComplexCalculations
include Sneakers::Worker
from_queue "#{ENV['RAILS_ENV']}.users.mass_complex_calculations_queue",
exchange: "#{ENV['RAILS_ENV']}.users.mass_complex_calculations_exchange"
def work(options)
parsed_options = JSON.parse(options)
ActiveRecord::Base.connection_pool.with_connection do
User.where(id: parsed_options['ids']).each do |user|
::Services::Users::ComplexCalculations.call(user)
end
end
ack!
end
end
end
бегущий рабочий
Producer.publish("#{ENV['RAILS_ENV']}.users.mass_complex_calculations", ids: User.limit(100).ids)
Я не совсем понимаю, как AMQP распределяет ресурсы для выполнения задач и как я могу помочь. Правильно ли, что каждый расчет лучше проводить на отдельном работнике? Например:
ИЗМЕНЕНО MassComplexРасчет работника
module UsersWorkers
class MassComplexCalculations
include Sneakers::Worker
from_queue "#{ENV['RAILS_ENV']}.users.mass_complex_calculations_queue",
exchange: "#{ENV['RAILS_ENV']}.users.mass_complex_calculations_exchange"
def work(options)
parsed_options = JSON.parse(options)
ActiveRecord::Base.connection_pool.with_connection do
parsed_options['ids'].each do |id|
Producer.publish("#{ENV['RAILS_ENV']}.users.personal_complex_calculations", id: id)
end
end
ack!
end
end
end
NEW PersonalComplexCalculations рабочий
module UsersWorkers
class PersonalComplexCalculations
include Sneakers::Worker
from_queue "#{ENV['RAILS_ENV']}.users.personal_complex_calculations_queue",
exchange: "#{ENV['RAILS_ENV']}.users.personal_complex_calculations_exchange"
def work(options)
parsed_options = JSON.parse(options)
user = User.find(parsed_options['id'])
ActiveRecord::Base.connection_pool.with_connection do
::Services::Users::ComplexCalculations.call(user)
end
ack!
end
end
end
В моем понимании, возможны два варианта:
- первая реализация может работать медленнее, потому что она будет вызывать службу для каждого пользователя, в то время как во втором варианте у нас будет 100 одновременно работающих работников, которые будут выполнять свою работу параллельно
- разницы нет
Так какой подход лучше? А может, даже один из них совершенно не прав?
Заранее спасибо.