2017-02-28 2 views
2

Mit faye-websocket und den Code sieht sehr eventmachine ähnlich Client-Beispiel-websocket faye:Verbindung zu mehreren WebSockets mit Ruby?

require 'faye/websocket' 
require 'eventmachine' 

def setup_socket(url) 
    EM.run { 
     ws = Faye::WebSocket::Client.new(url) 

     ws.on :open do ... end 

     ws.on :message do ... end 

     ws.on :close do ... end 
    } 
end 

ich mehrere Verbindungen offen parallel haben möchten. Ich kann nicht einfach setup_socket mehrmals anrufen, da die Ausführung die Klausel EM.run nicht verlassen wird. Ich habe versucht, setup_socket mehrere Male in separaten Threads ausgeführt wird:

urls.each do |url| 
    Thread.new { setup_socket(url) } 
end 

Aber es scheint nicht anyhting wie die puts Aussagen zu tun, nicht den Ausgang erreichen.

Ich bin nicht auf die Verwendung von Faye-Websocket beschränkt, aber es schien, dass die meisten Leute diese Bibliothek benutzen. Wenn möglich, möchte ich Multithreading vermeiden. Ich möchte auch nicht die Möglichkeit verlieren, im Laufe der Zeit Änderungen vorzunehmen (z. B. einen neuen Websocket hinzuzufügen). Daher ist es nicht erwünscht, die Iteration von URLs innerhalb der EM.run-Klausel zu verschieben, stattdessen wäre der Start mehrerer EMs vorteilhafter. Ich fand eine example for starting multiple servers via EM in einer sehr sauberen Art und Weise. Ich suche nach etwas ähnlichem.

Wie kann ich mich gleichzeitig mit mehreren WebSockets verbinden?

+0

Warum nicht 'def setup_sockets (urls); EM.run {urls.each {...}}; Ende. Funktioniert das nicht? – Casper

+0

Das könnte funktionieren. Ich habe nicht darüber nachgedacht, da sich URLs im Laufe der Zeit ändern oder neue hinzugefügt werden. Mit diesem Ansatz müsste ich den Prozess neu starten und kann keine Änderungen im laufenden Betrieb vornehmen. – thisismydesign

Antwort

2

Hier ist eine Möglichkeit, es zu tun.

Zuerst müssen Sie akzeptieren, dass der EM-Thread ausgeführt werden muss. Ohne diesen Thread können Sie keine aktuellen Verbindungen bearbeiten. Du kommst einfach nicht herum.

Um neue URLs zum EM-Thread hinzuzufügen, benötigen Sie eine Möglichkeit, vom Hauptthread zum EM-Thread zu kommunizieren, damit Sie ihm mitteilen können, dass er eine neue Verbindung starten soll. Dies kann mit EventMachine::Channel erfolgen.

Also, was wir jetzt so etwas wie dieses bauen kann:

@channel = EventMachine::Channel.new 

Thread.new { 
    EventMachine.run { 
    @channel.subscribe { |url| 
     ws = Faye::...new(url) 
     ... 
    } 
    } 
} 

dann im Hauptthread, jederzeit eine neue URL zu der Ereignisschleife hinzufügen möchten, verwenden Sie nur das:

def setup_socket(url) 
    @channel.push(url) 
end 
0

Hier ist eine andere Art und Weise, es zu tun ... nativen websocket Unterstützung der Verwendung Jod (oder die Plezi framework) statt em-websocket ...

... ich bin voreingenommen (ich bin der Autor), bu t Ich denke, sie machen es viel einfacher. Außerdem bietet Plezi eine automatische Skalierung mit Redis, so dass es einfach zu wachsen ist.

Hier ist ein Beispiel mit Plezi, wo jeder Controller wie ein Kanal wirkt, mit seiner eigenen URL und Websocket Callback (obwohl ich glaube, dass Plezis Auto-Dispatch einfacher ist als der untere on_message Callback). Dieser Code kann in einer config.ru Datei abgelegt werden:

require 'plezi' 

# Once controller/channel for all members of the "Red" group 
class RedGroup 
    def index # HTTP index for the /red URL 
    "return the RedGroup client using `:render`".freeze 
    end 
    # handle websocket messages 
    def on_message data 
    # in this example, we'll send the data to all the members of the other group. 
    BlueGroup.broadcast :handle_message, data 
    end 
    # This is the method activated by the "broadcast" message 
    def handle_message data 
    write data # write the data to the client. 
    end 
end 
# the blue group controller/channel 
class BlueGroup 
    def index # HTTP index for the /blue URL 
    "return the BlueGroup client using `:render`".freeze 
    end 
    # handle websocket messages 
    def on_message data 
    # in this example, we'll send the data to all the members of the other group. 
    RedGroup.broadcast :handle_message, data 
    end 
    # This is the method activated by the "broadcast" message 
    def handle_message data 
    write data 
    end 
end 
# the routes 
Plezi.route '/red', RedGroup 
Plezi.route '/blue', BlueGroup 
# Set the Rack application 
run Plezi.app 

P. S.

Ich schrieb diese Antwort auch, weil em-websocket in einigen Fällen möglicherweise fehlschlagen oder Ressourcen schwächen kann. Ich bin mir nicht sicher über die Details, aber es wurde sowohl auf der websocket-shootout benchmark als auch der AnyCable Websocket Benchmarks notiert.

Verwandte Themen