2016-10-23 3 views
3

J'ai un problème avec les chaînes django. Mon application Django fonctionnait parfaitement avec WSGI pour les requêtes HTTP. J'ai essayé de migrer vers des canaux afin de permettre les demandes de WebSocket, et il se trouve que, après l'installation de canaux et ASGI en cours d'exécution (daphné) et un travailleur, le serveur répond erreur 503 et le navigateur affiche une erreur 504 (temps) pour le http demandes qui fonctionnaient précédemment (page d'administration par exemple). J'ai lu tout le tutoriel que j'ai pu trouver et je ne vois pas ce que le problème peut être. De plus, si je cours avec "runserver", ça fonctionne bien.canaux Django fois sur avec daphné et travailleur

I ont une Nginx en face de l'application (sur un serveur distinct), travaillant comme proxy et loadbalancer. J'utilise Django 1.9.5 avec asgi-redis> = 0.10.0, channels> = 0.17.0 et daphne> = 0.15.0. Les fichiers wsgi.py et asgi.py se trouvent dans le même dossier. Redis travaille.

La commande que j'utilisais précédemment avec WSGI (et qui fonctionne toujours si je passe revenir) est: uwsgi --http :8000 --master --enable-threads --module Cats.wsgi

La commande qui fonctionne à l'aide runserver est: python manage.py runserver 0.0.0.0:8000

Les commandes qui ne pour les demandes qui travaillent avec les 2 autres commandes sont: daphne -b 0.0.0.0 -p 8000 Cats.asgi:channel_layer python manage.py runworker

autres informations: I ajouté « canaux » dans les applications installées (en settings.py)

autres informations pertinentes settings.py

CHANNEL_LAYERS = { 
"default": { 
    "BACKEND": "asgi_redis.RedisChannelLayer", 
    "ROUTING": "Cats.routing.app_routing", 
    "CONFIG": { 
     "hosts": [(os.environ['REDIS_HOST'], 6379)], 
    }, 
}, 

}

Chats/routing.py

from channels.routing import route, include 
from main.routing import routing as main_routing 

app_routing = [ 
    include(main_routing, path=r"^/ws/main"), 
] 

principal/routing.py

from channels.routing import route, include 

http_routing = [ 
] 

stream_routing = [ 
    route('websocket.receive', 'main.consumers.ws_echo'), #just for test once it will work 
] 

routing = [ 
    include(stream_routing), 
    include(http_routing), 
] 
principaux/consommateurs

. py

def ws_echo(message): 
message.reply_channel.send({ 
    'text': message.content['text'], 
}) 

#this consumer is just for test once it will work 

Une idée de ce qui pourrait se tromper? Toute aide très appréciée! Ty

EDIT: J'ai essayé une chose nouvelle:

python manage.py runserver 0.0.0.0:8000 --noworker 
python manage.py runworker 

Et cela ne fonctionne pas, alors que python manage.py runserver 0.0.0.0:8000 travaillait ...

Toute idée qui pourrait aider?

+0

J'ai modifié mon message avec une nouvelle tentative de séparer le worker du "runserver". Il échoue aussi – Yom86

+0

Avez-vous vérifié redis si daphne met effectivement la demande dans la file d'attente? – r00m

+0

Avez-vous résolu ceci en attendant? Nous avons des canaux en cours de production mais quand j'essaie de déployer le même projet sur notre serveur de développement, j'ai ce problème. Le travailleur reçoit la demande mais elle s'arrête là. daphne (runserver) renvoie un 503 et dans le navigateur je reçois 504. – ThaJay

Répondre

0

canaux utiliseront les vues par défaut pour les demandes de l'ONU-mis en déroute. en supposant que vous utilisez les javascripts droite, je vous suggère d'utiliser uniquement votre défaut Chats/fichier routing.py comme suit:

from channels.routing import route 
from main.consumers import * 


app_routing = [ 
    route('websocket.connect', ws_echo, path="/ws/main") 
] 

ou avec marche arrière pour aider avec votre chemin

from django.urls import reverse 

from channels.routing import route 
from main.consumers import * 


app_routing = [ 
    route('websocket.connect', ws_echo, path=reverse('main view name')) 
] 

Je pense aussi votre le consommateur devrait être changé. Lorsque le navigateur se connecte à l'aide de Websockets, le serveur doit d'abord gérer l'ajout du canal de réponse du message.quelque chose comme:

def ws_echo(message): 
    Group("notifications").add(message.reply_channel) 
    Group("notifications").send({ 
     "text": json.dumps({'testkey':'testvalue'}) 
    }) 

devrait probablement changé la fonction d'envoi devrait probablement être appelé sur les différents événements et le groupe « notifications » d'avoir un canal dédié à l'utilisateur. quelque chose comme

from channels.auth import channel_session_user_from_http 

@channel_session_user_from_http 
def ws_echo(message): 
    Group("notify-private-%s" % message.user.id).add(message.reply_channel) 
    Group("notify-private-%s" % message.user.id).send({ 
     "text": json.dumps({'testkey':'testvalue'}) 
    }) 
+0

dédié à l'utilisateur est beaucoup plus simple: 'message.reply_channel.send ({'text': json.dumps ({'test': 'tetest'})})' sauf si vous vous attendez à ce que l'utilisateur dispose de plusieurs connexions dont tous ont besoin le message. – ThaJay

0

Si vous utilisez Heroku ou Dokku assurez-vous que vous avez correctement défini l ' « échelle » pour y inclure le processus de travail. Par défaut, ils ne feront que lancer l'instance web et non le worker!

Pour heroku

heroku ps:scale web=1:free worker=1:free 

Pour Dokku créer un fichier nommé DOKKU_SCALE et ajouter:

web=1 
worker=1 

Voir: