Django channels, running uwsgi and awsgi

1,575 views
Skip to first unread message

Dev App

unread,
Jan 18, 2017, 7:13:15 AM1/18/17
to Django users

I hope there 's a documentation how to do "running-asgi-alongside-wsgi" https://channels.readthedocs.io/en/stable/deploying.html#running-asgi-alongside-wsgi
(I tried google, but none found for how to do it)

I'm just afraid to hand over every request to asgi which I don't know much about.

I have another question.

I'd like to send notification to websocket client when some signal (post-save, etc) occurs.  

For instance, if user-a starts following user-b (post-save signal occurs), (and this happens over wsgi, normal django),
I'd like to send notification to user-b through websocket.

Is the above usage possible with wsgi/asgi dual setup?


I didn't fully understand interface-server/channel-backend/workers concept. 
A single image could help people like me.

I wonder if the following is correct?

nginx --- wsgi --------------  django
                                        /
nginx --- asgi --- redis ---/

asgi is interface-server
redis is channel-backend
django is workers


Andrew Godwin

unread,
Jan 18, 2017, 1:40:00 PM1/18/17
to django...@googlegroups.com
On Wed, Jan 18, 2017 at 12:33 AM, Dev App <ziban...@gmail.com> wrote:

I hope there 's a documentation how to do "running-asgi-alongside-wsgi" https://channels.readthedocs.io/en/stable/deploying.html#running-asgi-alongside-wsgi
(I tried google, but none found for how to do it)

I'm just afraid to hand over every request to asgi which I don't know much about.

There's not individual documentation for every situation because people's choice of webserver and their OS versions and environments differ. If you tell me what you're using I can try and provide some hints or links to examples.
 

I have another question.

I'd like to send notification to websocket client when some signal (post-save, etc) occurs.  

For instance, if user-a starts following user-b (post-save signal occurs), (and this happens over wsgi, normal django),
I'd like to send notification to user-b through websocket.

Is the above usage possible with wsgi/asgi dual setup?


Yes, the dual setup still lets you send messages to channels from WSGI workers, just not act on them.
 

I didn't fully understand interface-server/channel-backend/workers concept. 
A single image could help people like me.

I wonder if the following is correct?

nginx --- wsgi --------------  django
                                        /
nginx --- asgi --- redis ---/

asgi is interface-server
redis is channel-backend
django is workers


That's not quite right, but close - the ASGI and WSGI workers live in different places, because the ASGI ones are a separate process using runworker and the WSGI ones run inside your WSGI server, and both can talk to the channel layer (redis in your example).

Any Python code can send to a channel - WSGI workers, management commands, etc. You can just only act on messages on channels inside workers or async code you write yourself.

Andrew

Dev App

unread,
Jan 19, 2017, 4:13:30 AM1/19/17
to Django users
Thank you for the answers.

It helps me immensely.


So in theory, if client doesn't need to send data to server (something which runworker needs to work on), 

I only need

nginx --- wsgi -------------- django
                                           /
nginx --- asgi ---- redis  ---/

where Django to redis is one way communication from django to redis. (but not redis to django)
because django can talk to channel backends, but wsgi django can't understand asgi messages from channel backends


------------------------

In a usual dual setup,

nginx --- wsgi -------------- django
                                           /
nginx --- asgi ---- -------redis ----- runworker

where django -> redis is still one way communcation whereas all other communications (------ lines) are bidirectional, 



2017년 1월 19일 목요일 오전 3시 40분 0초 UTC+9, Andrew Godwin 님의 말:

Dev App

unread,
Jan 19, 2017, 7:18:30 AM1/19/17
to Django users
 There's not individual documentation for every situation because people's choice of webserver and their OS versions and environments differ. If you tell me what you're using I can try and provide some hints or links to examples.
 
I thought it would be easy now, since I understand the concept better, but it still wasn't easy.


From django channels documentation

the ideal thing is to be able to look for the Upgrade: WebSocket header and distinguish connections by this


So wha I need is in pseudo code,

if Upgrade: WebSocket is present,
  hand over requests to asgi (darphene)
else
  hand over requests to wsgi (uwsgi)

I failed to find an example. 
So yes, please let me know how to do the dual setup with nginx in the front.

I found https://www.nginx.com/blog/websocket-nginx/ but not readily applicable because the example there seems to 
proxy every requests. 

2017년 1월 19일 목요일 오전 3시 40분 0초 UTC+9, Andrew Godwin 님의 말:

Avraham Serour

unread,
Jan 19, 2017, 8:23:59 AM1/19/17
to django-users
I think you can do conditionals on your server block and proxy pass to the correct upstream depending on your logic


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/3e352bf8-0ced-4ac3-94e3-fa28ced84d66%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Andrew Godwin

unread,
Jan 19, 2017, 1:27:37 PM1/19/17
to django...@googlegroups.com
Nginx can't (to my knowledge) easily switch on the Upgrade header without extra modules as you need to take the header, lowercase it, and check it equals "websocket", and Nginx if statements are weird and limited in some important ways.

Instead, I recommend you do prefix-based proxying, like this:

server {
    location /ws/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    ... normal config here ...
}

The key thing is that you put all the WebSocket configuration you need inside a non-/ location block, and then just use that prefix for all of your sockets.

Andrew
Reply all
Reply to author
Forward
0 new messages