Django中如何使用Channels功能
前言:最近后臺(tái)寫游戲更新版本功能,簡(jiǎn)單就是前端發(fā)送更新請(qǐng)求,后端需要對(duì)很多臺(tái)服務(wù)器進(jìn)行更新和各種操作,本來想著實(shí)現(xiàn)不難,后來發(fā)現(xiàn)因?yàn)楹蠖诵枰獔?zhí)行很長(zhǎng)時(shí)間,前端返回報(bào)錯(cuò),后端會(huì)執(zhí)行完畢,但是前端先斷開了,這樣在前端頁(yè)面我就看不到更新結(jié)果了。通過調(diào)整nginx參數(shù),設(shè)置超時(shí)時(shí)間,還是日志會(huì)報(bào)499狀態(tài)碼錯(cuò)誤。后來了解到了websocket,對(duì)于需要長(zhǎng)時(shí)間處理的請(qǐng)求,使用websocket會(huì)更好,通過使用websocket實(shí)現(xiàn)了自己的功能,簡(jiǎn)單分享下
一、什么是WebSocket
WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通訊的協(xié)議。WebSocket允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。
在WebSocket協(xié)議中,客戶端瀏覽器和服務(wù)器只需要完成一次握手就可以創(chuàng)建持久性的連接,并在瀏覽器和服務(wù)器之間進(jìn)行雙向的數(shù)據(jù)傳輸。
WebSocket的響應(yīng)頭中重要的字段:
HTTP/1.1 101 Swi tching Protocols:切換協(xié)議,WebSocket協(xié)議通過HTTP協(xié)議來建立運(yùn)輸層的TCP連接
Connection和Upgrade:表示服務(wù)端發(fā)起的WebSocket響應(yīng)
Sec-WebSocket-Accept:表示服務(wù)器接受了客戶端的請(qǐng)求,由Sec-WebSocket-Key計(jì)算得來
WebSocket協(xié)議的優(yōu)點(diǎn):
支持雙向通信,實(shí)時(shí)性更強(qiáng)
數(shù)據(jù)格式比較輕量,性能開銷小,通信高效
支持?jǐn)U展,用戶可以擴(kuò)展協(xié)議或者實(shí)現(xiàn)自定義的子協(xié)議(比如支持自定義壓縮算法等)
WebSocket協(xié)議的缺點(diǎn):
少部分瀏覽器不支持,瀏覽器支持的程度與方式有區(qū)別
長(zhǎng)連接對(duì)后端處理業(yè)務(wù)的代碼穩(wěn)定性要求更高,后端推送功能相對(duì)復(fù)雜
成熟的HTTP生態(tài)下有大量的組件可以復(fù)用,WebSocket較少
WebSocket的應(yīng)用場(chǎng)景:
即時(shí)聊天通信,網(wǎng)站消息通知
在線協(xié)同編輯,如騰訊文檔
多玩家在線游戲,視頻彈幕,股票基金實(shí)施報(bào)價(jià)
二、什么是Channels
Django本身不支持WebSocket,但可以通過集成Channels框架來實(shí)現(xiàn)WebSocket
Channels是針對(duì)Django項(xiàng)目的一個(gè)增強(qiáng)框架,可以使Django不僅支持HTTP協(xié)議,還能支持WebSocket,MQTT等多種協(xié)議,同時(shí)Channels還整合了Django的auth以及session系統(tǒng)方便進(jìn)行用戶管理及認(rèn)證。
2.1channels文件和配置的含義
asgi.py:介于網(wǎng)絡(luò)協(xié)議服務(wù)和Python應(yīng)用之間的接口,能夠處理多種通用協(xié)議類型,包括HTTP、HTTP2和WebSocket
channel_layers:在settings.py中配置。類似于一個(gè)通道,發(fā)送者(producer)在一段發(fā)送消息,消費(fèi)者(consumer)在另一端進(jìn)行監(jiān)聽
routings.py:相當(dāng)于Django中的urls.py
consumers.py:相當(dāng)于Django中的views.py
2.2channels文檔鏈接
https://channels.readthedocs.io/en/latest/introduction.html
2.3.WSGI和ASGI不同
WSGI(Python Web Server Gateway Interface):為Python語言定義的Web服務(wù)器和Web應(yīng)用程序或者框架之間的一種簡(jiǎn)單而通用的接口。
ASGI(Asynchronous Web Server Gateway Interface):異步網(wǎng)關(guān)協(xié)議接口,一個(gè)介于網(wǎng)絡(luò)協(xié)議服務(wù)和Python應(yīng)用之間的標(biāo)準(zhǔn)接口,能夠處理多種通用的協(xié)議類型,包括HTTP,HTTP2和WebSocket。
三、Django中使用Channel
3.1安裝channels
pip install channels==2.1.7
3.2修改setting.py文件
INSTALLED_APPS = [ 'django.contrib.staticfiles', ... ... 'channels', ] # 指定ASGI的路由地址 ASGI_APPLICATION = 'webapp.routing.application' #ASGI_APPLICATION 指定主路由的位置為webapp下的routing.py文件中的application
3.3setting.py的同級(jí)目錄下創(chuàng)建routing.py路由文件,routing.py類似于Django中的url.py指明websocket協(xié)議的路由
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter from channels.security.websocket import AllowedHostsOriginValidator import webapp.routing application = ProtocolTypeRouter({ 'websocket':AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter( webapp.routing.websocket_urlpatterns ) ) ) })
ProtocolTypeRouter:ASGI支持多種不同的協(xié)議,在這里可以指定特定協(xié)議的路由信息,這里只使用了websocket協(xié)議,這里只配置websocket即可
AllowedHostsOriginValidator:指定允許訪問的IP,設(shè)置后會(huì)去Django中的settings.py中去查找ALLOWED_HOSTS設(shè)置的IP
AuthMiddlewareStack:用于WebSocket認(rèn)證,繼承了Cookie Middleware,SessionMiddleware,SessionMiddleware。
django的channels封裝了django的auth模塊,使用這個(gè)配置我們就可以在consumer中通過下邊的代碼獲取到用戶的信息,和請(qǐng)求的url路徑
self.sc
def connect(self): self.user = self.scope["user"] self.request_url = self.scope['path']
ope類似于django中的request,包含了請(qǐng)求的type、path、header、cookie、session、user等等有用的信息
URLRouter: 指定路由文件的路徑,也可以直接將路由信息寫在這里,代碼中配置了路由文件的路徑,會(huì)去對(duì)應(yīng)應(yīng)用下的routeing.py文件中查找websocket_urlpatterns
3.4webapp.routing.py內(nèi)容如下
from django.urls import path from webapp.consumers import ChatConsumer websocket_urlpatterns = [ path('ws/chat/',ChatConsumer) ]
routing.py路由文件跟django的url.py功能類似,語法也一樣,意思就是訪問ws/chat/都交給ChatConsumer處理。
3.5在要使用WebSocket的應(yīng)用中創(chuàng)建consumers.py,consumers.py是用來開發(fā)ASGI接口規(guī)范的python應(yīng)用,而Django中的view.py是用來開發(fā)符合WSGI接口規(guī)范的python應(yīng)用?! ?/p>
from channels.generic.websocket import WebsocketConsumer from channels.generic.websocket import AsyncWebsocketConsumer import json,time
Channels支持同步,也支持異步方式
同步方式代碼如下:
class ChatConsumer(WebsocketConsumer): # websocket建立連接時(shí)執(zhí)行方法 def connect(self): self.accept() # websocket斷開時(shí)執(zhí)行方法 def disconnect(self, close_code): self.close() # 從websocket接收到消息時(shí)執(zhí)行函數(shù) def receive(self, text_data): text_data_json = json.loads(text_data) message = f'結(jié)果:{text_data_json}' self.send(text_data=json.dumps( { 'message': message }))
異步方式代碼如下:
class ChatConsumer(AsyncWebsocketConsumer): #websocket建立連接時(shí)執(zhí)行方法 async def connect(self): await self.accept() # websocket斷開時(shí)執(zhí)行方法 async def disconnect(self, close_code): print(close_code) # 從websocket接收到消息時(shí)執(zhí)行函數(shù) async def receive(self, text_data): for i in range(10): time.sleep(i) message = '結(jié)果: ' + str(i) await self.send(text_data=json.dumps({ 'message': message }) )
需要注意的是在異步中所有的邏輯都應(yīng)該是異步的,不可以那同步的和異步的代碼混合使用?! ?/p>
四、前端Websocket使用
WebSocket對(duì)象一個(gè)支持四個(gè)消息:onopen,onmessage,oncluse和onerror
onopen: 當(dāng)瀏覽器和websocket服務(wù)端連接成功后會(huì)觸發(fā)onopen消息
onerror: 如果連接失敗,或者發(fā)送、接收數(shù)據(jù)失敗,或者數(shù)據(jù)處理出錯(cuò)都會(huì)觸發(fā)onerror消息
onmessage: 當(dāng)瀏覽器接收到websocket服務(wù)器發(fā)送過來的數(shù)據(jù)時(shí),就會(huì)觸發(fā)onmessage消息,參數(shù)e包含了服務(wù)端發(fā)送過來的數(shù)據(jù)
onclose: 當(dāng)瀏覽器接收到websocket服務(wù)器發(fā)送過來的關(guān)閉連接請(qǐng)求時(shí),會(huì)觸發(fā)onclose消息
拼接websocket請(qǐng)求地址,建立長(zhǎng)連接
var chatSocket = new WebSocket('ws://' + window.location.host + '/ws/ver_update/');
連接事件
chatSocket.onopen = function () { console.log(getCurrentDate(2) + ' ' + 'websocket connection success') };
錯(cuò)誤事件
chatSocket.onerror = function () { console.error(getCurrentDate(2) + ' ' + 'websocket connection error') };
關(guān)閉事件
chatSocket.onclose = function (e) { layer.msg('websocket關(guān)閉,檢查錯(cuò)誤日志', {icon: 2}); console.error(getCurrentDate(2) + ' ' + 'websocket closed unexpectedly 狀態(tài)碼:' + e.code); chatSocket.close(); };
接收事件
chatSocket.onmessage = function (e) { var data = JSON.parse(e.data); }
五、測(cè)試Channels功能
總結(jié):自從使用Websocket功能后,再也沒發(fā)生前端突然斷開的情況了,對(duì)于長(zhǎng)時(shí)間運(yùn)行的任務(wù),使用websocket是不錯(cuò)的選擇~,有不足的地方請(qǐng)多多指教
到此這篇關(guān)于Django中使用Channels功能的文章就介紹到這了,更多相關(guān)Django使用Channels內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Django實(shí)現(xiàn)WebSocket在線聊天室功能(channels庫(kù))
- Django使用channels + websocket打造在線聊天室
- django使用channels實(shí)現(xiàn)通信的示例
- 淺談django channels 路由誤導(dǎo)
- 詳解Django-channels 實(shí)現(xiàn)WebSocket實(shí)例
- Django使用Channels實(shí)現(xiàn)WebSocket的方法
- Django Channels 實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)實(shí)時(shí)聊天和消息推送功能
- django使用channels2.x實(shí)現(xiàn)實(shí)時(shí)通訊
- django channels使用和配置及實(shí)現(xiàn)群聊
相關(guān)文章
python初學(xué)者,用python實(shí)現(xiàn)基本的學(xué)生管理系統(tǒng)(python3)代碼實(shí)例
這篇文章主要介紹了用python實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04python+influxdb+shell編寫區(qū)域網(wǎng)絡(luò)狀況表
這篇文章主要為大家詳細(xì)介紹了python+influxdb+shell編寫區(qū)域網(wǎng)絡(luò)狀況表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Python使用內(nèi)置函數(shù)setattr設(shè)置對(duì)象的屬性值
這篇文章主要介紹了Python使用內(nèi)置函數(shù)setattr設(shè)置對(duì)象的屬性值,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Python實(shí)現(xiàn)讀取csv文件并進(jìn)行排序
這篇文章主要為大家詳細(xì)介紹了一個(gè)python簡(jiǎn)單案例并進(jìn)行代碼展示,本文的案例是利用pandas庫(kù)實(shí)現(xiàn)讀取csv文件并按照列的從小到大進(jìn)行排序,需要的可以參考一下2023-02-02Python如何通過ARIMA模型進(jìn)行時(shí)間序列分析預(yù)測(cè)
這篇文章主要介紹了Python如何通過ARIMA模型進(jìn)行時(shí)間序列分析預(yù)測(cè)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02python 限制函數(shù)執(zhí)行時(shí)間,自己實(shí)現(xiàn)timeout的實(shí)例
今天小編就為大家分享一篇python 限制函數(shù)執(zhí)行時(shí)間,自己實(shí)現(xiàn)timeout的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01pycharm中虛擬環(huán)境venv簡(jiǎn)介以及實(shí)踐指南
這篇文章主要給大家介紹了關(guān)于pycharm中虛擬環(huán)境venv簡(jiǎn)介以及實(shí)踐的相關(guān)資料,虛擬環(huán)境是利用了操作系統(tǒng)中環(huán)境變量,以及進(jìn)程間環(huán)境隔離的特性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10Python?matplotlib設(shè)置多子圖、子圖間距及外邊距的幾種方式
子圖是Matplotlib中強(qiáng)大的功能之一,使用函數(shù)您可以方便地創(chuàng)建多個(gè)子圖,并使用Axes對(duì)象繪制各種圖形,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib設(shè)置多子圖、子圖間距及外邊距的幾種方式,需要的朋友可以參考下2024-02-02