我尝试了Django 3.0的异步服务器


前言

maxresdefault.jpg

Django 3.0于3天前正式发布。
释放节点链接
进行了如此多的更改,我对添加对ASGI,的支持非常感兴趣
我想实际使用它。 :sunny:

注意:什么是ASGI?:briefcase:

1
2
3
ASGI(非同期サーバーゲートウェイインターフェイス)は、WSGIの精神的な後継者であり、非同期対応のPython Webサーバー、フレームワーク、およびアプリケーション間の標準インターフェイスを提供することを目的としています。

WSGIが同期Pythonアプリの標準を提供したのに対し、ASGIは、WSGIの下位互換性の実装と複数のサーバーとアプリケーションフレームワークを備えた非同期アプリと同期アプリの両方を提供します。

文档链接

新项目

创建一个用于测试

的虚拟环境

1
 mkvirtualenv django3.0

安装Django

1
 pip3 install django

安装完成后,请确保您具有Django 3.0

1
2
3
4
5
6
7
8
9
10
(django3.0) ~ $ pip3 list
Package    Version
---------- -------
asgiref    3.2.3  
Django     3.0    
pip        19.3.1
pytz       2019.3
setuptools 42.0.2
sqlparse   0.3.0  
wheel      0.33.6

让我们创建一个新项目并启动服务器

1
2
3
4
5
6
7
mkdir django-test
&&
django-admin startproject newtest
&&
cd newtest/
&&
python3 manage.py runserver

您可以通过访问

8000来查看熟悉的火箭。

UNADJUSTEDNONRAW_thumb_38.jpg
到目前为止!:relaxed: :point_up:

让我们看一下官方文档

2019-12-05 19.17のイメーシ?.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
How to deploy with ASGI?
As well as WSGI, Django also supports deploying on ASGI, the emerging Python standard for asynchronous web servers and applications.

Django’s startproject management command sets up a default ASGI configuration for you, which you can tweak as needed for your project, and direct any ASGI-compliant application server to use.

Django includes getting-started documentation for the following ASGI servers:

How to use Django with Daphne
How to use Django with Uvicorn
The application object?
Like WSGI, ASGI has you supply an application callable which the application server uses to communicate with your code. It’s commonly provided as an object named application in a Python module accessible to the server.

The startproject command creates a file <project_name>/asgi.py that contains such an application callable.

It’s not used by the development server (runserver), but can be used by any ASGI server either in development or in production.

ASGI servers usually take the path to the application callable as a string; for most Django projects, this will look like myproject.asgi:application.

Warning

While Django’s default ASGI handler will run all your code in a synchronous thread, if you choose to run your own async handler you must be aware of async-safety.

Do not call blocking synchronous functions or libraries in any async code. Django prevents you from doing this with the parts of Django that are not async-safe, but the same may not be true of third-party apps or Python libraries.

Configuring the settings module?
When the ASGI server loads your application, Django needs to import the settings module — that’s where your entire application is defined.

Django uses the DJANGO_SETTINGS_MODULE environment variable to locate the appropriate settings module. It must contain the dotted path to the settings module. You can use a different value for development and production; it all depends on how you organize your settings.

If this variable isn’t set, the default asgi.py sets it to mysite.settings, where mysite is the name of your project.

Applying ASGI middleware?
To apply ASGI middleware, or to embed Django in another ASGI application, you can wrap Django’s application object in the asgi.py file. For example:

from some_asgi_library import AmazingMiddleware
application = AmazingMiddleware(application)

链接

大致归纳

  • 不要使用python manage.py runserver启动服务器,它将启动通常的wsgi服务器。

  • 我们建议在启动服务器时使用DaphneUvicorn

让我们打开官方链接,看看

Daphne是链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
How to use Django with Daphne?
Daphne is a pure-Python ASGI server for UNIX, maintained by members of the Django project. It acts as the reference server for ASGI.

Installing Daphne?
You can install Daphne with pip:

python -m pip install daphne
Running Django in Daphne?
When Daphne is installed, a daphne command is available which starts the Daphne server process. At its simplest, Daphne needs to be called with the location of a module containing an ASGI application object, followed by what the application is called (separated by a colon).

For a typical Django project, invoking Daphne would look like:

daphne myproject.asgi:application
This will start one process listening on 127.0.0.1:8000. It requires that your project be on the Python path; to ensure that run this command from the same directory as your manage.py file.

翻译
-用pip安装daphne
-运行daphne myproject.asgi:应用程序以启动ASGI服务器
-127.0.0.1:访问8000

让我们尝试:point_up:

启动ASGI服务器

达芙妮安装

1
 pip3 install daphne

启动服务器

1
daphne [プロジェクト名].asgi:application

当我访问8000时,我再次看到了火箭,尽管角色有所变化。 :eye:

2019-12-05 19.59のイメーシ?.jpg

WebSocket测试

我将打开浏览器并发送websocket消息。
UNADJUSTEDNONRAW_mini_3b.jpg

返回

500,错误消息如下。

1
2
3
4
5
6
2019-12-05 11:02:09,533 ERROR    Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
  File "/Envs/django3.0/lib/python3.7/site-packages/daphne/cli.py", line 30, in asgi
    await self.app(scope, receive, send)
  File "/Envs/django3.0/lib/python3.7/site-packages/django/core/handlers/asgi.py", line 146, in __call__
    % scope['type']
  Django can only handle ASGI/HTTP connections, not websocket.

asgi.py的第146行似乎有东西,让我们看一下。

asgi.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 async def __call__(self, scope, receive, send):
        """
        Async entrypoint - parses the request and hands off to get_response.
        """
        # Serve only HTTP connections.
        # FIXME: Allow to override this.
        if scope['type'] != 'http':
            raise ValueError(
                'Django can only handle ASGI/HTTP connections, not %s.'
                % scope['type']
            )
        # Receive the HTTP request body as a stream object.
        try:
            body_file = await self.read_body(receive)
        except RequestAborted:
            return
        # Request is complete and can be served.
        set_script_prefix(self.get_script_prefix(scope))

注意下面的两行注释。

1
2
 # Serve only HTTP connections.
 # FIXME: Allow to override this.

目前,仅允许http通信。如有必要,请自行修复!

持续

可能的原因如下。

  • 也许我再也不了解Django
  • 通过Websocket以外的其他方式实现ASGI通信
  • 尚未完全支持ASGI

当前Django3.0,如果要使用websocket,建议使用django-channel软件包。