django+channels(websocket)开发及nginx部署

前言:因为项目中需要服务器实时将结果反馈给前端,之前采用的ajax轮询的方式,缺点大家都懂的。因为久仰websocket大名,正好最近有些时间,就想把原有项目升级一下,由ajax升级到websocket,毕竟websocket可以由服务器主动发送数据,优势太明显了。

这篇博文分为两个阶段,即开发配置与部署。其实开发(demo)只用了一会儿就完成了,并且在python manage.py runserver 下前后台测试成功,以为很快可以发布了。结果部署到生产环境中居然费了两天时间。因为之前没用过,所以费了好大的力气,特别是开始想用IIS的URL重写功能,结果研究了一天也没成功(本来用IIS+Django的案例就很少,加上channels就更少了,我可能还是哪里没设置好,如果有谁配置成功了希望能教教我),后来改用nginx也磨了大半天才成功。这里记录一下流程的步骤,以免将来遗忘。

各种版本:python--3.8.3  django--3.1.4  nginx--1.21.4  chanels--3.0.4  OS:window2012Server 

一,开发配置

1,安装channels:

        因为新版django中已经淘汰了传统的websocket,将功能融入到了更全面的channels中,所以需要先在命令行安装channels

pip install channels

2,配置项目setting.py,首先注册一下channels

INSTALLED_APPS = [
   ...
    'channels',
   ...
]

        再在原来指定WSGI的后面添加ASGI变量

WSGI_APPLICATION = 'heidanew.wsgi.application' #原项目中有的
ASGI_APPLICATION = 'heidanew.asgi.application' #新添加的,就是将wsgi都改成asgi

这里解释一下这两个名词:WSGI是基于HTTP协议模式的,不支持WebSocket,而ASGI的诞生则是为了解决Python常用的WSGI不支持当前Web开发中的一些新的协议标准。同时,ASGI对于WSGI原有的模式的支持和WebSocket的扩展,即ASGIWSGI的扩展。

3,修改asgi.py中的内容(django3以上应该都有这个文件,如果没有可以创建一个,与setting.py平级)如下:

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'heidanew.settings')

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

因为默认的asgi中没有websocket协议,所以利用这个入口文件将websocket加进来,注意上面有一个from . import routing,现在还没有这个文件,所以按这个顺序走的时候那里会报错,一会儿我们就创建这个文件

4,与asgi.py平级的目录中新建routing.py文件,

我的代码如下:

from django.urls import re_path
from ws_app import consumers

websocket_urlpatterns=[
    re_path(r'ws/channels/',consumers.ChatConsumer.as_asgi())
]

routing.py相当于wsgi使用的urls.py,都是提供路由作用的。我这里只写了一个路径,你当然可以写多个路径。上面引入 的ws_app中的consumners,是下面即将要创建的app及其中的一个模块。

5, 用startapp命令创建一个ws_app的app,创建consumers.py文件(app名和文件名当然可以随意起名,但要和第4步中的引入对应上)

 consumers.py中的代码如下:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        #有客户端向后端改善websocket请求时自动触发
        #服务端允许执行下行代码,如果不允许可以用 raise StopConsumner()拒绝客户端的连接请求
        self.accept()
    def websocket_receive(self, message):
        #客户端发来数据时触发,message是客户端发来的数据(一个字典)
        print(message)
        self.send("服务器端的内容")#向客户端发送数据
    def websocket_disconnect(self, message):
        # 断开连接时触发
        raise StopConsumer()

这里的三个“回调”函数分别分别连接成功时,接收客户端数据时,连接关闭时,函数名不能变,我这里每当接收到客户端请求时就自动发一个“服务端的内容”给客户端,而且你也可以在程序中任意位置使用self.send随时将数据主动发送给客户端。

二.,前端代码 

<body>
 
    <button onclick="sendData(123)">发送</button>
   
</body>
<script type="text/javascript">
    if ("WebSocket" in window) {
        // 打开一个 web socket      
        ws = new WebSocket("ws://127.0.0.1:7002/ws/channels/");

        // 连接建立后的回调函数
        ws.onopen = function() {
            // Web Socket 已连接上,使用 send() 方法发送数据
            ws.send("admin:123456");
            console.log("正在发送:admin:123456");
        };

        // 接收到服务器消息后的回调函数
        ws.onmessage = function(evt) {
            var received_msg = evt.data;
            if (received_msg.indexOf("sorry") == -1) {
                console.log("收到消息:" + received_msg);
            }

        };

        // 连接关闭后的回调函数
        ws.onclose = function() {
            // 关闭 websocket
            console.log("连接已关闭...");
        };
    } else {
        // 浏览器不支持 WebSocket
        console.log("您的浏览器不支持 WebSocket!");
    }
    // setTimeout(() => {
    //     ws.send("aaabbccc");
    //     console.log("正在发送:aabccc");

    // }, 1000)

    function sendData(str) {
        ws.send(str)
    }
</script>

现在,可以使用python manage.py runserver 7002开启测试服务器,打开前端网页时直接可以看到下图所示结果,就表示成功了

三,部署nginx服务器 

你觉得这样就够了?远远不行,因为思路为外网进来的时候是不可以使用这个测试(开发环境)w作为服务器的,需要绑定域名和使用daphne服务器进行托管asgi服务。思路如下:

进站域名如果是ws协议开头的,如ws://域名:7002/ws/channels/
则转换为ws://127.0.0.1:7002/ws/channels。此时的127.0.0.1:7002并不是nginx服务器,而是为ASGI提供服务的daphne程序。具体步骤如下:(以下操作均在远程服务器进行)

1,启动daphne服务:

在终端运行执行以下命令,启动127.0.0.1:7002的ASGI服务

daphne -p 7002 heidanew.asgi:application

启动后如下所示:

这里注意一下:这个daphne在官网上看是在unix环境下 运行的,但实际上我的操作系统是window也可以运行

2,nginx中的nginx.conf文件内容,其中的server配置这么写:

    server {
        listen       7002;
        server_name  你的域名;
        location / {#一般的http协议
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host  $http_host;
            proxy_set_header X-Nginx-Proxy true;
            proxy_set_header Connection "";
            proxy_pass http://域名:7001;
            proxy_redirect default;
            #root   html;
        }
          location /ws{#ws协议时
            proxy_http_version 1.1;
            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-Nginx-Proxy true;
            proxy_redirect off;
            client_max_body_size 10m;
            proxy_pass http://127.0.0.1:7002;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_connect_timeout 300s;
            proxy_read_timeout 300s;
            proxy_send_timeout 300s; 
       }
     
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

说明一下,上面的代码将访问网站的请求分为2种,http(https)或ws(wss),前者直接走前面的请求,实际上我还有一个IIS服务器,是指向 “域名:7001"地址的,所以正常的请求就直接走7001这个地址即可即proxy_pass http://域名:7001,但如果是ws协议,则走的proxy_pass http://127.0.0.1:7002;运行的是本机的daphne服务。、

我在配置IIS时也想进行这种URL重写,但是不知为什么一直没有成功。以上就是配置的全部内容,现在在远程测试一下。将前端代码中的websocket对象在定义时改成你的域名,即:

ws = new WebSocket("ws://域名:7002/ws/channels/");

然后在本地运行(即访问远程服务器)应该可以得到下图的结果了。

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Django是一个优秀的Web框架,可以帮助开发者快速构建Web应用程序。但是,当我们需要将Django应用程序部署到生产环境时,我们需要考虑很多方面,例如性能、安全、可靠性等。本文将介绍如何使用Gunicorn和NginxDjango应用程序部署到生产环境中。 ## 准备工作 在开始之前,我们需要在服务器上安装一些必要的软件包和库。 ### 安装Python和pip 首先,我们需要在服务器上安装Python和pip。如果您已经安装了它们,请跳过此步骤。 ```shell # Ubuntu sudo apt-get update sudo apt-get install python3 python3-pip # CentOS sudo yum update sudo yum install python3 python3-pip ``` ### 创建虚拟环境 为了避免与其他Python应用程序的依赖项冲突,我们建议在服务器上使用虚拟环境。在此过程中,我们将使用venv创建一个虚拟环境。 ```shell python3 -m venv myenv source myenv/bin/activate ``` ### 安装Django和Gunicorn 一旦我们进入虚拟环境,我们可以使用pip安装Django和Gunicorn。 ```shell pip install django gunicorn ``` ## 配置Gunicorn Gunicorn是一个Python WSGI HTTP服务器,可以处理Django应用程序的并发请求。下面是如何配置Gunicorn。 ### 创建Gunicorn配置文件 我们可以为Gunicorn创建一个配置文件。在此过程中,我们将创建一个名为`gunicorn_config.py`的文件。 ```python bind = "127.0.0.1:8000" workers = 3 user = "myuser" ``` 在这个配置文件中,我们定义了以下几个参数: - `bind`:指定Gunicorn绑定的IP地址和端口号。 - `workers`:指定Gunicorn启动的工作进程数。 - `user`:指定Gunicorn运行的用户。 请注意,我们将Gunicorn绑定到`127.0.0.1`地址,这意味着它只能在本地访问。如果您想让Gunicorn在公共IP地址上运行,请使用`0.0.0.0`。 ### 启动Gunicorn 一旦我们创建了配置文件,我们可以使用以下命令启动Gunicorn。 ```shell gunicorn myproject.wsgi:application -c gunicorn_config.py ``` 在这个命令中,我们指定了Django的WSGI入口点`myproject.wsgi:application`,以及Gunicorn配置文件`gunicorn_config.py`。 ## 配置Nginx 现在我们已经成功启动了Gunicorn,我们需要将Nginx配置为反向代理,以便客户端可以通过Nginx访问我们的应用程序。 ### 安装Nginx 如果您还没有安装Nginx,请按照以下步骤进行安装。 ```shell # Ubuntu sudo apt-get update sudo apt-get install nginx # CentOS sudo yum update sudo yum install nginx ``` ### 创建Nginx配置文件 我们需要为Nginx创建一个配置文件。在此过程中,我们将创建一个名为`myproject.conf`的文件。 ```nginx server { listen 80; server_name example.com; access_log /var/log/nginx/access.log; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 在这个配置文件中,我们定义了以下几个参数: - `listen`:指定Nginx监听的端口号。 - `server_name`:指定Nginx的域名。 - `access_log`:指定Nginx的访问日志路径。 - `location`:指定Nginx的URL匹配规则和反向代理设置。 请注意,我们将Nginx绑定到`example.com`域名,并将所有请求转发到Gunicorn运行的`127.0.0.1:8000`地址。 ### 重启Nginx 一旦我们创建了配置文件,我们可以使用以下命令重新启动Nginx。 ```shell sudo service nginx restart ``` ## 结论 现在我们已经成功地将Django应用程序部署到生产环境中。我们使用Gunicorn处理并发请求,并使用Nginx作为反向代理,以提高性能和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haichao0991

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值