一代版本一代神:利用Docker在Win10系统极速体验Django3.1真实异步(Async)任务
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_177

就在去年(2019年),Django官方发布3.0版本,内核升级宣布支持Asgi,这一重磅消息让无数后台研发人员欢呼雀跃,弹冠相庆。大喜过望之下,小伙伴们兴奋的开箱试用,结果却让人大跌眼镜:非但说好的内部集成Websocket没有出现,就连原生的异步通信功能也只是个壳子,内部并未实现,很明显的换汤不换药,这让不少人转身投入了FastAPI的怀抱。不过一年之后,今天8月,Django3.1版本姗姗来迟,这个新版本终于一代封神,不仅支持原生的异步视图,同时也支持异步中间件,明显整了个大活。

本次我们利用Docker制作一款基于Django3.1.1的项目镜像,实际体验一下Django原生异步的魅力。

首先在宿主机安装新版Django

pip install Django==3.1.1

新建一个项目,名字为django31

django-admin.py startproject django31 .

进入项目目录可以发现,熟悉的入口文件mange.py已经消失不见,新增了asgi.py文件用来启动项目,这里我们使用异步服务器uvicorn来启动新版Django,而uvicorn对windows系统支持不够友好,所以使用Docker来构建一个运行镜像,简单方便,进入django31目录,新建Dockerfile:

FROM python:3.7
WORKDIR /Project/django31 COPY requirements.txt ./
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . .
ENV LANG C.UTF-8
WORKDIR /Project
CMD ["uvicorn", "django31.asgi:application","--host","0.0.0.0"]

这里需要注意一点,Docker每创建一个容器,会在iptables中添加一个规则,每个容器都会在本机127.17.X.X范围内分配一个地址,容器绑定的主机端口会映射到本机的127.17.X.X的容器抛出端口上。所以容器内部的项目绑定的ip不能是127.0.0.1,要绑定为0.0.0.0,这样绑定后容器内部app的实际ip由Docker自动分配,所以这里uvicorn启动参数需要用host强制绑定为0.0.0.0。

随后在项目中创建依赖文件requirements.txt:

django==3.1.1
uvicorn
httpx

开始编译镜像文件:

docker build -t 'django31' .

编译成功后大概1g左右

liuyue:django31 liuyue$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
django31 latest e8afbbbb9305 30 minutes ago 919MB

然后我们来启动项目:

docker run -it --rm -p 8000:8000 django31

后台显示启动顺利,绑定在容器内的0.0.0.0:

liuyue:django31 liuyue$ docker run -it --rm -p 8000:8000 django31
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

浏览器访问:http://localhost:8000

熟悉的小火箭又起飞了,接下来我们来编写第一个异步视图views.py

from django.http import HttpResponse
async def index(request):
return HttpResponse("异步视图")

修改一下路由文件urls.py

from django.contrib import admin
from django.urls import path
from django31.views import index urlpatterns = [
path('admin/', admin.site.urls),
path("", index)
]

重新编译镜像:

docker build -t 'django31' .
docker run -it --rm -p 8000:8000 django31

访问http://localhost:8000

没有问题,还记得去年我们曾经使用Siege对Django2.0版本进行压力测试吗?现在我们再来测一下

siege -c150 -t60S -v -b 127.0.0.1:8000

150个并发持续一分钟,看看新版Django的抗压能力怎么样:

liuyue:~ liuyue$ siege -c150 -t60S -v -b 127.0.0.1:8000  

{	"transactions":			       10517,
"availability": 100.00,
"elapsed_time": 59.70,
"data_transferred": 0.12,
"response_time": 0.84,
"transaction_rate": 176.16,
"throughput": 0.00,
"concurrency": 148.58,
"successful_transactions": 10517,
"failed_transactions": 0,
"longest_transaction": 1.13,
"shortest_transaction": 0.45
}
liuyue:~ liuyue$

从测试结果看,整体性能虽然没有质的提高,但是也还算是差强人意,乞丐级主机在uvicorn的加持下单机200个左右并发还是能抗住的。

接下来我们来体验一下真正的技术,Django内置的原生异步任务,分别同步和异步两种方式使用httpx来请求接口,方法中人为的阻塞10秒钟:



from django.http import HttpResponse  

import asyncio
from time import sleep
import httpx #异步请求
async def http_call_async():
for num in range(10):
await asyncio.sleep(1)
print(num)
async with httpx.AsyncClient() as client:
r = await client.get("https://v3u.cn")
print(r) #同步请求
def http_call_sync():
for num in range(10):
sleep(1)
print(num)
r = httpx.get("https://v3u.cn")
print(r)

再分别通过同步和异步视图进行调用:

async def async_view(request):
loop = asyncio.get_event_loop()
loop.create_task(http_call_async())
return HttpResponse("非阻塞视图") def sync_view(request):
http_call_sync()
return HttpResponse("阻塞视图")

修改路由:

from django.contrib import admin
from django.urls import path
from django31.views import index, async_view, sync_view urlpatterns = [
path('admin/', admin.site.urls),
path("", index),
path("async/", async_view),
path("sync/", sync_view),
]

重新编译:

docker build -t 'django31' .
docker run -it --rm -p 8000:8000 django31

访问 http://localhost:8000/sync/ 看看同步的效率

很明显过程中阻塞了10秒,然后我们才等到页面结果:

再来试试不一样的,访问http://localhost:8000/async/

16毫秒,无视阻塞,瞬间响应。

通过动图我们可以发现,后端还在执行阻塞任务,但是前段已经通过异步多路复用将请求任务结果返回至浏览器了。

虽然这已经很不错了,但是稍有遗憾的是,目前Django内置的ORM还是同步机制,也就是说当我们读写数据库的时候还是阻塞状态,此时的场景就是异步视图内塞入了同步操作,这该怎么办呢?可以使用内置的sync_to_async方法进行转化:

from asgiref.sync import sync_to_async
async def async_with_sync_view(request):
loop = asyncio.get_event_loop()
async_function = sync_to_async(http_call_sync)
loop.create_task(async_function())
return HttpResponse("(via sync_to_async)")

由此可见,Django3.1在异步层面真的开始秀操作了,这就带来另外一个问题,既然原生异步任务已经做得这么牛逼了,我们到底还有没有必要使用Celery?

其实关于Django的异步视图只是提供了类似于任务或消息队列的功能,但功能上并没有Celery强大。如果你正在使用(或者正在考虑)Django3.1,并且想做一些简单的事情(并且不关心可靠性),异步视图是一种快速、简单地完成这个任务的好方法。如果你需要执行重得多的、长期运行的后台进程,你还是要使用Celery。

简而言之,Django3.1的异步任务目前仅仅是解决Celery过重的一个简化方案而已。

结语:假如我们说,新世纪以来在Python在Web开发界有什么成就,无疑的,我们应该说,Django和Flask是两个颠扑不破的巨石重镇,没有了它们,Python的web开发史上便要黯然失光,Django作为第一web开发框架,要文档有文档,要功能有功能,腰斩对手于马下,敏捷开发利器。Django3.1的发布仿佛把我们又拉回到了Django一统江湖的年代,那个美好的时代,让无数人午夜梦回。

原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_177

一代版本一代神:利用Docker在Win10系统极速体验Django3.1真实异步(Async)任务的更多相关文章

  1. Docker在手,天下我有,在Win10系统下利用Docker部署Gunicorn+Flask打造独立镜像

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_164 书接上回,之前一篇:Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最 ...

  2. Win10系统下基于Docker构建Appium容器连接Android模拟器Genymotion完成移动端Python自动化测试

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_196 Python自动化,大概也许或者是今年最具热度的话题之一了.七月流火,招聘市场上对于Python自动化的追捧热度仍未消减,那 ...

  3. 浩若烟海事半功倍|利用Docker容器技术构建自动化分布式web测试集群Selenium Grid

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_195 "世界上有那么多城市,城市里有那么多的酒馆,可她,却偏偏走进了我的-",这是电影<卡萨布拉卡> ...

  4. 上穷碧落下凡尘:Win10系统下基于Docker配置Elasticsearch7配合Python3进行全文检索交互

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_166 基于文档式的全文检索引擎大家都不陌生,之前一篇文章:使用Redisearch实现的全文检索功能服务,曾经使用Rediseac ...

  5. [转]利用Docker构建开发环境

    利用Docker构建开发环境 Posted by  makewonder on 2014 年 4 月 2 日   最近接触PAAS相关的知识,在研发过程中开始使用Docker搭建了自己完整的开发环境, ...

  6. ubuntu14.04环境下利用docker搭建solrCloud集群

    在Ubuntu14.04操作系统的宿主机中,安装docker17.06.3,将宿主机的操作系统制作成docker基础镜像,之后使用自制的基础镜像在docker中启动3个容器,分配固定IP,再在3个容器 ...

  7. 利用Docker设置Node.js

      docker是一个开源的应用容器引擎,可以为我们提供安全.可移植.可重复的自动化部署的方式.docker采用虚拟化的技术来虚拟化出应用程序的运行环境.如上图一样.docker就像一艘轮船.而轮船上 ...

  8. Docker学习总结(8)——利用Docker开启持续交付之路

    持续交付即Continuous Delivery,简称CD,随着DevOps的流行正越来越被传统企业所重视.持续交付讲求以短周期.小细粒度,自动化的方式频繁的交付软件,在这个过 程中要求开发.测试.用 ...

  9. CentOS下利用Docker部署Surging

    原文:CentOS下利用Docker部署Surging 1. 安装Centos, 配置固定ip配置文件地址vi /etc/sysconfig/network-scripts/ifcfg-ens33`` ...

随机推荐

  1. kvm 虚拟化技术 1.3之kvm克隆以及快照

    1.kvm虚拟机克隆   克隆kvm虚拟机 ,克隆前需要提前关机     语法: virt-clone -o 原虚拟机  -n 新虚拟机 -f 新虚拟机镜像存放路径    选项中-o 表示 old  ...

  2. 189. Rotate Array - LeetCode

    Question 189. Rotate Array Solution 题目大意:数组中最后一个元素移到第一个,称动k次 思路:用笨方法,再复制一个数组 Java实现: public void rot ...

  3. mmdetection源码阅读

    2021-11-23号更新 mmdetection中的hook函数 参考: 重难点总结: # step1: 根据官方文档,getattr(self,'name')等同于self.name # sept ...

  4. [gym102978C] Count Min Ratio

    [gym102978C] Count Min Ratio 给定 \(B\) 个蓝色的球. \(R\) 个红色的球以及一个绿色的球,同颜色的球不可区分.对于一种球的排列方式,记 \(l_B,r_B,l_ ...

  5. SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析(上)

    概述 定义 Sentinel官网地址 https://sentinelguard.io/zh-cn/index.html 最新版本v1.8.4 Sentinel官网文档地址 https://senti ...

  6. Weakmap详解

    先看一个例子 let obj = { name: 'toto' } // { name: 'toto' }这个对象能够被读取到,因为obj这个变量名有对它的引用 // 将引用覆盖掉 obj = nul ...

  7. 牛亚男:基于多Domain多任务学习框架和Transformer,搭建快精排模型

    导读: 本文主要介绍了快手的精排模型实践,包括快手的推荐系统,以及结合快手业务展开的各种模型实战和探索,全文围绕以下几大方面展开: 快手推荐系统 CTR模型--PPNet 多domain多任务学习框架 ...

  8. JS:比较运算符

    比较运算符有如下: 1.== 等于: 值相等 var a = "0"; var b = 1; var c = 0; console.log(a==0); //true consol ...

  9. Vue路由的模块自动化与统一加载

    首先呢,我们来看看一般项目路由是怎么划分的. 为什么这么划分呢?如果大项目业务非常多,单纯的单页面很难维护,我们只有这样规范化,才能高效率. 模块自动化与统一加载的好处: 规范化命名(模块名.业务名. ...

  10. GameFramework食用指南

    1.框架简介 GF框架分两部分,GameFramework(GF)和UnityGameFramework(UGF): 通过接口的形式对Unity引擎进行了解耦: GF独立于Unity,具体业务逻辑实现 ...