Django Channels wesbsocket在Heroku上失败

af7jpaap  于 2023-05-01  发布在  Go
关注(0)|答案(1)|浏览(112)

我有一个部署到Heroku并使用django channels 3的应用程序。0.4。它在过去的18个月里一直运行得很好,但现在出现了以下错误:
WebSocket连接到'wss://my-app。myurl/ws/quiztest/mc/'失败:
我没有改变任何的代码时,它是以前的工作。我也有一个在Heroku上运行的应用程序的测试版本,使用完全相同的代码库,它工作正常,这表明错误可能与我的Heroku配置有关,尽管我已经比较了这个应用程序的设置与测试应用程序,它们似乎还可以。我的应用程序中的其他一切都很好,只是django通道WebSocket问题。
我做了一个简单的测试来重现这个问题。下面是尝试连接的JS:

<script>

    var loc = window.location;

    var wsStart = 'ws://';
    if (loc.protocol == 'https:'){
        wsStart = 'wss://';
    }

    var endpoint = wsStart + loc.host + '/ws/quiztest/';
    var username = 'mc';
    var socket = new WebSocket(endpoint + username + '/');
    console.log(socket);
    console.log(endpoint + username + '/');

    socket.onopen = function(e) {
      console.log('Open Host Socket')
    };

    socket.onmessage = function(event) {
      // Handle incoming messages from the server here
      console.log('Received message:', event.data);
    }

    socket.onclose = function(e) {
        console.log('Close',e);
    };

    socket.onerror = function(e) {
        console.log('Error', e);
    };

</script>

这是我 www.example.com

from django.urls import path

from taskmanager.consumers import MyQuizConsumer

ws_urlpatterns = [
    path('ws/quiztest/<username>/', MyQuizConsumer.as_asgi()),
]

这是我 www.example.com

from channels.generic.websocket import WebsocketConsumer, AsyncWebsocketConsumer
from base.base_helpers import log_and_print

from asgiref.sync import async_to_sync

class MyQuizConsumer(WebsocketConsumer):

    def connect(self):
        log_and_print('QUIZ HOST TEST connecting...')

        async_to_sync(self.channel_layer.group_add)(
            'id-1',
            self.channel_name
        )
        self.accept()

有没有什么我可能做错了,或者我的Heroku配置中有哪些方面我需要检查,可能会导致WebSocket失败?

bvuwiixz

bvuwiixz1#

所以我解决了这个问题。据我所知,这最初是由我的Heroku Redis示例达到最大可用内存造成的。我将计划从Mini升级到Premium-0。不过,这也将Redis示例升级到了6。2、我得到了:
SSLCertVerificationError:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败:证书链中的自签名证书(_ssl.c:1123)
原来Production plans (Premium and higher) of Heroku Data for Redis running Redis 6+ require TLS connections. Heroku Data for Redis使用自签名证书,这些需要禁用。这需要对缓存和两个通道层进行。

酒店CACHES

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL,
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'IGNORE_EXCEPTIONS': True,
            'CONNECTION_POOL_KWARGS': {
                'ssl_cert_reqs': None
            },

        }
    }
}

通道层

import ssl
ssl_context = ssl.SSLContext()
ssl_context.check_hostname = False

heroku_redis_ssl_host = {
    'address': REDIS_URL,
    'ssl': ssl_context
}

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': (heroku_redis_ssl_host,)
        }
    },
}

相关问题