6

channels パッケージを使用し、正常に動作するアプリがあります... localhost で。ステージングを開始してnginx(SSL を使用して) Django の前にボックスを配置するとすぐに、ソケットに接続できますが、クライアントはメッセージを受信しません。

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 で動作し、websocket 用に daphne サーバーを立ち上げました。クライアントが接続していることを daphne ログで確認できますが、それでも daphne からクライアントへのメッセージは受信されません。

Daphne は、nginx が通信するために取得する UNIX ソケットを作成しています。 daphne main.asgi:channel_layer -u /tmp/daphne.sock

4

2 に答える 2

8

私はまったく同じ問題を抱えていました。Unix ソケット経由で接続することはできませんでしたが、システム ポートを使用してリクエスト管理を実現する非常に簡単な方法を見つけました。私は次のチュートリアルを使用し (そして 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/;
  }
}

私のプロジェクトの websockets (グループとチャネル) は非常にうまく機能しており、すべての要求は Daphne によって処理されていますが、ソケットを本当に使用する必要がある場合は、この構成が実際に役立つ可能性があります。

考慮すべき点

  • この Nginx ファイルにより、Daphne は一般的に接続できるようになりますが、実稼働サーバーでは、「Daphne Instance Server」と「Daphne Workers」を個別に実行して、チャネルを介してメッセージを送信できるようにする必要があることに注意してください。

  • チャネルとグループにサービスを提供するときに、Redis-Server またはその他のキュー マネージャーを使用するかどうかを確認します。「InMemory」構成を使用すると、複数のメッセージが失われることに気付いたので、これを言います。

  • また、本番環境で Redis-Server がデーモンとして実行されているかどうかも確認してください。いくつかのシステムでは Redis-Server が機能していないことに気付きましたが、Django アプリケーションは接続が拒否されたときに例外を発生させませんでした。

  • Daphne とそのワーカーを維持するために何かが必要です。なぜなら、それらはループしても「例外耐性」ではないため、例外が発生すると終了するからです。明らかに、サービスにはスーパーバイザーまたは Linux システムを使用することをお勧めします。

  • ダフネのワーカーが静的ファイルとメディア ファイルを提供できるかどうかはわかりませんがDEBUG==False、Nginx 構成を使用してそれらを個別に提供する方が明らかに優れています。

  • ソケットを使用する場合と比較して、ポートを使用する場合のセキュリティ/パフォーマンスへの影響はまだわかりません。そのため、確認する価値があります (以下をお読みください。Daphne または私の構成にバグの可能性があることがわかりました)。

これは今あなたにとって無関係かもしれないことを私は知っています(つまり、ほぼ1か月が経ちました)が、おそらく誰かがこの答えに何らかの用途を見つけるでしょう.

未知のかなり奇妙なセキュリティの問題

TL;DR : この構成で同じサーバーに 2 つの Django-Daphne アプリをデプロイしないでください。

この構成を使用することで、Phoenix アプリケーションを Django アプリケーションと一緒に問題なくデプロイできましたが、このタイプの構成を使用して 2 つ以上の Django アプリケーションをデプロイするときに問題が発生しました。ある理由から、Daphne はリクエストを受信するためにどのポートを常に読み取らなければならないかを知っていますが、すべてのポートを読み取って、好きな人に提供するだけです。たとえば、同じサーバーDJANGO_APP_1DJANGO_APP_2実行している場合 (Nginx の構成が異なり、システム ポートが明らかに異なる場合)、Daphne WorkerDJANGO_APP_2が目的のリクエストを盗むことがあります。DJANGO_APP_1およびその逆。問題の原因を突き止めることはできませんでしたが、Daphne の従業員が、関連するプロジェクトに特定の方法でとらわれていたことに関係していると考えられます。(単なる理論です。コードをチェックする時間がありません)。

于 2016-10-25T17:31:55.807 に答える