django如何处理并发(2023年最新整理)

我请分析下,django如何处理并发(2023年最新整理)
最新回答
仙女不仙

2024-10-31 07:25:56

导读:今天首席CTO笔记来给各位分享关于django如何处理并发的相关内容,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

Django配置Celery执行异步和同步任务(tasks))

celery是一个基于python开发的简单、灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线程上执行任务调度。采用典型的生产者-消费者模型,主要由三部分组成:

比如系统上线前后台批量导入历史数据,发送短信、发送邮件等耗时的任务

1.安装RabbitMQ,这里我们使用RabbitMQ作为broker,安装完成后默认启动了,也不需要其他任何配置

Ubuntulinux安装

CentOSLinux安装

苹果mac安装需要配置

配置环境变量(苹果用户)

启动rabbitmq-server

2.安装celery

3.celery用在django项目中,django项目目录结构(简化)如下

4.创建oa/celery.py主文件

5.在oa/__init__.py文件中增加如下内容,确保django启动的时候这个app能够被加载到

6.各应用创建tasks.py文件,这里为users/tasks.py

7.views.py中引用使用这个tasks异步处理

8.启动celery

9.这样在调用post这个方法时,里边的add就可以异步处理了

定时任务的使用场景就很普遍了,比如我需要定时发送报告给老板~

1.oa/celery.py文件添加如下配置以支持定时任务crontab

3.启动celerybeat,celery启动了一个beat进程一直在不断的判断是否有任务需要执行

django使用全局线程池

系统里面有频繁的异步操作,每次触发异步操作就会开始一个新的线程处理相关逻辑,逻辑集中在I/O密集型;频繁的新建/销毁线程,消耗大量资源;由此,考虑使用线程池替换现有逻辑。

经过查询资料,python有ThreadPoolExecutor(tomorrow)可以直接实现线程池的相关功能,它的使用方式

具体使用方法见ThreadPoolExecutor

ThreadPoolExecutor建立的线程池会先启动若干数量的线程,并让这些线程都处于睡眠状态,当向线程池submit一个任务后,会唤醒线程池中的某一个睡眠线程,让它来处理这个任务,当处理完这个任务,线程又处于睡眠状态。减少了建立销毁线程池消耗

在本项目里面的实现如下(定义的装饰器)

总体的原则是:CPU密集型任务应配置尽可能小的线程,尽量跟CPU的个数相近;IO密集型任务应配置尽可能多的线程,因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量。推荐的公式:

django并发是多线程还是epoll

django自带的那个是效率相当低下的,它没有采用epoll/kqueue。

具体支持多少人在线,这个很难说。

测了一下,对于我的电脑,初始django工程的根的并发能力大概是294。

相比而言,tornado是高性能的server,用它文档的web的范例,并发能力大概是1324。

对nginx上的一个只包含“helloworld!"的静态文件的访问,并发能力大概是2942

djangowebsocket

做个比喻,如果说A是服务端,B是客户端,现在要在A家里吃火锅,虽然A说你人来就行,但是B心想总得带点东西过去,于是去了市场.

先到了蔬菜店,B想买点菠菜,但又怕A家里已经有了,于是给A打电话

B:"我带点菠菜过去吧?"

A:"好"

然后挂断.过一会儿到了水产区

B:"我带点虾过去吧?"

A:"不用"

...如此反复多了之后A突然发现自己确实少准备了一些东西,于是A给主动给B打了电话

A:"我忘准备蘸料了,你买点,然后先别挂掉"

...

A:"再买瓶酒"

...

这就是websocket了

django当让也提供对websocket的支持,虽然这似乎不是他更擅长的东西.我们可以通过channels实现websocket连接

诸如上述例子的场景都是合适的场景

举例来说的话比如聊天室,每个人发送的消息都要实时显示在别人的屏幕上.

比如说数据监控,波动状态也要实时的呈现在屏幕上,而不是依赖于使用者自己刷新.

需要安装channels,asgi_redis,asgiref,channels_redis.后三个未必都需要装,记不太清了,总之安装过程都在channels的使用文档上.

INSTALL_APPS中需要加上"channels",需要注意的是因为这是一个list,是有先后顺序的,最好把它加在第一个.

这里我们的channel通过redis实现,要在settings.py中配置

这里还有点小坑,官方文档里的hosts不是这种格式,是"uri"这种模式,但是如果你在设置redis密码时机智的设置了特殊符号('#$%'这种),你就会发现redis的uri直接就用不了了,期间尝试各种方法,转义什么的也试了都不行,然后去github上开了个issue,结果作者说我们是通过aioredis连接的,你去找他们的文档吧....

然后就找到了这种方式.

常规的WSGI不支持websocket,所以还需要配置ASGI

ASGI_APPLICATION='project.routing.application'

同wsgi的配置一样,这是指向project文件夹下routing.py文件的application

这里建议大家跟这官方教程的Tutorial走一遍.有个比较悲剧的地方就是网上可以搜到许多channels使用指南,大多都是搭个简易聊天室什么的,然而你用起来可能发现存在各种报错,因为channels升了2.0之后更改了一些方法,而那些教程里基本全都是1.x的版本.

简单说下,首先startapp叫chat,假如这里我们没有进行前后端分离,里面有templates,两个html:index和room分别对应首页和某一个聊天室

新建consumers.py来写websocket方法

如上,connect和disconnect含义分别如函数名.因为是聊天室,所以同一个聊天室内的人应该消息共享,用room_group_name来区分所在的频道.

receive和chat_message是对消息的处理.当一个用户发送消息时,前端把消息通过websocket发送过来,receive收到消息提取关键内容,通过chat_message发送给组内的所有连接.这时保持连接的所有组内人员都会收到这条消息推送,前端收到推送再显示在屏幕上.

定义websocket的地址

类似于django的url(consumers.py就类似于views.py),同级新建routing.py

统一用ws/来区分websocket的连接

剩下常规的页面配置和django一样

views.py:

urls.py:

注意:如果网站是http,连接使用ws,如果是https要修改成wss

剩下的自己找资料吧,笔者对前端了解的不多

本地的话runserver就好了,但是在线上还是得更改启动方式应对高并发.

传统的uwsgi不支持websocket.

gunicorn好像可以同时支持websocket,但是性能不太ok

这里我们用daphne

这里需要额外开个服务,专门负责处理websocket.

ingress中要配置路由跳转

django并发请求是多线程吗

用Django搭了个环境,创建了一个App。

我想要测试假如同时多个请求进来Django的处理方式,于是写了一下代码在View.py中:

Pythoncode?

defarchive(request):

print("start")

time.sleep(5)

print("end")

returnHttpResponse("HellowWorld")

结语:以上就是首席CTO笔记为大家整理的关于django如何处理并发的相关内容解答汇总了,希望对您有所帮助!如果解决了您的问题欢迎分享给更多关注此问题的朋友喔~