python - 在 nginx 上使用 Django 设置套接字

标签 python django sockets nginx redis

我有一个在 nginx 上运行的 Django 应用程序。这个应用程序使用套接字,(据我所知)应该被代理。所以我在配置 nginx 和其他东西时遇到了麻烦。相同的应用程序在 Apache/2.4.7 上运行良好,因此我认为这不是编程错误。

使用的套接字基于 Django-Channels,后端与 Channels getting started 中的代码非常相似.

对于服务器配置,我使用了 this手册。

一开始我只有一个问题:在创建套接字时我得到了 200 个请求应答而不是 101 个。经过多次操作(配置和安装更新版本)和信息收集后,我得出了目前的情况:

我为套接字单独启动 uwsgi:

uwsgi --virtualenv /home/appname/env/ --http-socket /var/run/redis/redis.sock --http-websock --wsgi-file /home/appname/appname/appname/wsgi.py

在创建套接字的这一步 var socket = new WebSocket("ws://appname.ch/ws/64"); 我明白了

WebSocket connection to 'ws://appname.ch/ws/64' failed: Error during WebSocket handshake: Unexpected response code: 502 

当然

2016/09/12 12:00:26 [crit] 30070#0: *2141 connect() to unix:/var/run/redis/redis.sock failed (13: Permission denied) while connecting to upstream, client: 140.70.82.220, server: appname.ch,, request: "GET /ws/64 HTTP/1.1", upstream: "http://unix:/var/run/redis/redis.sock:/ws/64", host: "appname.ch"

在 nginx 错误日志中。

chmod 777/var/run/redis/redis.sock 之后我得到响应

WebSocket connection to 'ws://appname.ch/ws/64' failed: Error during WebSocket handshake: Unexpected response code: 404

在 uwsgi 中

[pid: 6572|app: 0|req: 1/1] 0.0.0.0 () {46 vars in 916 bytes} [Mon Sep 12 12:01:29 2016] GET /ws/64 => generated 3357 bytes in 24 msecs (HTTP/1.1 404) 2 headers in 80 bytes (1 switches on core 0)

nginx.conf 文件

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
worker_connections 768;
# multi_accept on;
}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

redis.conf

daemonize yes

pidfile /var/run/redis/redis-server.pid

port 6379

unixsocket /var/run/redis/redis.sock
unixsocketperm 777

timeout 0

loglevel notice

logfile /var/log/redis/redis-server.log

databases 16

save 900 1
save 300 10
save 60 10000

rdbcompression yes

dbfilename dump.rdb

dir /var/lib/redis

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

/etc/nginx/sites-enabled/应用名称

server {
        listen       80;
        server_name  appname.ch, 177.62.206.170;

      #charset koi8-r;
    client_max_body_size 8M;

        access_log  /var/log/nginx/access.log;
        error_log   /var/log/nginx/error.log;

        location / {
            include        uwsgi_params;
            uwsgi_pass     unix:///home/appname/appname/app.sock;
           #add_header     Access-Control-Allow-Origin *;
    }
    location /ws/ {
        #proxy_redirect off;
        proxy_pass http://unix:/var/run/redis/redis.sock;
        #proxy_http_version 1.1;
        #proxy_set_header Upgrade $http_upgrade;
            #proxy_set_header Connection "upgrade";

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

    }

        location /static {
            alias /home/appname/appname/static_files;
        }

        location /media {
            alias /home/appname/appname/media;
       }
}

uwsgi.ini

[uwsgi]

chdir=/home/appname/appname
env=DJANGO_SETTINGS_MODULE=appname.settings
wsgi-file=appname/wsgi.py
master=True
pidfile=/home/appname/appname/appname-master.pid
vacuum=True
max-requests=5000
daemonize=/home/appname/appname/uwsgi.log
socket=/home/appname/appname/app.sock
virtualenv=/home/appname/env
uid=appname
gid=appname

Django 应用设置.py

"""
Django settings for appname project.

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

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

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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ''

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

TEMPLATE_DEBUG = DEBUG

ALLOWED_HOSTS = ['.appname.ch', '177.62.206.170', '127.0.0.1']


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'customers',
    'projects',
    'moodboard',
    'channels',
    'debug_toolbar',
    'rest_framework',
    'appname',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'appname.urls'

WSGI_APPLICATION = 'appname.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


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

STATIC_URL = '/static/'

MEDIA_URL = '/media/'

STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')

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

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static_files'),
)

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
)

AUTH_PROFILE_MODULE = 'customers.Customer'

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

LOGIN_REDIRECT_URL = '/accounts/home'

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
        "ROUTING": "appname.routing.channel_routing",
    },
}

应用程序网址

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.contrib.auth import views as auth_views
from projects.views import ProjectViewSet
from customers.views import UserHomeView, RegistrationView, CustomerViewSet, UserViewSet
from moodboard.views import MoodBoardViewSet, BoardItemViewSet, BoardTextViewSet, ShareMoodBoardItem, LiveViewSet
from rest_framework import routers
from django.conf import settings
from django.conf.urls.static import static


router = routers.DefaultRouter()
router.register(r'projects', ProjectViewSet)
router.register(r'moodboards', MoodBoardViewSet)
router.register(r'items', BoardItemViewSet)
router.register(r'texts', BoardTextViewSet)
router.register(r'share', ShareMoodBoardItem)
router.register(r'customers', CustomerViewSet)
router.register(r'users', UserViewSet)
router.register(r'live', LiveViewSet)


urlpatterns = patterns('',
                       url(r'^$', 'appname.views.home', name='landing_page'),
                       url(r'^api/', include(router.urls)),
                       url(r'^accounts/login/$', auth_views.login, name='login'),
                       url(r'^accounts/logout/$', auth_views.logout, name='logout'),
                       url(r'^accounts/home/$', UserHomeView.as_view(), name='home'),
                       url(r'^accounts/register/$', RegistrationView.as_view(), name='registration'),
                       url(r'^admin/', include(admin.site.urls)),
                       url(r'^customers/', include('customers.urls')),
                       url(r'^projects/', include('projects.urls')),
                       url(r'^moodboard/', include('moodboard.urls')),
                       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
                       )

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)root

nginx 版本:1.6.2 Redis 服务器版本:2.4.14 uwsgi版本:2.1 Django 版本:1.8.0“最终版” python 版本:2.7.3

似乎 404 应该不是一个复杂的错误,但经过多天的修复后,我不知道问题出在哪里,也不知道我的方法是否正确。

最佳答案

首先,永远不要尝试手动创建 socks 。 只需设置一个路径,它就会自动创建。

这是 nginx 和 uwsgi conf 的示例:

server {
root /your/djang/app/main/folder/;

# the port your site will be served on
listen      80;
server_name your-domain.com *.your-domain.com # if you have subdomains
charset     utf-8;

access_log /path/to/logs/if/you/have/access_log.log
error_log /path/to/logs/if/you/have/error_log.log

# max upload size
client_max_body_size 1G;

location /media/  {
    alias /path/to/django/media/if/exist/;
}

location /static/ {
    alias  /path/to/django/static/if/exist/;
}
# Note three slash 
location / { 
    uwsgi_pass unix:///home/path/to/sock/file/your-sock.sock
}

这个cna就是你的uwsgi配置文件

# suprasl_uwsgi.ini file
[uwsgi]

uid = www-data
gid = www-data
chmod-socket = 755
chown-socket = www-data
# Django-related settings
# the base directory (full path)
chdir           = /your/djang/app/main/folder/
# Django's wsgi file
wsgi-file       = /your/djang/app/main/folder/main-folder/wsgi.py;
# the virtualenv (full path)
home            = /your/env/folder/;
# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 2
# the socket (use the full path to be safe
socket          =  /home/path/to/sock/file/your-sock.soc

logto           = /path/to/logs/if/you/have/uwsgi_logs.log

你所要做的就是运行这个命令:

uwsgi --ini your_uwsgi_file.ini # --ini 选项用于指定一个文件

关于python - 在 nginx 上使用 Django 设置套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39450642/

相关文章:

c - C 中 Socket 中的大文件传输错误

java - 在 Android 中连接到服务器时切换网络

python - os.makedirs 导致 Amazon AWS Ubuntu 实例上的 OSError

python - 使用 range/arange 函数作为参数索引/切片 2d numpy 数组

python - 当从遗留数据库生成模型类时,如何在 django-rest 中序列化多个模型数据

javascript - django 使用模板 View 和 ajax

django - 为什么需要使用 Django REST API?

Python - 关于字符串编辑的问题

python - 将单元格从 Libreoffice Calc 复制到 Spyder 中的 IPython 控制台

javascript - 使用node.js向HL7服务器发送数据的问题