【问题标题】:Run websocket onmessage in different thread在不同的线程中运行 websocket onmessage
【发布时间】:2013-11-18 12:01:48
【问题描述】:

我在如下服务器上使用 websocket。它响应onmessage 事件,并根据消息条件执行不同的任务:

require "websocket-eventmachine-server"

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) Here, the current thread is the main thread
      ...
    else
      # (C) Here, the current thread is the main thread
      ...
    end 
  end
end

每个onmessage事件执行的线程(上面描述为BC)每次都是相同的,它们与主线程相同(上面描述为A)。

我想以C 的形式在单独的线程中执行B 中的代码。一种方法是将BC 中的操作放在一个新线程中,如下所示:

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) Here, the current thread will be created each time.
      Thread.new{...}
    else
      # (C) Here, the current thread will be created each time.
      Thread.new{...}
    end
  end
end

但是每次发生事件时创建一个新线程似乎很繁重,并且使响应变慢。所以,我希望在B 中处理的所有onmessage 事件之间共享一个线程,在C 中处理的所有事件之间共享另一个线程:

WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
  # (A) Here, the current thread is the main thread
  ws.onmessage do |s|
    if foo
      # (B) I want this part to be executed in a thread
      #     that does not change each time, but is different from the thread in C
      ...
    else
      # (C) I want this part to be executed in a thread
      #     that does not change each time, but is different from the thread in B
      ...
    end
  end
end

有什么好的方法可以做到这一点?或者,是否有更好的结构来以相互非阻塞的方式响应 websocket onmessage 事件?

【问题讨论】:

    标签: ruby multithreading websocket eventmachine em-websocket


    【解决方案1】:

    使用EventMachine.defer方法在其内部线程池中执行代码。

    【讨论】:

    • 你说的不够清楚,但是除了EventMachine.defer之外还有WebSocket::EventMachine.defer
    【解决方案2】:

    您可以将接收到的消息制作成队列,并按队列制作一个线程以执行 特点:

    def do_foo(message)
       .... your code
    end
    def do_fee(message)
       .... your code
    end
    
    queueA= Queue.new
    queueB= Queue.new
    Thread.new { loop { do_foo(queueA.pop) } }
    Thread.new { loop { do_fee(queueB.pop) } }
    WebSocket::EventMachine::Server.start(host: some_server_name, port: some_port) do |ws|
      # (A) Here, the current thread is the main thread
      ws.onmessage do |s|
        if foo
           queueA.push(s)
        else
           queueB.push(s)
        end
      end
    end
    

    警告!如果 do_foo/fee 需要在 websocket 上发送消息,你应该 在 EM.next_tick { if .. } 中调用 'if foo..'。

    【讨论】:

    • do_foodo_fee 是如何定义的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 2017-02-09
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多