简体   繁体   English

django 通道在本地工作但在服务器上失败

[英]django channels works locally but fails on server

Django channels fails to connect in production Django 通道无法在生产中连接

i'm working on a chat application using django Channels and reconnecting-web-socket the app works fine locally but when deployed to heroku the site works fine but the web socket closes before connection is established and sometimes it works fine.我正在使用django Channels和 reconnecting-web-socket 开发一个聊天应用程序,该应用程序在本地运行良好,但是当部署到heroku该站点运行良好,但 web 套接字在连接建立之前关闭,有时它运行正常。

it tries to connect and says websocket open and established它尝试连接并说 websocket 打开并建立

2020-11-21T11:45:14.483101+00:00 app[web.1]: 10.38.231.42:12792 - - [21/Nov/2020:11:45:14] "WSCONNECTING /ws/chat/" - -
2020-11-21T11:45:14.483267+00:00 app[web.1]: 2020-11-21 11:45:14,483 DEBUG    Upgraded connection ['10.38.231.42', 12792] to WebSocket
2020-11-21T11:45:14.486434+00:00 app[web.1]: 2020-11-21 11:45:14.486 UTC [24] LOG C-0x5564d6f000a0: db1/kutxkggzwbkjsp@127.0.0.1:35034 login attempt: db=db1 user=kutxkggzwbkjsp tls=no
2020-11-21T11:45:14.493134+00:00 app[web.1]: 2020-11-21 11:45:14,492 DEBUG    WebSocket ['10.38.231.42', 12792] open and established
2020-11-21T11:45:14.493228+00:00 app[web.1]: 10.38.231.42:12792 - - [21/Nov/2020:11:45:14] "WSCONNECT /ws/chat/" - -
2020-11-21T11:45:14.493405+00:00 app[web.1]: 2020-11-21 11:45:14,493 DEBUG    WebSocket ['10.38.231.42', 12792] accepted by application

then it tries to connect to the redis db然后它尝试连接到 redis 数据库

2020-11-21T11:45:14.494880+00:00 app[web.1]: 2020-11-21 11:45:14,494 DEBUG    Parsed Redis URI ('redis-10596.c8.us-east-1-2.ec2.cloud.redislabs.com', 10596)
2020-11-21T11:45:14.495020+00:00 app[web.1]: 2020-11-21 11:45:14,494 DEBUG    Creating tcp connection to ('redis-10596.c8.us-east-1-2.ec2.cloud.redislabs.com', 10596)

but right after that the socket closes但在那之后套接字关闭

2020-11-21T11:45:17.133433+00:00 heroku[router]: at=info method=GET path="/ws/chat/" host=tolk-project.herokuapp.com request_id=41ed7690-5f91-4238-9792-01f52c5f65a1 fwd="102.143.218.204" dyno=web.1 connect=0ms service=2654ms status=101 bytes=145 protocol=http
2020-11-21T11:45:17.134597+00:00 app[web.1]: 2020-11-21 11:45:17,134 DEBUG    WebSocket closed for ['10.38.231.42', 12792]
2020-11-21T11:45:17.135119+00:00 app[web.1]: 10.38.231.42:12792 - - [21/Nov/2020:11:45:17] "WSDISCONNECT /ws/chat/" - -
2020-11-21T11:45:17.419219+00:00 app[web.1]: 2020-11-21 11:45:17,419 DEBUG    Cancelling waiter (<Future cancelled>, [None, None])
2020-11-21T11:45:17.419377+00:00 app[web.1]: 2020-11-21 11:45:17,419 DEBUG    Waiter future is already done <Future cancelled>

what is causing the connection to close immediately ?是什么导致连接立即关闭?

my requirements.txt file:我的requirements.txt文件:

dj-config-url
django==2.2.7
pillow==5.2.0
twisted==19.7.0
asgiref==3.2.2
channels==2.2.0
channels-redis==2.4.0
daphne==2.3.0
django-heroku==0.3.1
django-redis==4.10.0
django-rest-framework==0.1.0
django-storages==1.9.1
djangorestframework==3.10.3
dropbox==9.4.0
psycopg2==2.8.5
setuptools==40.8.0
whitenoise==4.1.2
twisted==19.7.0

my asgi.py file:我的 asgi.py 文件:

import os

import django
from channels.routing import get_default_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Tolk.settings")
os.environ['ASGI_THREADS'] = "19"
django.setup()
application = get_default_application()

my procfile:我的档案:

web: bin/start-pgbouncer-stunnel daphne Tolk.asgi:application --port $PORT --bind 0.0.0.0 -v2

my settings.py file:我的 settings.py 文件:

"""
Django settings for Tolk project.

Generated by 'django-admin startproject' using Django 2.2.1.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os

import dj_database_url
import django_heroku

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

# hosts allowed for use with this application
ALLOWED_HOSTS = [
    'http://tolk-project.herokuapp.com/',
]

# Application definition
INSTALLED_APPS = [
    # built-in
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # third party
    'channels',
    'rest_framework',

    # local
    'chat.apps.ChatConfig',
    'accounts.apps.AccountsConfig',
    'Authentication.apps.AuthenticationConfig',
    'web_interface.apps.WebInterfaceConfig',
]


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

ROOT_URLCONF = 'Tolk.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Tolk.wsgi.application'

# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {'default': dj_database_url.config(ssl_require=False)}

# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files settings
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/


STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'assets'),
)

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

MEDIA_URL = '/media/'

# Authentication Settings
# authentication user model
# https://docs.djangoproject.com/en/2.2/topics/auth/customizing.html
AUTH_USER_MODEL = 'accounts.User'

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

#  *****Channels settings******
# root application
ASGI_APPLICATION = "Tolk.routing.application"
# channel layers backends
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [
                f"redis://:{os.environ.get('REDIS_PASSWORD_1')}@{os.environ.get('REDIS_HOST_1')}",
            ],
        },
    },
}


# Redis Cache
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": f"redis://{os.environ.get('REDIS_HOST_2')}",
        'TIMEOUT': 60 * 60 * 24,
        "OPTIONS": {
            'PASSWORD': os.environ.get('REDIS_PASSWORD_2'),
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        },
        "KEY_PREFIX": "chat"
    },
}



# rest framework
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework.renderers.AdminRenderer',
    ]
}

# **** heroku settings ****
# Activate Django-Heroku.
django_heroku.settings(locals())
# delete ssl mode
del DATABASES['default']['OPTIONS']['sslmode']

# **** dropbox settings ****
DEFAULT_FILE_STORAGE = 'storages.backends.dropbox.DropBoxStorage'
DROPBOX_OAUTH2_TOKEN = os.environ.get('DROPBOX_OAUTH2_TOKEN')

my connect function in consumers.py我在consumers.py 中的连接功能

# used to receive, send messages and keep
# track of online and offline users
class ChatConsumer(AsyncJsonWebsocketConsumer):
    connected_user = None

    async def connect(self) -> None:
        """
        check id user is authenticated if user is
        authenticated the connect to channel and sets up
        a cache db
        """

        if self.scope['user'].is_authenticated:
            # accept user
            await self.accept()
            # to keep track of user
            self.connected_user = self.scope['user']

            cache = caches['default']
            cache.set(f"{self.connected_user.email}", "active")  # cache the user status

            # add your self to your own friend list
            await self.channel_layer.group_add(
                f'{self.connected_user.id}_friends',
                self.channel_name
            )

            # loop the connected user's friends list and
            # add yourself to the each friend's friend list
            for friend in self.connected_user.contact.friends.all():
                group_name = f'{friend.user.id}_friends'
                await self.channel_layer.group_add(
                    group_name,
                    self.channel_name
                )

            # create a new dict that contains the conversation the user joins
            # every time they connected
            joined_conversations = dict()
            cache.set(f"{self.connected_user.email}_conversations", joined_conversations)
            # close cache
            cache.close()
            # send all notifications that the user has
            await self.send_notifications()
        else:
            await self.close()  # reject connection

Note: i also tested this across different browsers注意:我也在不同的浏览器上测试了这个

the problem was in reconnecting-web-socket.min.js changing问题是在重新连接 web-socket.min.js 改变

let socket = new ReconnectingWebSocket(ws_path)

to

let socket =  new WebSocket(ws_path)

fixed the problem.解决了这个问题。

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

相关问题 Django 频道测试失败 - Django Channels testing fails Python Pool.map()-在服务器上本地工作失败 - Python Pool.map() - locally works, on server fails Django登录自定义身份验证在本地有效,但不能在生产服务器上使用 - Django Login Custom Auth works locally but not on production server Flask 在本地工作,但不在服务器上? - Flask works locally, but not on a server? Django 应用程序在本地运行良好,但在登录管理员坐席时在 heroku 中失败 - Django app works fine locally, but fails in heroku when logging into admin sit Django包含标签可用于开发服务器,但测试失败 - Django inclusion tag works with the dev server but fails tests 托管在Apache上的Django应用程序失败,但在Dev服务器上工作正常 - Django application fails when hosted on Apache but works fine on Dev server 在本地运行 pyspark 失败,但在数据块中运行良好 - run pyspark locally fails but works fine in databricks Django / Python http.server通过代理访问404,在本地工作 - Django/Python http.server access 404s via proxy, works locally 使用部署到Heroku的Django应用程序时出现内部服务器错误。 该应用程序在本地工作 - I have an internal server error when using Django app deployed to Heroku. The app works locally
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM