上週Django
官方正式發佈了Django 3.0
版本,其中最重要的更新莫過於對ASGI
的支持。今天對Django 3.0
的異步功能作了簡單的試用,分析下過程,但願對你們有幫助。html
具體的詳細更新列表可參考官方 Django 3.0 release notes, 這裏再也不贅述,下面咱們開始。python
在開始以前咱們先來準備下環境,直接使用 Pycharm 新建一個項目,並新建虛擬環境.git
獲得以下項目:github
相比以前版本的 django 項目,多了一個asgi.py
。這即是ASGI
的服務的入口文件了,內容基本同wsgi.py
。web
在使用ASGI
特性以前,先讓咱們瞭解下,什麼是 ASGI?django
ASGI
和WSGI
,都是一種 Web 服務網關接口協議,是在CGI
的標準上構建的。瀏覽器
CGI
(通用網關接口, Common Gateway Interface),簡單來講就是解析瀏覽器等客戶端發送給服務端的請求,並組裝須要返回的 HTTP 請求的一種通用協議,處理這個過程的程序,咱們就能夠叫 CGI 腳本。互聯網早起的動態網頁都是基於CGI
標準的。緩存
WSGI
,是一種 Python 專用的 Web 服務器網關接口,它分爲兩部分"服務器(或網關)"和"應用程序(或應用框架)"。「服務器」,通常獨立於應用框架,爲應用程序運行提供環境信息和一個回調函數(Callback Function)。當應用程序完成處理請求後,透過回調函數,將結果回傳給服務器。經常使用的WSGI
服務器有: uwsgi
、gunicon
。「應用程序」,是各類實現了WSGI
標準的 Python web 框架了,經常使用的有Django
、Flask
等。bash
ASGI
(Asynchronous Server Gateway Interface)是 Django 團隊提出的一種具備異步功能的 Python web 服務器網關接口協議。可以處理多種通用的協議類型,包括 HTTP,HTTP2 和 WebSocket。WSGI
是基於 HTTP 協議模式的,不支持WebSocket
,而ASGI
的誕生則是爲了解決 Python 經常使用的 WSGI 不支持當前 Web 開發中的一些新的協議標準(WebSocket、Http2 等)。同時,ASGI
向下兼容WSGI
標準,能夠經過一些方法跑WSGI
的應用程序。經常使用的「服務器」有Daphne
、Uvicorn
。服務器
更多ASGI
資料可參考文檔
瞭解了ASGI
,咱們進入正題。關於ASGI
在Django release Notes
文檔中並無過多的介紹,只有一個部署的文檔 How to deploy with ASGI
看了下,主要說了兩種部署方式:daphne 和 uvicorn。其中"必須使用 Daphne
或Uvicorn
部署,纔會是 ASGI 服務,直接 runnerserver 是同步服務"這句給了咱們提醒,想要使用 ASGI,便不能直接 runerserver。
咱們隨便選一種使用方式,並啓動服務:
# 安裝
pip install uvicorn
# 啓動服務
uvicorn django3_demo.asgi:application
複製代碼
啓動日誌以下:
$ uvicorn django3_demo.asgi:application
INFO: Started server process [48508]
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
複製代碼
根據ASGI
的特性,能夠支持 HTTP、HTTP2 和 WebSocket。那咱們來進行下 websocket 和 http 的測試。
打開瀏覽器 console 控制檯,新建一個 websocket 連接,出現以下錯誤:
看服務錯誤以下:
INFO: Application startup complete.
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/Users/xiumin1/.local/share/virtualenvs/django3_demo/lib/python3.6/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 153, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
File "/Users/xiumin1/.local/share/virtualenvs/django3_demo/lib/python3.6/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "/Users/xiumin1/.local/share/virtualenvs/django3_demo/lib/python3.6/site-packages/django/core/handlers/asgi.py", line 146, in __call__
% scope['type']
ValueError: Django can only handle ASGI/HTTP connections, not websocket.
複製代碼
Django can only handle ASGI/HTTP connections, not websocket
,貌似 Django 的 ASGI 尚未徹底實現,僅支持 HTTP。
在瀏覽器輸入http://127.0.0.1:8000
出現了咱們熟悉的小火箭頁面。這只是簡單的啓動頁面,咱們須要寫個異步的 view 和 model 來具體操做下。
翻閱了一遍文檔,在一個小角落裏:
令我失望的找到了以下說明:
Django has developing support for asynchronous (「async」) Python, but does not yet support asynchronous views or middleware; they will be coming in a future release.
主要意思是現階段不支持異步的 view 和中間件。那也就說明無法使用 Django 原生的方式來實現ASGI
了。
到此,異步功能的試用告一段落。結論,現階段Django
原生仍是沒法徹底的支持ASGI
的服務。若是想徹底實現ASGI
服務,仍是須要 Channels
或 starlette
。
通過翻閱資料,我找到了 Django 原生異步主要推進者Andrew Godwin的一篇博客, 描述了異步功能開發的時間軸。大體以下:
從如今 3.0 發佈的功能看,實現貌似與該時間抽差了一個版本,只實現了應該到 2.2 的功能。
到這裏今天的分享就結束了。最後,仍是但願 Django 的異步功能早點來臨,到時候咱們便能直接使用 django 開發各類異步特性的功能,而沒必要安裝三方軟件。