如何修复 Daphne、Redis 和 Ngnix 配置以支持来自前端客户端的 Websocket 连接?

问题描述 投票:0回答:1

这是我的数字海洋水滴当前的配置:

Django、Django 频道、Daphne、Nginx、Gunicorn、HTTPS**

我在尝试配置 Redis、Daphne 和 Nginx 时陷入困境。我使用此演练来配置它,但我仍然遇到问题:

我能够成功地将我的服务器部署到 https,前端能够成功连接后端并与后端交互。

--------------------------------------达芙妮.服务-------- ----------------------------

[Unit]
Description=WebSocket Daphne Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/user/project
ExecStart=/home/user/project/venv/bin/python /home/user/project/venv/bin/daphne -e ssl:8001:privateKey=/etc/letsencrypt/live/mydomian.com/privkey.pem:certKey=/etc/letsencrypt/live/DomainURL/fullchain.pem project.asgi:application  
Restart=on-failure

[Install]
WantedBy=multi-user.target

----------------------/etc/nginx/sites-available/project----------------- ---------------

server {
    server_name DomainURL www.DomainURL;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/project;
}

location / {
    include proxy_params;
    proxy_pass http://unix:/run/gunicorn.sock;
}

location /ws/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;
    proxy_pass http://127.0.0.1:8001;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/DomainURL/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/DomainURL/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = www.DomainURL) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = DomainURL) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


listen 80;
server_name DomainURL www.DomainURL;
return 404; # managed by Certbot
}

--------------------------------(Django)Settings.py------------ --------------------------

ALLOWED_HOSTS = ['<server ip>', 'localhost', '127.0.0.1', 'DomainURL', 'www.DomainURL']

ASGI_APPLICATION = "project.asgi.application"

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

CORS_ORIGIN_ALLOW_ALL = True  
CORS_ALLOW_CREDENTIALS = True

----------------------------------(Django) asgi.py--------- ------------------------------------------

import os
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import myApp.routing

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")

application = ProtocolTypeRouter({
     "http": get_asgi_application(),
     "websocket": AuthMiddlewareStack(
         URLRouter(
             myApp.routing.websocket_urlpatterns
         )
     )
 })

---------------------------------(Django) Routing.py---------- --------------------------

from django.urls import re_path
from. consumers import ChatConsumer

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<user_id>\d+)/', ChatConsumer.as_asgi()),
]

--------------------------------(Django) 需求.txt------------ ---------------------------------

asgiref==3.7.2
Django==5.0
django-jazzmin==2.6.0
djangorestframework==3.14.0
djangorestframework-simplejwt==5.3.1
import-export==0.3.1
Pillow==10.1.0
PyJWT==2.8.0
pytz==2023.3.post1
sqlparse==0.4.4
tzdata==2023.3
django-crispy-forms
django-import-export
django-mathfilters
django-taggit
django-ckeditor
django-ckeditor-5

# Additional Django utilities
django-cors-headers
channels
daphne
gunicorn
psycopg2

#db url
dj-database-url

我正在尝试使用前端的 JavaScript 将我的前端连接到在我的服务器上运行的 websocket:

--------------------------------前端文件处理 websocket 操作------------ -----------

class WebSocketService {
    private socket: WebSocket | null

    private messageHandler: ((data: any) => void) | null;

    constructor() {
      this.socket = null;
      this.messageHandler = null;
    }

    setMessageHandler(handler: (data: any) => void) {
      this.messageHandler = handler;
    }
  
    connect(url: string) {
      this.socket = new WebSocket(url);
  
      // Connection opened
      this.socket.addEventListener('open', (event) => {
        console.log('WebSocket is connected');

      });

...
  export const websocketService = new WebSocketService();


---------------------前端文件调用websocket函数------------------------ -----

const wsBaseUrl = 'wss://www.DomainURL';

  if (UserProfile && !isSocketConnected) {
    setisSocketConnected(true)
    const socket = `${wsBaseUrl}/ws/chat/${UserProfile.user_id}/`
    websocketService.connect(socket as any)
  }



*** 所有代码和 Web 套接字连接都按照我的开发环境中的设计工作,我的后端托管在我的本地/家庭网络上。

运行这些命令时我没有收到任何错误:

sudo systemctl status gunicorn
sudo systemctl status redis
systemctl status daphne.service
systemctl status on_boot.service

我在前端应用程序上收到此控制台错误:

WebSocket connection to 'wss://www.DomainURL/ws/chat/2/' failed: There was a bad response from the server.

我尝试修改这些文件的配置,但未能获得不同的结果。目标是让前端与后端 websocket 建立连接。

nginx redis digital-ocean django-channels daphne
1个回答
0
投票

我能够解决这个问题。我需要更改我的配置,以便所有内容都在同一端口上运行。

这是我改变的:

----------------------/etc/nginx/sites-available/project----------------- ---------------- 之前:

location /ws/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;
    proxy_pass http://127.0.0.1:8001;
}

之后:

location /ws/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;
    proxy_pass http://127.0.0.1:8000/ws/;
}

这对我有用,因为我的 Daphne 服务在端口 8000 上运行。

对于有类似问题的其他人,请运行此命令来验证您的 Daphne 服务正在运行:

sudo journalctl -u daphne.service -f
© www.soinside.com 2019 - 2024. All rights reserved.