Django实现websocket
Django实现websocket
- WebSocket功能
- 使用介绍
- 安装
- 配置
- WebSocket接口--消息接收者的实现
- scope
- 通道层 channel layer
- 部署
- Web客户端连接
- Mac客户端
WebSocket功能
WebSocket长连接一般用于实现实时功能,例如web端的消息通知、会话等场景。
使用 WebSocket 向 Django 项目添加实时功能,一般有两个选择:
-
使用 Django Channels,这是一个向 Django 添加 WebSocket 等功能的项目。 Django 完全支持这种方法。 但是,它需要切换到新的部署架构;
-
在 Django 项目旁边部署一个单独的 WebSocket 服务。
方法2的实现一般可以借助 django-sesame 去管理会话的鉴权,本文不做过多阐述,可以点击参考链接,下面组要介绍方法1中Channels在Django中的使用。
关于Channels:
- 源码地址 https://github.com/django/channels
- 文档介绍 https://channels.readthedocs.io/en/latest/
使用介绍
安装
pip install -U 'channels[daphne]'
需要使用daphne,是为了后续部署用于启动ASGI1服务。当然,若是你有其他的部署方式你可以仅安装channels。
配置
安装完后,需要在INSTALLED_APPS配置中添加:
INSTALLED_APPS = ("daphne","django.contrib.auth","django.contrib.contenttypes","django.contrib.sessions","django.contrib.sites",...
)ASGI_APPLICATION = "mysite.asgi.application"
注意:
ASGI_APPLICATION配置后正常可通过python manage.py runserver启动服务,低版本Django不行,Django 5.x 版本可行。
添加文件 myproject/asgi.py
from django.core.asgi import get_asgi_application
from django.urls import re_path# Initialize Django ASGI application early to ensure the AppRegistry
# is populated before importing code that may import ORM models.
django_asgi_app = get_asgi_application()from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidatorapplication = ProtocolTypeRouter({# 同时能支持原有http协议的接口"http": django_asgi_app,# 增加websocket协议的支持"websocket": AllowedHostsOriginValidator(AuthMiddlewareStack(# 接口路由URLRouter([re_path(r"^chat/(?P<room_name>\w+)/$", consumers.ChatConsumer.as_asgi()),]))),
})
WebSocket接口–消息接收者的实现
接口实现可以继承WebsocketConsumer / AsyncConsumer / AsyncConsumer,此处介绍WebsocketConsumer,代码示例:
class ChatConsumer(WebsocketConsumer):def connect(self):# django框架会自动处理websocket链接带上的headers信息进行鉴权认证,初始化成用户对象self.user = self.scope['user']self.accept()self.send(text_data="[Welcome %s!]" % self.user.username)def receive(self, *, text_data):if text_data.startswith("/name"):username = text_data[5:].strip()self.send(text_data="[set your username to %s]" % username)else:self.send(text_data=username + ": " + text_data)def disconnect(self, message):pass
值的一提的是,Django框架和Channels结合很好,Auth体系完全兼容,Django http中的header这里也能识别成User用户。
scope
Consumer接受到client端发来的websocket请求后,会将请求信息初始化成scope,请求相关信息可以从self.scope中获取,例如:
scope["client"]client来源ip和port, eg:['127.0.0.1', 6533]scope["user"]根据headers等信息初始化的User用户scope["path"]请求接口path路径scope["query_string"]连接上的query参数scope["headers"]请求headersscope["url_route"]请求path定义路由解析出的参数,eg:{"args": {}, "kwargs": {"pk": 1}}
以上的介绍算是基本实现了一个简单的websoket服务。
若是实现较为复杂的群聊、或者广播通知该如何实现?下面 channel layer 。
通道层 channel layer
安装pip install channels_redis
通道层是一种通信系统。 它允许多个消费者实例相互通信以及与 Django 的其他部分通信。
通道层提供以下抽象:
- 通道是一个可以发送消息的邮箱。 每个频道都有一个名称。 知道频道名称的任何人都可以向该频道发送消息。
- 组是一组相关的通道。 一个团体有一个名字。 任何拥有群组名称的人都可以通过名称向群组添加/删除频道,并向群组中的所有频道发送消息。 不可能枚举特定组中有哪些频道。
每个消费者实例都有一个自动生成的唯一通道名称,因此可以通过通道层进行通信。
需要在Django settings.py 文件中添加配置
# Channels
ASGI_APPLICATION = "mysite.asgi.application"
CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer","CONFIG": {"hosts": [("127.0.0.1", 6379)],},},
}
接口代码实现
# chat/consumers.py
import jsonfrom asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumerclass ChatConsumer(WebsocketConsumer):def connect(self):# 这里是将群名room_name定义在了path中,通过正则提取self.room_name = self.scope["url_route"]["kwargs"]["room_name"]self.room_group_name = f"chat_{self.room_name}"# Join room groupasync_to_sync(self.channel_layer.group_add)(self.room_group_name, self.channel_name)self.accept()def disconnect(self, close_code):# Leave room groupasync_to_sync(self.channel_layer.group_discard)(self.room_group_name, self.channel_name)# Receive message from WebSocketdef receive(self, text_data):text_data_json = json.loads(text_data)message = text_data_json["message"]# Send message to room groupasync_to_sync(self.channel_layer.group_send)(self.room_group_name, {"type": "chat.message", "message": message})# Receive message from room groupdef chat_message(self, event):message = event["message"]# Send message to WebSocketself.send(text_data=json.dumps({"message": message}))
部署
服务启动 daphne -b 0.0.0.0 -p 8000 myproject.asgi:application
其他参数可以查看 daphne文档 。
websocket协议nginx代理示例配置如下:
upstream channels-backend {server localhost:8000;
}
...
server {...location / {try_files $uri @proxy_to_app;}...location @proxy_to_app {proxy_pass http://channels-backend;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";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-Host $server_name;}...
}
Web客户端连接
前端JS可以通过 WebSocket 实现连接,注意浏览器兼容问题即可。
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8000/chat/room/");// Connection opened
socket.addEventListener("open", function (event) {socket.send("Hello Server!");
});// Listen for messages
socket.addEventListener("message", function (event) {console.log("Message from server ", event.data);
});
Mac客户端
借助工具 websocat , 可通过 brew install websocat 安装。
websocat ws://localhost:8000/chat/room/
# 加header
websocat -H="Authorization: Token xxxx" ws://localhost:8000/chat/room/
需要注意的是,
-H=""中间等号不能用空格替代,否则无法生效,希望作者在之后的版本中个可以兼容这个问题。
可以关注下Django框架中提供的WSGI和ASGI的区别; ↩︎
相关文章:
Django实现websocket
Django实现websocket WebSocket功能使用介绍安装配置WebSocket接口--消息接收者的实现scope通道层 channel layer部署Web客户端连接Mac客户端 WebSocket功能 WebSocket长连接一般用于实现实时功能,例如web端的消息通知、会话等场景。 使用 WebSocket 向 Django 项…...
先进制造aps专题九 中国aps行业分析
国外aps的问题是不给国内客户定制算法 国外aps的算法都很强大,考虑几百个约束条件,各种复杂的工序关系,还有副资源约束特殊规格约束,排程还优化,光c写的算法代码就几十万行甚至上百万行 国内aps的问题是实现不了复杂的…...
力扣hot100:23. 合并 K 个升序链表
23. 合并 K 个升序链表 这题非常容易想到归并排序的思路,俩升序序列合并,可以使用归并的方法。 不过这里显然是一个多路归并排序;包含多个子数组的归并算法,这可以让我们拓展归并算法的思路。 假设n是序列个数,ni是…...
Lightweight Robust Size Aware Cache Management——论文泛读
TOC 2022 Paper 论文阅读笔记整理 问题 现代键值存储、对象存储、互联网代理缓存和内容交付网络(CDN)通常管理不同大小的对象,例如,Blob、不同长度的视频文件、不同分辨率的图像和小文件。在这种工作负载中,大小感知…...
搜索自动补全-elasticsearch实现
1. elasticsearch准备 1.1 拼音分词器 github地址:https://github.com/infinilabs/analysis-pinyin/releases?page6 必须与elasticsearch的版本相同 第四步,重启es docker restart es1.2 定义索引库 PUT /app_info_article {"settings": …...
连接远程的kafka【linux】
# 连接远程的kafka【linux】 前言版权推荐连接远程的kafka【linux】一、开放防火墙端口二、本地测试是否能访问端口三、远程kafka配置四、开启远程kakfa五、本地测试能否连接远程六、SpringBoot测试连接 遇到的问题最后 前言 2024-5-14 18:45:48 以下内容源自《【linux】》 仅…...
简单的 Cython 示例
1, pyx文件 fibonacci.pyx def fibonacci_old(n):if n < 0:return 0elif n 1:return 1else:return fibonacci_old(n-1) fibonacci_old(n-2) 2,setup.py setup.py from setuptools import setup from Cython.Build import cythonizesetup(ext_mod…...
Laravel时间处理类Carbon
时间和日期处理是非常常见的任务。Carbon 是一个功能强大的 PHP 扩展包,它为我们提供了许多方便的方法来处理日期和时间。在 Laravel 中,你无需单独安装 Carbon,因为 Laravel 默认已经包含了它。如果你正在使用 Laravel,那么你已经…...
2024年5月软考架构题目回忆分享
十年架构两茫茫 ,Redis , UML 夜来幽梦忽还乡 , 大数据, Lambda 选择题 1.需求分析和架构设计面临这两个不同对象,一个是问题空间,一个是解空间 这是英文题,总共五个题目,只记得这么多 2. …...
香橙派 AIpro开发板初上手
一、香橙派 AIpro开箱 最近拿到了香橙派 AIpro(OrangePi AIpro),下面就是里面的板子和相关的配件。包含主板、散热组件、电源适配器、双C口电源线、32GB SD卡。我手上的这个是8G LPDDR4X运存的版本。 OrangePi AIpro开发板是一款由香橙派与华…...
如何使用DotNet-MetaData识别.NET恶意软件源码文件元数据
关于DotNet-MetaData DotNet-MetaData是一款针对.NET恶意软件的安全分析工具,该工具专为蓝队研究人员设计,可以帮助广大研究人员轻松识别.NET恶意软件二进制源代码文件中的元数据。 工具架构 当前版本的DotNet-MetaData主要由以下两个部分组成…...
LeetCode---栈与队列
232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元素int pee…...
【教程】利用API接口添加本站同款【每日新闻早早报】-每天自动更新,不占用文章数量
本次分享的是给网站添加一个每日早报的文章,可以看到本站置顶上面还有一个日更的日报,这是利用ALAPI的接口完成的!利用接口有利也有弊,因为每次用户访问网站的时候就会增加一次API接口请求,导致文章的请求会因为请求量…...
僵尸进程,孤儿进程,守护进程
【一】僵尸进程 1.僵尸进程是指完成自己的任务之后,没有被父进程回收资源,占用系统资源,对计算机有害,应该避免 """ 所有的子进程在运行结束之后都会变成僵尸进程(死了没死透)还保留着pid和一些运行过程的中的记录便于主进程查看(短时间…...
Nuxt3 中使用 ESLint
# 快速安装 使用该命令安装的同时会给依赖、内置模块同时更新 npx nuxi module add eslint安装完毕后,nuxt.config.ts 文件 和 package.json 文件 会新增代码段: # nuxt.config.ts modules: ["nuxt/eslint" ] # package.json "devDep…...
【Jmeter】性能测试之压测脚本生成,也可以录制接口自动化测试场景
准备工作-10分中药录制HTTPS脚本,需配置证书 准备工作-10分中药 以https://www.baidu.com/这个地址为录制脚本的示例。 录制脚本前的准备工作当然是得先把Jmeter下载安装好、JDK环境配置好、打开Jmeter.bat,打开cmd,输入ipconfig,…...
Go 编程技巧:零拷贝字符串与切片转换的高效秘籍
前言 在深入探讨Go语言中字符串与切片类型转换的高效方法之前,让我们先思考一个关键问题:如何在不进行内存拷贝的情况下,实现这两种数据类型之间的无缝转换?本文将详细解析Go语言中字符串(字符类型)和切…...
音视频开发—FFmpeg 音频重采样详解
音频重采样(audio resampling)是指改变音频信号的采样率的过程。采样率(sample rate)是指每秒钟采集的音频样本数,通常以赫兹(Hz)或每秒样本数(samples per second)表示。…...
统计本地端口占用情况
要查看MongoDB是否正在备份,可以通过以下几种方法: 查看MongoDB的进程列表: 使用命令ps -ef | grep mongo,这将列出所有正在运行的MongoDB进程。在输出的列表中,你可以查看是否有与备份相关的进程或任务正在运行。 查…...
【MySQL精通之路】SQL优化(1)-查询优化(9)-外部联接优化
主博客: 【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客 上一篇: 【MySQL精通之路】SQL优化(1)-查询优化(8)-嵌套联接优化-CSDN博客 下一篇: 【MySQL精通之路】SQL优化(1)-查询优化(10)-外部联接简化-CSDN博客 外部联接包括LEFT JOIN和…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
