Django Channels Worker not responding to websocket.connect

1.6k views Asked by At

I'm having a problem with django channels. Daphne accepts WebSocket CONNECT requests properly, but then the workers doesn't respond to the request with the supplied method in consumers.py. The thing is this happens only most of the time. Sometimes it responds with the method in the consumers.py but most of the time the worker doesn't respond at all. I have a duplicate code working fine in vagrant (trusty64) environment, but the code behaves like that in an actual trusty64 machine. It should be noted that the trusty64 machine that hosts the app also has other application running (about 4 apps running at the same time).

I have a routing.py set up like this

from channels import route
from app.consumers import connect_tracking, disconnect_tracking

channel_routing = [

    route("websocket.connect", connect_tracking, path=r'^/websocket/tms/tracking/stream/$'),
    route("websocket.disconnect", disconnect_tracking, path=r'^/websocket/tms/tracking/stream/$'),
]

with the corresponding consumers.py that looks like this

import json
from channels import Group
from channels.sessions import channel_session
from channels.auth import http_session_user, channel_session_user, channel_session_user_from_http

from django.conf import settings

@channel_session_user_from_http
def connect_tracking(message):
    group_name = settings.TRACKING_GROUP_NAME
    print "%s is joining %s" % (message.user, group_name)
    Group(group_name).add(message.reply_channel)

@channel_session_user
def disconnect_tracking(message):
    group_name = settings.TRACKING_GROUP_NAME
    print "%s is joining %s" % (message.user, group_name)
    Group(group_name).discard(message.reply_channel)

and some channels related lines in settings.py like this

redis_host = os.environ.get('REDIS_HOST', 'localhost')
CHANNEL_LAYERS = {
    "default": {
        # This example app uses the Redis channel layer implementation asgi_redis
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "hosts": [(redis_host, 6379)],
        },
        "ROUTING": "tms_app.routing.channel_routing",
    },
}

referencing another question, I've tried running daphne and worker like this

daphne tms_app.asgi:channel_layer --port 9015 --bind 0.0.0.0 -v2
python manage.py runworker -v3

I've captured daphne's and the worker's log, it looks like this

Daphne log :

2016-12-30 17:00:18,870 INFO     Starting server at 0.0.0.0:9015, channel layer tms_app.asgi:channel_layer
2016-12-30 17:00:26,788 DEBUG    WebSocket open for websocket.send!APpWONQKKDXR
192.168.31.197:48933 - - [30/Dec/2016:17:00:26] "WSCONNECT /websocket/tms/tracking/stream/" - -
2016-12-30 17:00:26,790 DEBUG    Upgraded connection http.response!sqlMPEEtolDP to WebSocket websocket.send!APpWONQKKDXR

corresponding worker log :

2016-12-30 17:00:22,265 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2016-12-30 17:00:22,265 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive

As you can see when there's a WSCONNECT event, the worker doesn't respond to it.

There's another question that's close to this issue that was solved by downgrading Twisted to 16.2 but it doesn't work for me.

UPDATE January 3, 2017

I cannot replicate the issue on a local vagrant machine despite using the same code and same settings for nginx, supervisor, gunicorn and daphne. I tried changed the channel layers settings so it uses IPC instead of redis and it works. Here's the settings :

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_ipc.IPCChannelLayer",
        "ROUTING": "tms_app.routing.channel_routing",
        "CONFIG": {
            "prefix": "tms",
        },
    },
}

However this does not solve the current problem as I intend to use Redis channel layers because it's more easier to scale compared to IPC. Does this mean there's something wrong with my redis server?

1

There are 1 answers

1
Black Magic On

I think the reason your Connection doesnt complete is because you are not sending the accept message like this: message.reply_channel.send({'accept': True})

This is what works for my version of Channels, but you should make check the docs for your version to make sure what works for you