[英]django channels works locally but fails on server
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.