在不同的线程中运行websocket onmessage

时间:2013-11-18 12:01:49

标签: ruby multithreading websocket eventmachine em-websocket

我在服务器上使用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)每次都是相同的,并且它们与主线程相同(描述为{上面{1}}。

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

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) 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 中处理的所有onmessage个事件中共享一个线程,并在B中处理的所有事件之间共享另一个线程:

C

这样做的好方法是什么?或者,是否有更好的结构以相互非阻塞的方式响应websocket 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 事件?

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:-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 ..'。