我期待爲利用Sinatra的內部項目構建一個簡單的RESTful通知系統。過去我使用過EventMachine頻道來訂閱/發佈事件,但在我以前的所有情況下,我都是直接使用EventMachine。是否可以從Thin/Rack/Sinatra訪問Ruby EventMachine頻道?
是否有人知道是否可以從Sinatra應用程序創建,訂閱併發布到EventMachine渠道(以Thin方式運行),或者甚至可以從某些Rack中間件那裏發佈?
我期待爲利用Sinatra的內部項目構建一個簡單的RESTful通知系統。過去我使用過EventMachine頻道來訂閱/發佈事件,但在我以前的所有情況下,我都是直接使用EventMachine。是否可以從Thin/Rack/Sinatra訪問Ruby EventMachine頻道?
是否有人知道是否可以從Sinatra應用程序創建,訂閱併發布到EventMachine渠道(以Thin方式運行),或者甚至可以從某些Rack中間件那裏發佈?
基本上,爲了在Thin中運行時使用EventMachine成爲可能,您需要讓它知道您想異步地處理請求。 Rack協議在設計上是同步的,而Thin期望在處理程序返回時執行請求。有很多方法可以讓Thin知道您想異步處理請求(有關示例,請參閱think_async),並且async_sinatra使其變得非常簡單。
Bryan, 您可以使用em-http-request庫(https://github.com/igrigorik/em-http-request),這將允許您引用在A上運行的特定EventMachine應用程序。同一臺服務器,B.一臺不同的服務器,或C.你想要的任何地方。
require 'eventmachine'
require 'em-http-request'
require 'sinatra/base'
require 'thin'
class ServerClass < EventMachine::Connection
def initialize(*args)
# ruby singleton - store channel data in global hash
($channels ||= [])
end
def post_init
puts "initialized"
$cb.call("initialized");
end
def receive_data(data)
# got information from client connection
end
def channel_send(msg,channel)
$channels[channel].send_data(msg)
end
def channels_send(msg)
$channels.each{|channel| channel.send_data(msg)}
end
def unbind
# puts user left
end
end
EventMachine.run do
$cb = EM.callback {|msg| puts msg #do something creative}
$ems = EventMachine::start_server('0.0.0.0',ServerClass,args)
class App < Sinatra::Base
set :public, File.dirname(__FILE__) + '/public'
get '/' do
erb :index
end
end
App.run!({:port => 3000})
end
上面是一個基本的線框。根據你想要發送數據的方式,你可以使用WebSocket(em-websocket)並在登錄時綁定每個用戶(必須添加一個登錄系統),或者你可以使用它來做任何事情。只要您有對Eventmachine對象(連接,websocket,通道)的全局引用,就可以傳遞應用程序內的消息。
順便說一句 - 添加EventMachine.run do; .... end循環是可選的,因爲Thin會做到這一點。它有助於瞭解它是如何工作的。
好運
嗯...所以我不需要異步儘可能多的服務請求,我只是需要一種方法來利用EventMachine的的通道對象。但是,您的回答使我明白,以Thin方式運行的EventMachine僅適用於Rack應用程序,只需通過引用EM就可以實現。 因此,你已經回答了我的問題。感謝Theo! – Bryan 2011-04-22 19:09:48
我以爲你想在你的應用程序中使用頻道進行通信。例如,在處理您想要發佈到頻道的請求時,等待另一個頻道的回覆,或者您想要彈出一個隊列。這些是異步操作,並且您必須異步處理請求以處理它們。例如,如果你運行'queue.pop {| msg | ...}您的請求在調用回調/塊時已經發送。 – Theo 2011-04-22 19:39:07
是的,我沒有必要解釋我想要完成什麼。本質上,我想提供一個RESTful界面來創建,推送和註冊頻道,以支持在我的應用程序之外通知其他Web服務器。最後,我希望一個客戶端能夠將通知推送到一個通道,並通過在queue.pop塊中定義的單獨HTTP請求通知所有註冊了所述通道的Web服務器。 – Bryan 2011-04-22 19:51:06