Ruby 如何在websocket eventmachine中断开redis客户端

Ruby 如何在websocket eventmachine中断开redis客户端,ruby,websocket,redis,eventmachine,Ruby,Websocket,Redis,Eventmachine,我正在尝试构建一个websocket服务器,其中每个客户端都建立自己的用于发布和订阅的redis连接 当redis服务器运行时,当客户端连接到websocket服务器时,我可以看到两个新连接正在建立,我也可以将数据发布到客户端,但是当客户端断开与websocket服务器的连接时,我还想断开与redis的连接。我该怎么做 也许我做错了,但这是我的代码 #require 'redis' require 'em-websocket' require 'em-hiredis' require 'json

我正在尝试构建一个websocket服务器,其中每个客户端都建立自己的用于发布和订阅的redis连接

当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
#需要“redis”
需要“他们是websocket”
需要雇佣他们
需要“json”
CLIENTS=Hash.new
类PubSub
def初始化(客户端)
@socket=client.ws
#这些客户端只能用于发布子命令
@publisher=EM::Hiredis.connect#稍后我要断开此连接
@subscriber=EM::Hiredis.connect#稍后我想断开此连接
client.connections(8081)do | ws|
ws.onopen do
#我在上面举例说明
使“客户端”连接。创建套接字'
@client=client.new(ws)
客户端[ws]=@client
结束
ws.onclose do
#在连接关闭后,我将其从正在运行的套接字列表中删除
使“客户端”断开连接。闭合插座'
@client.connections.each do | con|
#做点什么来断开与redis的连接
结束
CLIENTS.delete-ws
结束
ws.onmessage{| msg|
放入“收到的消息:#{msg}”
result=JSON.parse(msg)
如果result.has_key?'channel'
ps=PubSub.new(@client)
ps.subscribe(结果['channel'])
elsif result.has_key?'publish'
ps=PubSub.new(ws)
ps.publish(结果['publish']['channel'],结果['publish']['msg']);
结束
}
结束
结束
以下是我如何(并且多次)做到这一点的: 不必总是为每个客户机打开和关闭连接,您可以根据并发性的基础为每个线程/光纤保持1个连接打开,这样,如果您使用线程/光纤轮询,一旦每个线程/光纤都有了连接,它们就会保留连接并重新使用

直到现在,我才开始使用websocket(我一直在等待标准实现),但我相信您也可以将这种想法应用到websocket中

您还可以执行rails/activerecord所做的操作:保留一个redis连接池,每次需要使用一个连接时,您都会请求一个连接,使用它并重新启用它,它可能如下所示:

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

在生成块之前,将从可用的连接中获取连接,然后将连接标记为免费。

此版本的em hiredis支持紧密连接:

这已添加到em hiredis:

感谢您的回答,但我不确定它是否能在事件驱动的环境中工作。感谢Dave在这里提供了解决方案:感谢分享。无论是谁到达这里,但没有发现这样的obivous,这个分叉版本添加了方法close\u connection,因此基本上:sub=EM::Hiredis.connect(“redis://localhost:6379/0"); sub.close_连接