多线程 Sneaker 中的对象变量就像一个全局可变数据

Object variables in multithreaded Sneaker works like a global mutable data

我有一个运动鞋工人(如下所示)作为聊天机器人的后端。

  class RabbitMQWorker
    include Sneakers::Worker

    from_queue "message"

    def work(options)
      parsed_options = JSON.parse(options)

      # Initializing some object variables
      @question_id = parsed_options[:question_id]
      @answer = parsed_option[:answer]
      @session_id = parsed_option[:session_id]


      ActiveRecord::Base.connection_pool.with_connection do
        # send next question to the session_id based on answer
      end

      ack!
    end
  end

发生了什么事

我在这里面临的问题是,当我 运行 运动鞋有超过 1 个线程并且多个用户同时聊天时,稍后出现的 ampq 事件会导致覆盖 @session_id 结果,第二个用户得到两个问题,第一个用户得到 none。发生这种情况是因为当第一个事件正在处理时,第二个事件来了并覆盖@session_id。现在,当使用@session_id 将下一个问题发送给第一个用户时,问题将发送给第二个用户。

我的问题

  1. work 方法和我在其中创建的任何 instance variables 是否像运动鞋线程的全局可变数据一样工作?
  2. 如果是,那么我猜我需要将它们作为线程局部变量。如果我这样做,那么我是否也需要在我的 Rails 逻辑中进行这些更改?因为这个工人与 Rails.
  3. 一起工作

好奇心问题

Puma 是如何管理这些事情的?它是一个多线程应用程序服务器,我们在控制器中使用实例变量,它设法同时处理多个请求。这是否意味着 Puma 会隐式处理这种多上下文关系,而 Sneakers 不会?

到目前为止我做了什么

  1. 我阅读了 Sneaker 的文档,但找不到任何相关信息。
  2. 我执行负载测试来验证问题,这就是我上面所说的问题。
  3. 我试着让我的逻辑清楚多线程实际是如何工作的,但到处都只有一般的东西。我上面问的好奇问题对理清概念有很大帮助,我搜索了几天的解释,但找不到任何解释。

在搜索消息似乎混淆的问题 2 天后,我终于能够通过从我的工作人员中删除所有实例变量来解决这个问题。

这个线程给了我这样做的线索:https://github.com/jondot/sneakers/issues/244

maybe we should simply disallow instance variables in workers since changing the behavior to instantiate multiple worker instances might break existing code somehow

和:

I think that an instance per thread is the way to go.

所以当你删除你的实例变量时你应该没问题!