Ruby on rails RabbitMQ/Sneakers-将特定队列一次仅限制为一个工作者?

Ruby on rails RabbitMQ/Sneakers-将特定队列一次仅限制为一个工作者?,ruby-on-rails,ruby,rabbitmq,sneakers,Ruby On Rails,Ruby,Rabbitmq,Sneakers,我有一个RabbitMQ和Sneakers gem的用例,其中我有多个工作人员在运行,以响应我项目中的几十个队列。因此,工作人员很可能同时处理来自同一队列的消息 但是,特别是一个队列——我们称之为:一次一个队列——我只希望一个工人能够在任何给定时间处理队列中的消息 我之所以要这样做,是因为worker设计用于执行以下操作: 通过传入的ID查找AR对象 检查是否设置了一个属性(比如:worked)。 如果true,则ack消息 如果为false,请通过电子邮件发送给用户,然后将:worked设置为

我有一个RabbitMQ和Sneakers gem的用例,其中我有多个工作人员在运行,以响应我项目中的几十个队列。因此,工作人员很可能同时处理来自同一队列的消息

但是,特别是一个队列——我们称之为
:一次一个队列
——我只希望一个工人能够在任何给定时间处理队列中的消息

我之所以要这样做,是因为worker设计用于执行以下操作:

  • 通过传入的ID查找AR对象
  • 检查是否设置了一个属性(比如:worked)。
  • 如果
    true
    ,则
    ack消息
  • 如果
    为false
    ,请通过电子邮件发送给用户,然后将
    :worked
    设置为true
  • 这样设计的目的是,在两条消息以相同的对象ID快速连续创建的情况下,我不会意外地向用户发送两次电子邮件。如果在任何给定时间只有一个工作人员听过此队列,此设计将很好地工作,因为第一次运行将通过步骤1->2->2,然后下一次运行将执行步骤1->2->1,并且不会向用户发送电子邮件。但在测试中,我发现存在一种潜在的竞争条件,即两名工作人员将同时从
    :一次一条
    队列中拉出一条消息,通过设置
    :worked
    的检查,并发送电子邮件


    因此,考虑到所有这些,有没有一种方法可以限制侦听队列的工作人员的数量?谢谢。

    如需进一步参考,Argus9的请求可以按照以下步骤存档:

    1) 您可以将员工的选择控制为:

    class YourWorker
    include Sneakers::Worker
    from_queue "your_queue",
               :env => nil,
               :ack => true,
               :workers => 1, #Number of per-cpu processes to run
               :prefetch => 1, #This param will define that single message will be fetched per time
               :threads => 1, #This will define that you have single thread running
               :heartbeat => 2,
               :share_threads => true,
               :timeout_job_after => 3600,
               :exchange => 'your_exchange'
    
    def work(args={})
     #... your steps here
    end 
    end
    
    2) 您需要注意您在sneakers.rb中指定的初始参数(在worker初始化时由sneakers::Runner使用),因此请确保其中包含正确的参数,如:

    Sneakers.configure  :amqp => url,
                    :daemonize => true,
                    :ack => true,
                    :prefetch => 1,
                    :threads => 1,
                    :start_worker_delay => 0.1,  
                    :workers => 1,               
                    :exchange => "your_exchange",
                    :exchange_type => :direct,
                    :log => "log/sneakers.log"
    Sneakers.logger.level = Logger::DEBUG
    
    您还可以使用RabbitMQ API构建一些额外的控件,这将使您能够检查是否已经有一些消息正在处理?。。。等什么是不是很容易存档使用兔子等。 使用非常简单的代码,如:

        def queue_info
        queues_infos = {}    
        rabbitmqctl_url = "http://127.0.0.1:15672"
        rabbitmqctl_user = "your_user"
        rabbitmqctl_password = "your_password"
        uri = URI.parse("#{rabbitmqctl_url}/api/queues")
        request = Net::HTTP::Get.new(uri)
        request.basic_auth(rabbitmqctl_user, rabbitmqctl_password)
        req_options = { use_ssl: uri.scheme == 'https' }
        response = Net::HTTP.start(uri.hostname, uri.port, req_options)  do |http|
          http.request(request)
        end
        queue_details = JSON.parse(response.body)
        queue_details.each do |queue|
          queues_infos[queue['name'].to_s] = {  name: queue['name'],
                                                msg_total: queue['messages'],
                                                msg_ready: queue['messages_ready'],
                                                msg_unacknowlged: queue['messages_unacknowledged'],
                                                state: queue['state'],
                                                consumers: queue['consumers'] }
        end
        return queues_infos
    end
    

    你找到解决办法了吗?有着完全相同的问题,并且很想知道你是如何解决的。