Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to integrate web sockets with a django wsgi

We have a significantly complex Django application currently served by apache/mod_wsgi and deployed on multiple AWS EC2 instances behind a AWS ELB load balancer. Client applications interact with the server using AJAX. They also periodically poll the server to retrieve notifications and updates to their state. We wish to remove the polling and replace it with "push", using web sockets.

Because arbitrary instances handle web socket requests from clients and hold onto those web sockets, and because we wish to push data to clients who may not be on the same instance that provides the source data for the push, we need a way to route data to the appropriate instance and then from that instance to the appropriate client web socket.

We realize that apache/mod_wsgi do not play well with web sockets and plan to replace these components with nginx/gunicorn and use the gevent-websocket worker. However, if one of several worker processes receive requests from clients to establish a web socket, and if the lifetime of worker processes is controlled by the main gunicorn process, it isn't clear how other worker processes, or in fact non-gunicorn processes can send data to these web sockets.

A specific case is this one: A user who issues a HTTP request is directed to one EC2 instance (host) and the desired behavior is that data is to be sent to another user who has a web socket open in a completely different instance. One can easily envision a system where a message broker (e.g. rabbitmq) running on each instance can be sent a message containing the data to be sent via web sockets to the client connected to that instance. But how can the handler of these messages access the web socket, which was received in a worker process of gunicorn? The high-level python web socket objects created gevent-websocket and made available to a worker cannot be pickled (they are instance methods with no support for pickling), so they cannot easily be shared by a worker process to some long-running, external process.

In fact, the root of this question comes down to how can web sockets which are initiated by HTTP requests from clients and handled by WSGI handlers in servers such as gunicorn be accessed by external processes? It doesn't seem right that gunicorn worker processes, which are intended to handle HTTP requests would spawn long-running threads to hang onto web sockets and support handling messages from other processes to send messages to the web sockets that have been attached through those worker processes.

Can anyone explain how web sockets and WSGI-based HTTP request handlers can possibly interplay in the environment I've described?

Thanks.

like image 324
eswenson Avatar asked Feb 28 '13 16:02

eswenson


People also ask

Can I use WebSockets in Django?

Using WebSockets in Django utilizes asynchronous Python and Django channels, making the process straightforward. Using Django channels, you can create an ASGI server, and then create a group where users can send text messages to all the other users in the group in real time.

How do I use sockets in Django?

With WebSockets (via Django Channels) managing the communication between the client and the server, whenever a user is authenticated, an event will be broadcasted to every other connected user. Each user's screen will change automatically, without them having to reload their browsers.

How does Python connect to WebSockets?

WebSocket Client with PythonCreate a new File “client.py” and import the packages as we did in our server code. Now let's create a Python asynchronous function (also called coroutine). async def test(): We will use the connect function from the WebSockets module to build a WebSocket client connection.

Does soap use WebSockets?

The SOAP over WebSocket Protocol Binding Specification defines a binding of SOAP to the WebSocket protocol (as defined in [RFC6455]), including a WSDL transport URI and supported message exchange patterns (MEPs). This specification also defines a WebSocket subprotocol.


1 Answers

I think you've made the correct assesment that mod_wsgi + websockets is a nasty combination.

You would find all of your wsgi workers hogged by the web sockets and an attempt to (massively) increase the size of the worker pool would probably choke the server because of the memory usage and context switching.

If you like to stick with the synchronous wsgi worker architecture (as opposed to the reactive approach implemented by gevent, twisted, tornado etc), I would suggest looking into uWSGI as a application server. Recent versions can handle some URLs in the old way (i.e. your existing django views would still work the same as before), and route other urls to a async websocket handler. This might be a relatively smooth migration path for you.

like image 177
Freek Wiekmeijer Avatar answered Nov 29 '22 12:11

Freek Wiekmeijer