首页>>后端>>Python->django如何处理高并发(django能支持多少量的并发)

django如何处理高并发(django能支持多少量的并发)

时间:2023-12-12 本站 点击:0

导读:很多朋友问到关于django如何处理高并发的相关问题,本文首席CTO笔记就来为大家做个详细解答,供大家参考,希望对大家有所帮助!一起来看看吧!

django并发是多线程还是epoll

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

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

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

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

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

如何用nginx关联django应用

通过Nginx部署Django(基于ubuntu)

Django的部署可以有很多方式,采用nginx+uwsgi的方式是其中比较常见的一种方式。

在这种方式中,我们的通常做法是,将nginx作为服务器最前端,它将接收WEB的所有请求,统一管理请求。nginx把所有静态请求自己来处理(这是NGINX的强项)。然后,NGINX将所有非静态请求通过uwsgi传递给Django,由Django来进行处理,从而完成一次WEB请求。

可见,uwsgi的作用就类似一个桥接器。起到桥梁的作用。

Linux的强项是用来做服务器,所以,下面的整个部署过程我们选择在Ubuntu下完成。

一、安装Nginx

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。

Nginx同样为当前非常流行的web服务器。利用其部署Django,我们在此也做简单的介绍。

Nginx官网:

打开ubuntu控制台(ctrl+alt+t)利用Ubuntu的仓库安装。

fnngj@ubuntu:~$ sudo apt-get install nginx #安装

启动Nginx:

fnngj@ubuntu:~$ /etc/init.d/nginx start #启动

fnngj@ubuntu:~$ /etc/init.d/nginx stop #关闭

fnngj@ubuntu:~$ /etc/init.d/nginx restart #重启

修改Nginx默认端口号,打开/etc/nginx/nginx.conf 文件,修改端口号。

复制代码

server {

listen 8088; # 修改端口号

server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {

root html;

index index.html index.htm;

}

复制代码

大概在文件36行的位置,将默认的80端口号改成其它端口号,如 8088。因为默认的80端口号很容易被其它应用程序占用。

然后,通过上面命令重启nginx。访问:http//127.0.0.1:8088/

如果出现如上图,说明Nginx启动成功。

二、安装uwsgi

通过pip安装uwsgi。

root@ubuntu:/etc# python3 -m pip install uwsgi

测试uwsgi,创建test.py文件:

def application(env, start_response):

start_response('200 OK', [('Content-Type','text/html')])

return [b"Hello World"]

通过uwsgi运行该文件。

fnngj@ubuntu:~/pydj$ uwsgi --http :8001 --wsgi-file test.py

接下来配置Django与uwsgi连接。此处,假定的我的django项目位置为:/home/fnngj/pydj/myweb

fnngj@ubuntu:~/pydj$ uwsgi --http :8001 --chdir /home/fnngj/pydj/myweb/ --wsgi-file myweb/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

常用选项:

http : 协议类型和端口号

processes : 开启的进程数量

workers : 开启的进程数量,等同于processes(官网的说法是spawn the specified number ofworkers / processes)

chdir : 指定运行目录(chdir to specified directory before apps loading)

wsgi-file : 载入wsgi-file(load .wsgi file)

stats : 在指定的地址上,开启状态服务(enable the stats server on the specified address)

threads : 运行线程。由于GIL的存在,我觉得这个真心没啥用。(run each worker in prethreaded mode with the specified number of threads)

master : 允许主进程存在(enable master process)

daemonize : 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器(daemonize uWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。

pidfile : 指定pid文件的位置,记录主进程的pid号。

vacuum : 当服务器退出的时候自动清理环境,删除unix socket文件和pid文件(try to remove all of the generated file/sockets)

三、Nginx+uwsgi+Django

接下来,我们要将三者结合起来。首先罗列一下项目的所需要的文件:

myweb/

├── manage.py

├── myweb/

│ ├── __init__.py

│ ├── settings.py

│ ├── urls.py

│ └── wsgi.py

└── myweb_uwsgi.ini

在我们通过Django创建myweb项目时,在子目录myweb下已经帮我们生成的 wsgi.py文件。所以,我们只需要再创建myweb_uwsgi.ini配置文件即可,当然,uwsgi支持多种类型的配置文件,如xml,ini等。此处,使用ini类型的配置。

复制代码

# myweb_uwsgi.ini file

[uwsgi]

# Django-related settings

socket = :8000

# the base directory (full path)

chdir = /home/fnngj/pydj/myweb

# Django s wsgi file

module = myweb.wsgi

# process-related settings

# master

master = true

# maximum number of worker processes

processes = 4

# ... with appropriate permissions - may be needed

# chmod-socket = 664

# clear environment on exit

vacuum = true

复制代码

这个配置,其实就相当于在上一小节中通过wsgi命令,后面跟一堆参数的方式,给文件化了。

socket 指定项目执行的端口号。

chdir 指定项目的目录。

module myweb.wsgi ,可以这么来理解,对于myweb_uwsgi.ini文件来说,与它的平级的有一个myweb目录,这个目录下有一个wsgi.py文件。

其它几个参数,可以参考上一小节中参数的介绍。

接下来,切换到myweb项目目录下,通过uwsgi命令读取myweb_uwsgi.ini文件启动项目。

复制代码

fnngj@ubuntu:~$ cd /home/fnngj/pydj/myweb/

fnngj@ubuntu:~/pydj/myweb$ uwsgi --ini myweb_uwsgi.ini

[uWSGI] getting INI configuration from myweb_uwsgi.ini

*** Starting uWSGI 2.0.12 (32bit) on [Sat Mar 12 13:05:06 2016] ***

compiled with version: 4.8.4 on 26 January 2016 06:14:41

os: Linux-3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015

nodename: ubuntu

machine: i686

clock source: unix

detected number of CPU cores: 2

current working directory: /home/fnngj/pydj/myweb

detected binary path: /usr/local/bin/uwsgi

!!! no internal routing support, rebuild with pcre support !!!

chdir() to /home/fnngj/pydj/myweb

your processes number limit is 15962

your memory page size is 4096 bytes

detected max file descriptor number: 1024

lock engine: pthread robust mutexes

thunder lock: disabled (you can enable it with --thunder-lock)

uwsgi socket 0 bound to TCP address :8000 fd 3

Python version: 3.4.3 (default, Oct 14 2015, 20:37:06) [GCC 4.8.4]

*** Python threads support is disabled. You can enable it with --enable-threads ***

Python main interpreter initialized at 0x8b52dc0

your server socket listen backlog is limited to 100 connections

your mercy for graceful operations on workers is 60 seconds

mapped 319920 bytes (312 KB) for 4 cores

*** Operational MODE: preforking ***

WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x8b52dc0 pid: 7158 (default app)

*** uWSGI is running in multiple interpreter mode ***

spawned uWSGI master process (pid: 7158)

spawned uWSGI worker 1 (pid: 7160, cores: 1)

spawned uWSGI worker 2 (pid: 7161, cores: 1)

spawned uWSGI worker 3 (pid: 7162, cores: 1)

spawned uWSGI worker 4 (pid: 7163, cores: 1)

复制代码

注意查看uwsgi的启动信息,如果有错,就要检查配置文件的参数是否设置有误。

再接下来要做的就是修改nginx.conf配置文件。打开/etc/nginx/nginx.conf文件,添加如下内容。

复制代码

……

server {

listen 8099;

server_name 127.0.0.1

charset UTF-8;

access_log /var/log/nginx/myweb_access.log;

error_log /var/log/nginx/myweb_error.log;

client_max_body_size 75M;

location / {

include uwsgi_params;

uwsgi_pass 127.0.0.1:8000;

uwsgi_read_timeout 2;

}

location /static {

expires 30d;

autoindex on;

add_header Cache-Control private;

alias /home/fnngj/pydj/myweb/static/;

}

}

……

复制代码

listen 指定的是nginx代理uwsgi对外的端口号。

server_name 网上大多资料都是设置的一个网址(例,wwwexamplecom),我这里如果设置成网址无法访问,所以,指定的到了本机默认ip。

在进行配置的时候,我有个问题一直想不通。nginx到底是如何uwsgi产生关联。现在看来大概最主要的就是这两行配置。

include uwsgi_params;

uwsgi_pass 127.0.0.1:8000;

include 必须指定为uwsgi_params;而uwsgi_pass指的本机IP的端口与myweb_uwsgi.ini配置文件中的必须一直。

现在重新启动nginx,翻看上面重启动nginx的命令。然后,访问:http//127.0.0.1:8099/

通过这个IP和端口号的指向,请求应该是先到nginx的。如果你在页面上执行一些请求,就会看到,这些请求最终会转到uwsgi来处理。

python高并发web框架有哪些

python的web框架很多

django (大而全,模板,orm都自带)

flask (pocoo出品,比属精品,自带jinja2模板,可以替换)

web.py (这个我没用过,作者自杀,白瞎了一个高手)

bottle (只有一个文件的框架,需要自己构建整个开发体系)

uliweb (中国人开发的,也很不错)

Tornado (异步框架,适合长连接,比如在线聊天之类的)

Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django。Django为人所称道的地方主要有:

①完美的文档,Django的成功,我觉得很大一部分原因要归功于Django近乎完美的官方文档(包括Django book)。

②全套的解决方案,Django象Rails一样,提供全套的解决方案(full-stack framework + batteries included),基本要什么有什么(比如:cache、session、feed、orm、geo、auth),而且全部Django自己造,开发网 站应手的工具Django基本都给你做好了,因此开发效率是不用说的,出了问题也算好找,不在你的代码里就在Django的源码里。

③强大的URL路由配置,Django让你可以设计出非常优雅的URL,在Django里你基本可以跟丑陋的GET参数说拜拜。

④自助管理后台,admin interface是Django里比较吸引眼球的一项contrib,让你几乎不用写一行代码就拥有一个完整的后台管理界面。

django websocket

做个比喻, 如果说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本身提供了runserver,为什么不用来部署

      Django本身自带了runserver,但是我们只是在测试的时候,会用到它,而在真正的生产部署一般都会使用uwsgi+nginx方式。

       因为我们的生产环境一般都会有很大的并发访问量,而django自带的runserver非常不稳定,最大连接数大约在几十个,过多的并发连接,导致服务崩溃,而且安全性上也不好。

       而nginx可以支持高并发连接,官方给出最大连接数在50000个左右,实际生产中,大约也在20000~40000个左右,内存消耗少,稳定性高,支持热部署(可以在不间断服务的情况下,进行版本升级)。

      相对比较而言,Django自带的runserver,只适合我们在测试的时候使用。

结语:以上就是首席CTO笔记为大家介绍的关于django如何处理高并发的全部内容了,希望对大家有所帮助,如果你还想了解更多这方面的信息,记得收藏关注本站。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Python/28088.html