原作:Valentino Gagliardi
翻译:大江狗。翻译时有删减。
原文链接:https://www.valentinog.com/blog/uvicorn-django/
Django 3.1终于支持异步视图了。这意味者我们可以在Django视图中使用async/await执行异步任务了。
async def index(request):
res = await do_stuff_async()
# return your view
如果你希望充分享受到异步视图的好处,我们需要使用ASGI服务器比如Daphne, Uvicorn或者Hypercorn来启动Django服务。本例中我们将使用Uvicorn和Nginx在生产环境中部署Django。
项目设置
本例中我们用到:
-
Nginx:Nginx作为反向代理和静态文件服务器
-
Uvicorn和Gunicorn:Uvicorn作为ASGI服务器,并使用Gunicorn管理。
项目依赖
本项目需要用到如下依赖,可以使用pip安装,建议安装到虚拟环境中。请同时确保Python版本在3.7以上。
django==3.1.1
gunicorn==20.0.4
uvicorn==0.12.0
httptools==0.1.1
uvloop==0.14.0
Nginx的安装与配置
首先你需要在你的服务器上安装nginx,然后对它进行配置。Nginx的安装很简单,我们这里就不详述了。在本例中Nginx将作为Uvicorn/Gunicorn服务的反向代理,意思是客户端用户发来的请求先经过nginx,再由nginx对请求进行转发,动态请求转发至Uvicorn/Gunicorn服务,静态请求转发到静态文件服务器或者自己处理静态请求。
通常情况下你需要创建或修改一个如/etc/nginx/conf.d/my-domain.conf的nginx配置文件,添加如下配置:
upstream backend {
server 127.0.0.1:8000;
# There could be more than a backend here
}
server {
server_name my-domain.com;
location / {
proxy_pass http://backend;
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-Proto $scheme;
}
}
当你使用UWSGI启动传统django服务时,你还可以使用uwsgi_pass转发请求。但本例中我们使用的是异步ASGI服务器,所以只能使用proxy_pass进行请求转发。
修改配置文件后,可以使用如下命令检查你的配置是否正确:
nginx -t
然后重启nginx服务:
systemctl reload nginx
使用Uvicorn启动Django服务
Django 3.1后创建的项目的典型目录结构如下所示:
├── app1
├── app2
├── app3
├── project_name
│ ├── asgi.py
│ ├── __init__.py
├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
假如你的项目名为project_name,该文件夹下会同时有asgi.py和uwsgi.py两个文件。如果你的uvicorn和gunicorn已经安装好,进入虚拟环境,终端输入如下命令即可使用异步服务器uvicorn启动django服务了。
gunicorn project_name.asgi:application -w 2 -k uvicorn.workers.UvicornWorker --log-file -
如果上面操作一切顺利,访问127.0.0.1:8000,你将看终端上有如下输出:
[2020-10-02 11:51:25 +0200] [10059] [INFO] Starting gunicorn 20.0.4
[2020-10-02 11:51:25 +0200] [10059] [INFO] Listening at: http://127.0.0.1:8000 (10059)
[2020-10-02 11:51:25 +0200] [10059] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-10-02 11:51:25 +0200] [10061] [INFO] Booting worker with pid: 10061
[2020-10-02 11:51:25 +0200] [10062] [INFO] Booting worker with pid: 10062
[2020-10-02 09:51:26 +0000] [10061] [INFO] Started server process [10061]
[2020-10-02 09:51:26 +0000] [10061] [INFO] Waiting for application startup.
[2020-10-02 09:51:26 +0000] [10061] [INFO] ASGI 'lifespan' protocol appears unsupported.
[2020-10-02 09:51:26 +0000] [10061] [INFO] Application startup complete.
[2020-10-02 09:51:26 +0000] [10062] [INFO] Started server process [10062]
[2020-10-02 09:51:26 +0000] [10062] [INFO] Waiting for application startup.
[2020-10-02 09:51:26 +0000] [10062] [INFO] ASGI 'lifespan' protocol appears unsupported.
[2020-10-02 09:51:26 +0000] [10062] [INFO] Application startup complete.
注:这里-w代表worker的数量,一般等于CPU的核数。
对Uvicorn服务进行持久化
把Uvicorn服务设置成开机启动,我们需要创建一个systemd文件。假设我们服务名称为django0, 那么文件所在位置在/etc/systemd/system/django0.service
[Unit]
Description=django0 uvicorn daemon
After=network.target
[Service]
Environment=DJANGO_SETTINGS_MODULE=project_name.settings
User=django0
Group=django0
WorkingDirectory=/home/django0/repo_root
ExecStart=/home/django0/repo_root/venv/bin/gunicorn project_name.asgi:application -w 2 -k uvicorn.workers.UvicornWorker --log-file -
[Install]
WantedBy=multi-user.target
文件创建好后,可以使用如下命令检查服务状态。
systemctl status django0
这时你将看到:
django0.service - django0 uvicorn daemon
Loaded: loaded (/etc/systemd/system/django0.service; disabled; vendor preset: disabled)
Active: inactive (dead)
接下来正式启动服务:
systemctl enable django0
如果你对django配置文件settings.py进行了任何修改,可以使用如下命令重启服务即可。
systemctl restart django0
完成!使用Nginx和Uvicorn在生产环境部署Django项目就完成了, 是不是很简单?
原文地址:
https://www.valentinog.com/blog/uvicorn-django/
小编注:
翻译本文时删掉了原文关于postgres的安装,使用django-environ设置settings.py等不相关部分。
更多阅读
如何在阿里云Ubuntu服务器通过uWSGI和Nginx部署Django项目教程-大江狗原创出品