2011-08-31 38 views
2

我试图建立一个websocket服务器,其中每个客户端建立自己的redis连接用于发布和订阅。如何断开websocket中的redis客户端eventmachine

当redis服务器运行时,我可以看到当客户端连接到websocket服务器时我建立了两个新连接,我也可以将数据发布到客户端,但是当客户端断开与websocket服务器的连接时,我也想要与Redis断开连接。我怎样才能做到这一点?

也许我做错了,但这是我的代码。

#require 'redis' 
require 'em-websocket' 
require 'em-hiredis' 
require 'json' 

CLIENTS = Hash.new 

class PubSub 
    def initialize(client) 
    @socket = client.ws 
    # These clients can only be used for pub sub commands 
    @publisher = EM::Hiredis.connect #Later I will like to disconnect this 
    @subscriber = EM::Hiredis.connect #Later I will like to disconnect this 
    client.connections << @publisher << @subscriber 
    end 
    def subscribe(channel) 
    @channel = channel 
    @subscriber.subscribe(channel) 
    @subscriber.on(:message) { |chan, message| 
     @socket.send message 
    } 
    end 
    def publish(channel,msg) 
    @publisher.publish(channel, msg).errback { |e| 
     puts [:publisherror, e] 
    } 
    end 
    def unsubscribe() 
    @subscriber.unsubscribe(@channel) 
    end 
end 

class Client 
    attr_accessor :connections, :ws 
    def initialize(ws) 
    @connections = [] 
    @ws = ws 
    end 
end 

EventMachine.run do 
    # Creates a websocket listener 
    EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8081) do |ws| 

    ws.onopen do 
     # I instantiated above 
     puts 'CLient connected. Creating socket'  
     @client = Client.new(ws) 
     CLIENTS[ws] = @client 
    end 

    ws.onclose do 
     # Upon the close of the connection I remove it from my list of running sockets 
     puts 'Client disconnected. Closing socket' 

     @client.connections.each do |con| 
     #do something to disconnect from redis 
     end 

     CLIENTS.delete ws 
    end 

    ws.onmessage { |msg| 
     puts "Received message: #{msg}" 
     result = JSON.parse(msg) 
     if result.has_key? 'channel' 
     ps = PubSub.new(@client) 
     ps.subscribe(result['channel']) 
     elsif result.has_key? 'publish' 
     ps = PubSub.new(ws) 
     ps.publish(result['publish']['channel'],result['publish']['msg']); 
     end 
    } 
    end 
end 

回答

1

这个版本EM-hiredis的支持密切相关:https://github.com/whatupdave/em-hiredis

+0

感谢您的分享。 无论谁来到这里都没有发现如此明显,这个分叉版本增加了close_connection方法,所以基本上: sub = EM :: Hiredis.connect(“redis:// localhost:6379/0”); sub.close_connection – Sikora

0

这里是我会怎样(和做了很多次)这样的: 而不是总是为每个客户端打开和关闭连接,你可以保持1个连接每线程/光纤dependeing开上你是在基础的并发这样,如果你使用一次线程/光纤轮询一旦他们每个人都有它的连接,他们会保留它并重用它们。

到现在为止我还没有和websocket一起工作太多(我正在等待一个标准实现),但我相信你也可以将它应用到它。

您还可以做什么导轨/ ActiveRecord的:keeo Redis的连接池,每次你需要使用你请求一个连接,使用它,并realease它的时候,它看起来是这样的:

def handle_request(request) 
    @redis_pool.get_connection do |c| 
    # [...] 
    end 
end 

在产生块之前,从可用块中获取连接,并在连接被标记为空闲之后进行连接。

+1

谢谢您的回答,但我不知道它会在事件驱动的环境中工作。感谢Dave分叉并在此修复:https://github.com/whatupdave/em-hiredis – user918712