6

我们有一个使用频道包的应用程序,并且工作得很好......在本地主机上。一旦我们点击 staging 并nginx在 Django 前面放置一个框(使用 SSL),我们就可以连接到套接字,但客户端没有收到任何消息。

Nginx 配置:

worker_processes auto;

error_log /dev/stdout info;

user nobody nogroup;
pid /tmp/nginx.pid;

events {
    worker_connections 1024;
    accept_mutex off;
}

http {
    include mime.types;
    default_type application/octet-stream;
    access_log /dev/stdout;
    sendfile on;
    keepalive_timeout 65;
    gzip on;
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_vary on;

    upstream ws_server {
        server unix:/tmp/daphne.sock fail_timeout=0;
    }

    server {
        #   redirect all http requests to https
        listen 80;
        listen [::]:80 ipv6only=on;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;

        client_max_body_size 4G;
        server_name changemyip.com;
        keepalive_timeout 5;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_session_tickets on;

        ssl_dhparam /etc/nginx/ssl/dhparam.pem;

        location /ws/ {
            try_files $uri @proxy_to_ws;
        }

        location @proxy_to_ws {
            proxy_pass   http://ws_server;

            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-Proto $scheme;

            #   Websocket specific
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $http_host;
            proxy_connect_timeout 86400;
            proxy_read_timeout 86400;
            proxy_send_timeout 86400;
        }

        ...
        ssl_protocols TLSv1.1 TLSv1.2;
        ...
        ssl_prefer_server_ciphers on;

        ssl_stapling on;
        ssl_stapling_verify on;
    }
}

Django 使用 gunicorn 运行,对于 websockets,我升级了一个 daphne 服务器。我可以在 daphne 日志中看到我的客户端正在连接,但仍然没有收到从 daphne 到客户端的消息。

Daphne 正在创建一个 nginx 用来通信的 unix 套接字: daphne main.asgi:channel_layer -u /tmp/daphne.sock

4

2 回答 2

8

我有同样的问题。我无法通过 unix-socket 进行连接,但我找到了一种非常简单的方法来使用系统端口来实现请求管理。我使用了以下教程(并使用了我对 Gunicorn 的经验),并设法修改了一些 Nginx 配置文件,我建议您查看教程:

我的 Nginx 文件

# Enable upgrading of connection (and websocket proxying) depending on the
# presence of the upgrade field in the client request header
map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

# Create an upstream alias to where we've set daphne to bind to
upstream django_app_server {
  server 127.0.0.1:8000;
}

server {
  listen 80;
  server_name YOURDOMAIN.COM;

  client_max_body_size 4G;
  access_log /webapps/General/logs/nginx-access.log;
  error_log /webapps/General/logs/nginx-error.log;

  location /static/ {
      alias /webapps/General/DjangoProject/static/;
  }

  location /media/ {
      alias /webapps/General/DjangoProject/media/;
  }

  location / {
    if (!-f $request_filename) {
        proxy_pass http://django_app_server;
        break;
    }
    # Require http version 1.1 to allow for upgrade requests
    proxy_http_version 1.1;
    # We want proxy_buffering off for proxying to websockets.
    proxy_buffering off;
    # http://en.wikipedia.org/wiki/X-Forwarded-For
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # enable this if you use HTTPS:
    # proxy_set_header X-Forwarded-Proto https;
    # pass the Host: header from the client for the sake of redirects
    proxy_set_header Host $http_host;
    # We've set the Host header, so we don't need Nginx to muddle
    # about with redirects
    proxy_redirect off;

    # Depending on the request value, set the Upgrade and
    # connection headers
    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection $connection_upgrade;
  }

  # Error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /webapps/General/DjangoProject/templates/;
  }
}

我项目中的 websocket 运行良好(组和通道),所有请求都由 Daphne 提供服务,但如果您真的需要使用套接字,此配置实际上可能对您有所帮助。

需要考虑的要点

  • 请记住,这个 Nginx 文件通常允许 Daphne 连接,但在生产服务器中,您需要分别运行“Daphne Instance Server”和“Daphne Workers”才能通过您的通道传输消息。

  • 检查您在为您的频道和组提供服务时是否会使用 Redis-Server 或其他一些队列管理器。我这样说是因为我注意到在使用“InMemory”配置时,多条消息丢失了。

  • 还要检查您的生产环境是否将 Redis-Server 作为守护进程运行。我注意到在几个系统中 Redis-Server 甚至没有工作,但是当连接被拒绝时 Django 应用程序没有引发异常。

  • 你需要一些东西来保持 Daphne 和它的工作人员,因为即使它们循环,它们也不是“抗异常”的,所以当出现异常时它们会死掉。显然,我推荐使用 Supervisor 或使用 Linux 系统进行服务。

  • 我不知道 daphne 的工作人员是否可以提供静态和媒体文件DEBUG==False,但显然使用 Nginx 配置单独提供它们更好。

  • 与使用套接字相比,我仍然不知道使用端口对安全/性能的影响,因此值得检查一下(阅读下文,我发现 Daphne 或我的配置可能存在错误)。

我知道这对您现在可能无关紧要,(我的意思是已经快 1 个月了)但也许有人会发现这个答案有一些用处。

未知且非常奇怪的安全问题

TL;DR:不要使用此配置在同一服务器上部署两个 Django-Daphne 应用程序,否则您将度过难关。

通过使用这种配置,我已经能够将 Phoenix 应用程序与 Django 应用程序一起部署而没有任何问题,但是在使用这种类型的配置部署 2 个或更多 Django 应用程序时我遇到了问题。出于某种原因,Daphne 知道它必须不断读取哪些端口才能接收请求,但它只是读取所有这些端口并将它们提供给它喜欢的任何人。例如,如果我拥有DJANGO_APP_1DJANGO_APP_2在同一台服务器上运行(具有不同的 Nginx 配置和明显不同的系统端口),有时 Daphne WorkersDJANGO_APP_2会窃取本应用于的请求DJANGO_APP_1反之亦然。我无法查明问题的根源,但我相信这与达芙妮工人在某种程度上不知道他们所涉及的项目有关。(只是一个理论,我没有时间检查他们的代码)。

于 2016-10-25T17:31:55.807 回答
3

i was working with daphne gunicorn and nginx and i had a hard time finding the correct configuration for nginx,after fiddling with it for sometime this configuration worked for me.

​worker_processes  2;

events {
worker_connections  1024;
}

http {

  include       mime.types;
  default_type  application/octet-stream;
  sendfile        on;
  keepalive_timeout  5;

  upstream webserver {
  server 127.0.0.1:8000;
  }

  upstream wsserver {
  server 127.0.0.1:9000;
  }

  server {
    listen 8046;

    client_max_body_size 20M;
    server_name localhost;
    tcp_nodelay     on;

    location / {
        proxy_pass http://webserver;
        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;
   }

   location /ws/ {
        proxy_pass http://wsserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
 }

 }
于 2017-08-03T13:52:56.310 回答