Как отключить клиент redis в websocket eventmachine - PullRequest
2 голосов
/ 31 августа 2011

Я пытаюсь создать сервер веб-сокетов, где каждый клиент устанавливает свои собственные подключения 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

Ответы [ 3 ]

1 голос
/ 05 сентября 2011

Эта версия em-hiredis поддерживает закрытое соединение: https://github.com/whatupdave/em-hiredis

0 голосов
/ 18 июля 2013

Это было добавлено в em-hiredis: https://github.com/mloughran/em-hiredis/pull/6

0 голосов
/ 03 сентября 2011

Вот как я бы (и делал это много раз) так: вместо того, чтобы всегда открывать и закрывать соединения для каждого клиента, вы можете оставить одно соединение открытым на поток / волокно в зависимости от того, на чем основан ваш параллелизм, таким образом, если выиспользуют опрос Thread / Fibers, как только у каждого из них есть свои соединения, они сохранят его и снова используют.

Я до сих пор мало работал с websocket (я ждал стандартной реализации), но яя уверен, что вы можете применить это мышление и к нему.

Вы также можете делать то, что rails / activerecord: keeo пул соединения redis, каждый раз, когда вам нужно использовать соединение, которое вы запрашиваете, используйте его и повторно выпустите его, это может выглядеть так:

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

до выдачи блока соединение берется из доступных и после него соединение помечается как свободное.

...