我正在尝试构建一个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
答案 0 :(得分:1)
此版本的em-hiredis支持密切连接:https://github.com/whatupdave/em-hiredis
答案 1 :(得分:0)
以下是我(以及多次)这样做的方式: 而不是总是打开和关闭每个客户端的连接,你可以保持每个线程/光纤1个连接打开依赖于你的并发性,这是如果你使用线程/光纤轮询一旦每个都有它的连接他们会保留它并重复使用它们。
到目前为止我没有使用websocket(我正在等待标准实现),但我相信你也可以将这种想法应用到它。
你也可以做什么rails / activerecord:keeo redis连接池,每次你需要使用你请求的连接,使用它并重新发布它,它可能看起来像这样:
def handle_request(request)
@redis_pool.get_connection do |c|
# [...]
end
end
在产生块之前,从可用的连接中获取连接,然后连接被标记为空闲。
答案 2 :(得分:0)
这已添加到em-hiredis:https://github.com/mloughran/em-hiredis/pull/6