简体   繁体   English

通道 django

[英]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我正在尝试让 django 频道与达芙妮一起工作,但我无法连接房间,应用程序运行良好,但每当我运行应用程序并打开“房间”websocket 它会自动断开连接,值得一提的是我的网站正在使用 HTTP 运行,任何帮助都将不胜感激

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 Django==4.0.6

daphne==3.0.2达芙妮==3.0.2

channels==3.0.5频道==3.0.5

My configurations我的配置

ASGI.PY 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) PROCFILE(达芙妮工作)

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消费者.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房间.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.我可以看到您在CHANNEL_LAYER配置中对REDIS_URL进行了硬编码。

If the REDIS instance you are using is from heroku add-ons, it's best you access it from the environment variable.如果您使用的 REDIS 实例来自 heroku 附加组件,则最好从环境变量中访问它。 You will want to do this because heroku add-ons credentials often change from time to time.您会想要这样做,因为 heroku 附加组件凭据经常会不时更改。

Read this Heroku docs on add-ons credentials changing here此处阅读有关插件凭据更改的 Heroku 文档

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).此外,您在 http 上运行的事实并没有导致问题,因为您在运行 http 时使用“ws”协议管理得很好(参考设置 ZBF56D570E62CDB5673C86B1852Z7 连接的三元运算符)

According to @FAYEMI BOLUWATIFE's answer I changed my Channel layer and it worked!根据@FAYEMI BOLUWATIFE 的回答,我改变了我的频道层并且它起作用了!

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

    },
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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