Reputation: 8529
My server has access to an API that receives real-time updates over a TCP socket (using ZeroMQ in broadcast mode).
I'd like to build a webservice that displays these updates to people on a website. To forward these updates, a constant connection with all clients through WebSockets seems like the best solution.
I have a good idea on how to do these things separately, but how do I efficiently combine these two in one Python server application?
My idea currently in pseudo code is something like this:
while True:
acceptNewWebSocketConnections()
update = receiveUpdateZeroMQ()
sendMessageToAllWebSockets(update)
What kind of Python libraries would support this kind of model and how do I implement it while preventing congestion?
Upvotes: 1
Views: 1701
Reputation: 529
As an alternative to what mguijarr said, you can use Tornado with zmq together in an IOLoop.
An IOLoop is something that basically checks if sockets are available to read from, and when they are calls a given callback. It runs on a single thread but since it wastes almost no time on just "waiting", it is often faster!
Using tornado with ZMQ is quite simple, so an architecture like you're describing can be like this:
from zmq.eventloop import zmqstream, ioloop
import tornado.web
from tornado import websocket
class MyBroadcastWebsocket(websocket.WebSocketHandler):
clients = set()
def open(self):
self.clients.add(self)
@classmethod
def broadcast_zmq_message(cls, msg):
for client in cls.clients:
client.write_message('Message:' + str(msg)) # Send the message to all connected clients
def on_close(self):
self.clients.remove(self)
def run():
ioloop.install()
my_stream = zmqstream.ZMQStream(my_zmq_socket) # i.e. a pull socket
my_stream.on_recv(MyBroadcastWebsocket.broadcast_zmq_message) # call this callback whenever there's a message
if __name__ == "__main__":
application = tornado.web.Application([
(r"/websocket", MyBroadcastWebsocket),
])
application.listen(8888)
ioloop.IOLoop.instance()
That's literally it! You can look at more info in zmq's or tornado's docs.
Upvotes: 2
Reputation: 7910
I would recommend to use gevent to have a single event loop for all connections,
since the Python binding of zmq supports gevent (import zmq.green as zmq
) and you
also have a gevent websockets implementation available here: gevent-websocket; gevent is compatible with many web servers thanks to WSGI.
Upvotes: 0