简体   繁体   中英

Channels django

I'm trying to get django channels to work with daphne, but I can't connect rooms, the app runs good,but whenever I run the app, and open a "room" websocket it automatically disconnects, it is worth mentioning that my site is running with HTTP and any help will be apreciated

2022-08-19T13:20:57.879758+00:00 app[worker.1]: conn = await self.create_conn(loop)
2022-08-19T13:20:57.879769+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 79, in create_conn
2022-08-19T13:20:57.879862+00:00 app[worker.1]: return await aioredis.create_redis_pool(**kwargs)
2022-08-19T13:20:57.879863+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/commands/__init__.py", line 188, in create_redis_pool
2022-08-19T13:20:57.879967+00:00 app[worker.1]: pool = await create_pool(address, db=db,
2022-08-19T13:20:57.879978+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/pool.py", line 58, in create_pool
2022-08-19T13:20:57.880062+00:00 app[worker.1]: await pool._fill_free(override_min=False)
2022-08-19T13:20:57.880073+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/pool.py", line 383, in _fill_free
2022-08-19T13:20:57.880224+00:00 app[worker.1]: conn = await self._create_new_connection(self._address)
2022-08-19T13:20:57.880233+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/connection.py", line 133, in create_connection
2022-08-19T13:20:57.880336+00:00 app[worker.1]: await conn.auth(password)
2022-08-19T13:20:57.880345+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/util.py", line 52, in wait_ok
2022-08-19T13:20:57.880426+00:00 app[worker.1]: res = await fut
2022-08-19T13:20:57.880437+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/connection.py", line 186, in _read_data
2022-08-19T13:20:57.880564+00:00 app[worker.1]: obj = await self._reader.readobj()
2022-08-19T13:20:57.880576+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/stream.py", line 102, in readobj
2022-08-19T13:20:57.880669+00:00 app[worker.1]: await self._wait_for_data('readobj')
2022-08-19T13:20:57.880680+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/asyncio/streams.py", line 502, in _wait_for_data
2022-08-19T13:20:57.880853+00:00 app[worker.1]: await self._waiter
2022-08-19T13:20:57.880863+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/asyncio/selector_events.py", line 854, in _read_ready__data_received
2022-08-19T13:20:57.881081+00:00 app[worker.1]: data = self._sock.recv(self.max_size)
2022-08-19T13:20:57.881108+00:00 app[worker.1]: ConnectionResetError: [Errno 104] Connection reset by peer
2022-08-19T13:20:58.216868+00:00 heroku[worker.1]: Process exited with status 1
2022-08-19T13:20:58.288781+00:00 heroku[worker.1]: State changed from up to crashed
2022-08-19T13:20:58.293098+00:00 heroku[worker.1]: State changed from crashed to starting
2022-08-19T13:21:01.803835+00:00 heroku[worker.1]: Starting process with command `python manage.py runworker channel_layer -v2`
2022-08-19T13:21:02.114989+00:00 app[web.1]: /app/templates/allauth
2022-08-19T13:21:02.115157+00:00 app[web.1]: 2022-08-19 13:21:02,115 INFO     Adding $DATABASE_URL to default DATABASE Django setting.
2022-08-19T13:21:02.115388+00:00 app[web.1]: 2022-08-19 13:21:02,115 INFO     Adding $DATABASE_URL to TEST default DATABASE Django setting.
2022-08-19T13:21:02.115464+00:00 app[web.1]: 2022-08-19 13:21:02,115 INFO     Applying Heroku Staticfiles configuration to Django settings.
2022-08-19T13:21:02.115620+00:00 app[web.1]: 2022-08-19 13:21:02,115 INFO     Applying Heroku ALLOWED_HOSTS configuration to Django settings.
2022-08-19T13:21:02.115673+00:00 app[web.1]: 2022-08-19 13:21:02,115 INFO     Applying Heroku logging configuration to Django settings.
2022-08-19T13:21:02.425949+00:00 heroku[worker.1]: State changed from starting to up
2022-08-19T13:21:02.756499+00:00 app[web.1]: 2022-08-19 09:21:02,756 INFO     Starting server at tcp:port=5104:interface=0.0.0.0
2022-08-19T13:21:02.757304+00:00 app[web.1]: 2022-08-19 09:21:02,757 INFO     HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2022-08-19T13:21:02.757571+00:00 app[web.1]: 2022-08-19 09:21:02,757 INFO     Configuring endpoint tcp:port=5104:interface=0.0.0.0
2022-08-19T13:21:02.758238+00:00 app[web.1]: 2022-08-19 09:21:02,758 INFO     HTTPFactory starting on 5104
2022-08-19T13:21:02.758408+00:00 app[web.1]: 2022-08-19 09:21:02,758 INFO     Starting factory <daphne.http_protocol.HTTPFactory object at 0x7f77a0c83a60>
2022-08-19T13:21:02.758717+00:00 app[web.1]: 2022-08-19 09:21:02,758 INFO     Listening on TCP address 0.0.0.0:5104
2022-08-19T13:21:02.973963+00:00 heroku[web.1]: State changed from starting to up
2022-08-19T13:21:03.384499+00:00 app[worker.1]: /app/templates/allauth
2022-08-19T13:21:04.746745+00:00 app[worker.1]: Running worker for channels ['channel_layer']
2022-08-19T13:21:04.764414+00:00 app[worker.1]: Traceback (most recent call last):
2022-08-19T13:21:04.764421+00:00 app[worker.1]: File "/app/manage.py", line 22, in <module>
2022-08-19T13:21:04.764513+00:00 app[worker.1]: main()
2022-08-19T13:21:04.764513+00:00 app[worker.1]: File "/app/manage.py", line 18, in main
2022-08-19T13:21:04.764568+00:00 app[worker.1]: execute_from_command_line(sys.argv)
2022-08-19T13:21:04.764579+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
2022-08-19T13:21:04.764694+00:00 app[worker.1]: utility.execute()
2022-08-19T13:21:04.764704+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
2022-08-19T13:21:04.764832+00:00 app[worker.1]: self.fetch_command(subcommand).run_from_argv(self.argv)
2022-08-19T13:21:04.764834+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
2022-08-19T13:21:04.764947+00:00 app[worker.1]: self.execute(*args, **cmd_options)
2022-08-19T13:21:04.764949+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
2022-08-19T13:21:04.765045+00:00 app[worker.1]: output = self.handle(*args, **options)
2022-08-19T13:21:04.765046+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels/management/commands/runworker.py", line 46, in handle
2022-08-19T13:21:04.765109+00:00 app[worker.1]: worker.run()
2022-08-19T13:21:04.765110+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/asgiref/server.py", line 62, in run
2022-08-19T13:21:04.765175+00:00 app[worker.1]: event_loop.run_until_complete(self.handle())
2022-08-19T13:21:04.765184+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
2022-08-19T13:21:04.765320+00:00 app[worker.1]: return future.result()
2022-08-19T13:21:04.765323+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels/worker.py", line 30, in handle
2022-08-19T13:21:04.765378+00:00 app[worker.1]: [listener.result() for listener in listeners]
2022-08-19T13:21:04.765380+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels/worker.py", line 30, in <listcomp>
2022-08-19T13:21:04.765469+00:00 app[worker.1]: [listener.result() for listener in listeners]
2022-08-19T13:21:04.765469+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels/worker.py", line 37, in listener
2022-08-19T13:21:04.765487+00:00 app[worker.1]: message = await self.channel_layer.receive(channel)
2022-08-19T13:21:04.765490+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 520, in receive
2022-08-19T13:21:04.765609+00:00 app[worker.1]: return (await self.receive_single(channel))[1]
2022-08-19T13:21:04.765628+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 542, in receive_single
2022-08-19T13:21:04.765726+00:00 app[worker.1]: content = await self._brpop_with_clean(
2022-08-19T13:21:04.765734+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 375, in _brpop_with_clean
2022-08-19T13:21:04.765828+00:00 app[worker.1]: async with self.connection(index) as connection:
2022-08-19T13:21:04.765828+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 862, in __aenter__
2022-08-19T13:21:04.765975+00:00 app[worker.1]: self.conn = await self.pool.pop()
2022-08-19T13:21:04.765978+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 93, in pop
2022-08-19T13:21:04.766043+00:00 app[worker.1]: conn = await self.create_conn(loop)
2022-08-19T13:21:04.766043+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/channels_redis/core.py", line 79, in create_conn
2022-08-19T13:21:04.766101+00:00 app[worker.1]: return await aioredis.create_redis_pool(**kwargs)
2022-08-19T13:21:04.766103+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/commands/__init__.py", line 188, in create_redis_pool
2022-08-19T13:21:04.766176+00:00 app[worker.1]: pool = await create_pool(address, db=db,
2022-08-19T13:21:04.766184+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/pool.py", line 58, in create_pool
2022-08-19T13:21:04.766241+00:00 app[worker.1]: await pool._fill_free(override_min=False)
2022-08-19T13:21:04.766243+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/pool.py", line 383, in _fill_free
2022-08-19T13:21:04.766334+00:00 app[worker.1]: conn = await self._create_new_connection(self._address)
2022-08-19T13:21:04.766342+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/connection.py", line 133, in create_connection
2022-08-19T13:21:04.766428+00:00 app[worker.1]: await conn.auth(password)
2022-08-19T13:21:04.766430+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/util.py", line 52, in wait_ok
2022-08-19T13:21:04.766495+00:00 app[worker.1]: res = await fut
2022-08-19T13:21:04.766497+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/connection.py", line 186, in _read_data
2022-08-19T13:21:04.766564+00:00 app[worker.1]: obj = await self._reader.readobj()
2022-08-19T13:21:04.766573+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/site-packages/aioredis/stream.py", line 102, in readobj
2022-08-19T13:21:04.766631+00:00 app[worker.1]: await self._wait_for_data('readobj')
2022-08-19T13:21:04.766640+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/asyncio/streams.py", line 502, in _wait_for_data
2022-08-19T13:21:04.766749+00:00 app[worker.1]: await self._waiter
2022-08-19T13:21:04.766758+00:00 app[worker.1]: File "/app/.heroku/python/lib/python3.10/asyncio/selector_events.py", line 854, in _read_ready__data_received
2022-08-19T13:21:04.766911+00:00 app[worker.1]: data = self._sock.recv(self.max_size)
2022-08-19T13:21:04.766935+00:00 app[worker.1]: ConnectionResetError: [Errno 104] Connection reset by peer
2022-08-19T13:21:05.128856+00:00 heroku[worker.1]: Process exited with status 1
2022-08-19T13:21:05.218917+00:00 heroku[worker.1]: State changed from up to crashed

I have

Django==4.0.6

daphne==3.0.2

channels==3.0.5

My configurations

ASGI.PY

import os

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
from django.urls import path

import django

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myProject.settings")
# Initialize Django ASGI application early to ensure the AppRegistry
# is populated before importing code that may import ORM models.
django.setup()
django_asgi_app = get_asgi_application()

from chat import consumers


application = ProtocolTypeRouter({
    # Django's ASGI application to handle traditional HTTP requests
    "http": django_asgi_app,

    # WebSocket chat handler
    "websocket": AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter([
                    path("ws/<str:room_name>/", consumers.ChatConsumer.as_asgi()),
            ])
        )
    ),
})

PROCFILE (daphne working)

web: daphne myProject.asgi:application --port $PORT --bind 0.0.0.0 -v2
web2: gunicorn myProject.wsgi --log-file -
worker: python manage.py runworker channel_layer -v2

SETTINGS

....
ASGI_APPLICATION = 'myProject.asgi.application'
# Channels
CHANNEL_LAYERS = {
    "default": {
         'BACKEND': 'channels_redis.core.RedisChannelLayer',
        "CONFIG": {
            "hosts": ["redis://:XXXXXXXXXXXeca8e639d8b1ca9617d708224c89641133e6191292a@XXXXXXXXX-25-163.compute-1.amazonaws.com:27320"]
        },

    },
}
....

CONSUMERS.PY

import json 


from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async

from django.contrib.auth.models import User

from .models import Message, Room

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name'] # url route {'args': (), 'kwargs': {'room_name': 'Yoru Room Name'}}
        self.room_group_name = 'chat_%s' % self.room_name #chat_my_room

        await self.channel_layer.group_add(
            self.room_group_name, # group
            self.channel_name # channel
            )
        
        await self.accept()
        

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.room_group_name, # group
            self.channel_name # channel         
            )

    async def receive(self, text_data):
        data = json.loads(text_data) # load json package {"message":"","username":"","room":""}
        message = data['message']
        username = data['username']
        room = data['room']

        await self.save_message(username, room, message)

        await self.channel_layer.group_send(
            self.room_group_name,
            {
            'type' : 'chat_message',
            'message' : message,
            'username' : username,
            'room' : room,
            }
            )

    async def chat_message(self, event):
        message = event['message']
        username = event['username']
        room = event['room']

        await self.send(text_data=json.dumps({ # create json package {"message":"","username":"","room":""}
            'message' : message,
            'username' : username,
            'room' : room,
            }))

    @sync_to_async
    def save_message(self, username, room, message):
        user = User.objects.get(username=username)
        room = Room.objects.get(slug=room)

        Message.objects.create(user=user, room=room, content=message)

ROOM.HTML

{{ room.slug|json_script:"json-roomname" }}
{{request.user.username|json_script:"json-username"}}

<script>
  const roomName = JSON.parse(document.getElementById('json-roomname').textContent);
  const userName = JSON.parse(document.getElementById('json-username').textContent);
  

  const charSocket = new WebSocket(
      (window.location.protocol === 'https:' ? 'wss' : 'ws') + '://'
      + window.location.host
      + '/ws/'
      + roomName
      + '/'

    );

I can see you hard coded the REDIS_URL in the CHANNEL_LAYER configuration.

If the REDIS instance you are using is from heroku add-ons, it's best you access it from the environment variable. You will want to do this because heroku add-ons credentials often change from time to time.

Read this Heroku docs on add-ons credentials changing here

It's worth mentioning that storing credentials externally is also a good practice. By doing so, you are following the twelve - factor app methodology.

Also the fact that you are running on http didn't cause the issue as you managed that well by using 'ws' protocol when running http (ref. the ternary operator in setting your websocket connection).

According to @FAYEMI BOLUWATIFE's answer I changed my Channel layer and it worked!

CHANNEL_LAYERS = {
    "default": {
         'BACKEND': 'channels_redis.core.RedisChannelLayer',
        "CONFIG": {
            "hosts": [os.environ.get('REDIS_URL')]
        },

    },
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM