django - 使用 django 通道的进程间通信在一小时后失败
问题描述
我有一个 ERP 产品,它需要 nodejs 和 Django 之间的实时双向进程间通信。现在我正在使用 npm WebSocket 和 Django 频道。在使用“python manage.py runserver”开发期间,它工作正常。但在生产过程中,django 推荐使用 daphne 和 runworker。我已经用 nginx 测试过了。现在我的问题是,连接在一段时间后断开。在 Django(1.9) 中,连接持续大约 24 小时。在我更改为 Django2 后,连接仅持续 1 小时左右。系统没有显示任何错误。我的配置如下。
nginx.conf
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name 209.97.166.79;
#location /static/ {
# alias /<project-static-files-path>/static/;
# expires 1y;
#}
location / {
proxy_pass http://0.0.0.0:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}}
项目结构
.
├── db.sqlite3
├── django_two_main
│ ├── asgi.py
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── asgi.cpython-35.pyc
│ │ ├── __init__.cpython-35.pyc
│ │ ├── routing.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ └── urls.cpython-35.pyc
│ ├── routing.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── README.md
├── requirements.txt
├── sales
│ ├── django_node_connect
│ │ ├── consumers.py
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── consumers.cpython-35.pyc
│ │ │ ├── __init__.cpython-35.pyc
│ │ │ └── routing.cpython-35.pyc
│ │ ├── routing.py
│ │ └── views.py
│ ├── __init__.py
│ └── __pycache__
│ └── __init__.cpython-35.pyc
└── static
设置.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ALLOWED_HOSTS = []
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
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',
]
ROOT_URLCONF = 'django_two_main.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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 = 'django_two_main.wsgi.application'
ASGI_APPLICATION = "django_two_main.routing.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
"django_two_main.settings")
django.setup()
application = get_default_application()
用于运行 daphne 的命令
daphne -b 0.0.0.0 -p 8001 django_two_main.asgi:application --access-
log /home/logs/access.log &
访问日志
127.0.0.1:37012 - - [13/Jun/2018:08:23:25] "GET /" 400 53326
127.0.0.1:37014 - - [13/Jun/2018:08:35:45] "HEAD /phpmyadmin/" 400 -
127.0.0.1:37016 - - [13/Jun/2018:08:35:45] "HEAD /PMA/" 400 -
127.0.0.1:37018 - - [13/Jun/2018:08:35:46] "HEAD /dbadmin/" 400 -
127.0.0.1:37020 - - [13/Jun/2018:08:35:46] "HEAD /pma/" 400 -
127.0.0.1:37022 - - [13/Jun/2018:08:35:46] "HEAD /db/" 400 -
127.0.0.1:37024 - - [13/Jun/2018:08:37:29] "GET /" 400 53322
127.0.0.1:37026 - - [13/Jun/2018:08:37:30] "GET /" 400 53322
127.0.0.1:37028 - - [13/Jun/2018:08:41:50] "GET /" 400 53320
127.0.0.1:37030 - - [13/Jun/2018:08:49:56] "GET /" 400 53322
127.0.0.1:37032 - - [13/Jun/2018:09:00:31] "GET /" 400 53322
127.0.0.1:37036 - - [13/Jun/2018:09:13:38] "GET /" 400 53320
127.0.0.1:37038 - - [13/Jun/2018:09:18:39] "GET /" 400 53572
127.0.0.1:37040 - - [13/Jun/2018:09:18:40] "GET /" 400 53572
127.0.0.1:37042 - - [13/Jun/2018:09:20:54] "GET /" 400 53320
127.0.0.1:37044 - - [13/Jun/2018:09:36:07] "GET /" 400 53324
nginx错误日志(IP地址已更改)
2018/06/13 04:56:31 [error] 5969#5969: *1820 connect() failed (111:
Connection refused) while connecting to upstream, client:
80.211.172.33, server: 100.23.126.79, request: "HEAD
http://239.237.136.29:80/dbadmin/ HTTP/1.1", upstream:
"http://0.0.0.0:8001/dbadmin/", host: "239.197.163.734"
2018/06/13 04:56:32 [error] 5969#5969: *1820 connect() failed (111:
Connection refused) while connecting to upstream, client:
80.211.172.33, server: 249.23.163.193, request: "HEAD
http://219.12.66.71:80/pma/ HTTP/1.1", upstream:
"http://0.0.0.0:8001/pma/", host: "212.37.136.49"
路由.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import sales.django_node_connect.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
sales.django_node_connect.routing.websocket_urlpatterns
)
),
})
nodejs (pm2) 日志显示此消息
[2018-06-13T10:29:06.899Z] reconnecting:ws://localhost:8001/channel
[2018-06-13T10:29:08.900Z] reconnecting:ws://localhost:8001/channel
[2018-06-13T10:29:10.900Z] reconnecting:ws://localhost:8001/channel
解决方案
Nginx 在预定义的时间后关闭连接。如果你想拥有长寿命的连接,你需要设置自定义超时。我也有同样的问题,设置proxy_read_timeout
为86400
.
location / {
proxy_pass http://0.0.0.0:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
推荐阅读
- java - 如何通过 micronaut Http Client 将 grails 应用程序连接到 Consul?
- javafx - 如何在 Java FX 11 中实现 JavaFX 2.2 示例
- django - ModuleNotFoundError:没有名为“social_django_urls”的模块
- node.js - 在不同的文件夹中创建帖子
- sql-server - 在 SQL Server 中用新的 Int FK 替换 varchar FK
- php - Yii2 - 测验 - 使用多对多表
- git - 拉取请求不作为 Github 中的合并(但不是 Bitbucket/Gitlab)
- javascript - 这种在对象中声明 JavaScript 函数的方式是什么?
- swift - 由于“内部”保护级别切换语句,Alamofire 的“值”无法访问
- excel - VBA:从 Excel 到 PowerPoint 的 PasteSpecial 带有“形状(未知成员):无效请求”。错误