How to integrate web sockets with django wsgi

We have a very sophisticated Django application that is currently serviced by apache / mod_wsgi and deployed in multiple instances of AWS EC2 for the AWS ELB Load Balancer. Client applications interact with the server using AJAX. They also periodically polled the server for notifications and updates their status. We want to remove the survey and replace it with "push" using network sockets.

Since arbitrary instances handle web socket requests from clients and hold these web sockets, and also because we want clients that cannot be in the same instance that provides the data source for push, we need a way to route the data to the corresponding instance. and then from this instance to the corresponding client network socket.

We understand that apache / mod_wsgi does not work well with web sockets and plan to replace these components with nginx / gunicorn and use gevent-websocket worker. However, if one of several workflows receives requests from clients to establish a web socket, and if the life cycle of workflows is controlled by the main artilleryman process, it is unclear how other workflows, or actually processes without a gun, can send data to these network sockets.

Specific case: this user: a user who issues an HTTP request directed to one instance of EC2 (host), and the desired behavior is that the data to be sent to another user who has a web socket is opened with a completely different instance. One can easily imagine a system in which a message broker (for example, rabbitmq) running on each instance can be sent a message containing data that must be sent via web sockets to the connected client to this instance. But how can the handler of these messages access the web socket that was received in the gun workflow? The high-level objects of the python web socket created a gevent-websocket and cannot be pickled by an employee (they are instances of methods without etching support), therefore they cannot be easily separated from a workflow to some lengthy external process.

In fact, the root of this question comes down to how can there be web sockets that are triggered by HTTP requests from clients and are processed by WSGI handlers on servers such as guns, access to external processes? It does not seem correct that the worker-shooter, which is designed to handle HTTP requests, will receive long-term threads for hanging on web sockets and support for processing messages from other processes for sending messages to web sockets that were attached through these workers processes.

Can anyone explain how WSGI-based web sockets and HTTP request handlers can interact in the environment that I described?

Thanks.

+8
django wsgi websocket gunicorn gevent
source share
2 answers

I think you made the correct assessment that mod_wsgi + websockets is an unpleasant combination.

You will find that all your wsgi workers running web sockets and trying to increase the size of the working pool (in bulk) will probably strangle the server due to memory usage and context switching.

If you like to stick to the wsgi synchronous working environment (as opposed to the reactive approach implemented by gevent, twisted, tornadoes, etc.), I would suggest exploring uWSGI as an application server. Recent versions can handle some URLs the old way (i.e., Existing django views will still work the same as before) and route other URLs to the async-websocket handler. This may be a relatively smooth migration path for you.

+1
source share

It does not seem correct that the machine gun workers that are designed to handle HTTP requests will generate long threads to hang on web sockets and support message processing from other processes to send messages to attached web sockets through these work processes.

Why not? After all, it is a long connection. A long-lasting thread to take care of such a connection would seem ... completely natural to me.

Often in these random situations, the record is processed separately from reading.

The worker who is currently processing the connection to the web server will wait for the corresponding message to drop from the messaging server, and then transfer it through the website.

You can also use gevent async-friendly Queues to handle passing code inside the code if you want.

0
source share

All Articles