高并发异步uwsgi+web.py+gevent

Flask高并发实战:从gevent到uWSGI的5种部署方案对比(附性能测试数据) 本文深入对比了Flask应用的五种高并发部署方案,包括Werkzeug多线程、gevent.pywsgi、uWSGI多进程、Gunicorn+gevent以及ASGI异步方案。通过详实的性能测试数据,分析了各方案在QPS、延迟、错误率和资源消耗上的差异,并针对不同应用场景提供了具体的选型建议和配置指南,帮助开发者构建高性能、稳定的Flask服务。 阅读详情

高并发异步uwsgi+web.py+gevent

为什么用web.py?

python的web框架有很多,比如webpy、flask、bottle等,但是为什么我们选了webpy呢?想了好久,未果,硬要给解释,我想可能原因有两个:第一个是兄弟项目组用webpy,被我们组拿来主义,直接用了;第二个是我可能当时不知道有其他框架,因为刚工作,知识面有限。但是不管怎么样,webpy还是好用的,所有API的URL和class在一个文件中进行映射,可以很方便地查找某个class是为了哪个API服务的。(webpy的其中一个作者是Aaron Swartz,这是个牛掰的小伙,英年早逝)

这里对webpy、flask、bottle性能进行了测试,测试结果详见:webpy/flask/bottle性能测试

wsgi,这是python开发中经常遇到词(以前只管用了,趁写博客之际,好好学习下细节)。

wsgi协议

WSGI的官方文档参考http://www.python.org/dev/peps/pep-3333/。WSGI是the Python Web Server Interface,它的作用是在协议之间进行转换。WSGI是一个桥梁,一边是web服务器(web server),一边是用户的应用(wsgi app)。但是这个桥梁功能非常简单,有时候还需要别的桥(wsgi middleware)进行帮忙处理,下图说明了wsgi这个桥梁的关系。

一个简单的WSGI应用:

?
1
2
3
4
5
6
def simple_app(environ, start_response):
     """Simplest possible application object"""
     status = '200 OK'
     response_headers = [( 'Content-type' , 'text/plain' )]
     start_response(status, response_headers)
     return [HELLO_WORLD]

这个是最简单的WSGI应用,那么两个参数environ,start_response是什么?

evniron是一系列环境变量,参考https://www.python.org/dev/peps/pep-3333/#id24,用于表示HTTP请求信息。(为了让理解更具体一点,下表给出一个例子,这是uWSGI传递给wsgi app的值)

?
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
{
     'wsgi.multiprocess' : True,
     'SCRIPT_NAME' : '' ,
     'REQUEST_METHOD' : 'GET' ,
     'UWSGI_ROUTER' : 'http' ,
     'SERVER_PROTOCOL' : 'HTTP/1.1' ,
     'QUERY_STRING' : '' ,
     'x-wsgiorg.fdevent.readable' : <built-infunctionuwsgi_eventfd_read>,
     'HTTP_USER_AGENT' : 'curl/7.19.7(x86_64-unknown-linux-gnu)libcurl/7.19.7NSS/3.12.7.0zlib/1.2.3libidn/1.18libssh2/1.2.2' ,
     'SERVER_NAME' : 'localhost.localdomain' ,
     'REMOTE_ADDR' : '127.0.0.1' ,
     'wsgi.url_scheme' : 'http' ,
     'SERVER_PORT' : '7012' ,
     'uwsgi.node' : 'localhost.localdomain' ,
     'uwsgi.core' : 1023,
     'x-wsgiorg.fdevent.timeout' : None,
     'wsgi.input' : <uwsgi._Inputobjectat0x7f287dc81e88>,
     'HTTP_HOST' : '127.0.0.1: 7012' ,
     'wsgi.multithread' : False,
     'REQUEST_URI' : '/index.html' ,
     'HTTP_ACCEPT' : '*/*' ,
     'wsgi.version' : (1, 0),
     'x-wsgiorg.fdevent.writable' : <built-infunctionuwsgi_eventfd_write>,
     'wsgi.run_once' : False,
     'wsgi.errors' : <openfile 'wsgi_errors' ,   mode 'w' at0x2fd46f0>,
     'REMOTE_PORT' : '56294' ,
     'uwsgi.version' : '1.9.10' ,
     'wsgi.file_wrapper' : <built-infunctionuwsgi_sendfile>,
     'PATH_INFO' : '/index.html'
}

start_response是个函数对象,参考https://www.python.org/dev/peps/pep-3333/#id26,其定义为为start_response(status, response_headers, exc_info=None),其作用是设置HTTP status码(如200 OK)和返回结果头部。

WSGI服务器

wsgi服务器就是为了构建一个让WSGI app运行的环境。运行时需要传入正确的参数,以及正确地返回结果,最终把结果返回客户端。工作流程大致是,获取客户端的request信息,封装到environ参数,然后把执行结果返回给客户端。

对于webpy而言,其内置了一个CherryPy服务器。CheckPy在运行时,采用多线程模式,主线程负责accept客户端请求,将请求放入一个request Queue里面,然后有N个子线程负责从Queue中取出request,然后处理后将结果返回给客户端。不过看起来,这个内置的服务器看起来是为了开发调试用,因为webpy并未开放这个默认容器的参数调节,例如线程数目,所以为了寻求高效地托管WSGI app,不建议用这个默认的容器。这可能也是使用uWSGI的原因,因为我们的线上系统有几个API的访问量很大,目前大概是250万次/天。(当然对于业务量不是很大的服务,可能这个默认的CheckPy也就够了)

uWSGI

我们知道,Python有把大锁GIL,会将多个线程退化为串行执行,所以一个多线程python进程,并不能充分使用多核CPU资源,所以对于Python进程,可能采用多进程部署方式比较有利于充分利用多核的CPU资源。

uWSGI就是这么一个项目,可以以多进程方式执行WSGI app,其工作模式为 1 master进程 + N worker进程(N*m线程),主进程负责accept客户端request,然后将请求转发给worker进程,因此最终是worker进程负责处理客户端request,这样很方便的将WSGI app以多进程方式进行部署。以下给出uwsgi响应客户端请求的执行流程图:

image值得注意的是,在master进程接收到客户端请求时,以round-bin方式分发给worker进程,所以多个process在处理前端请求时,所承受的负载相对还是均衡的。(这是我测试时的经验,改天再扒一下uwsgi的源代码确认一下 TODO)。关于uWSGI的使用,可能并不是这里的重点,不再赘述。

(其实看到uWSGI的多进程模型,我想到了Nginx,它也是多进程模型,这个也很有意思,由此了解了thunder herd问题,扯远了,继续往下说)

考虑一个应用场景:client向serverM(uwsgi)发起一个HTTP请求,serverM在处理这次请求时,需要访问另一个服务器serverN,直到serverN返回数据,serverM才会返回结果给client,即wsgi app是同步的。假如serverM访问serverN花费时间比较久,那么若是client请求数量比较多的情况下,(N*m)线程都会被占用,可想而知,大容量下的并发处理能力就受(N*m)的限制。

如果碰上了这种情况,怎么解决呢?

(1)增大N,即worker的数量:在增加进程的数量的时候,进程是要消耗内存的,并且如果进程数量太多的情况下(并且进程均处于活跃状态),进程间的切换会消耗系统资源的,所以N并不是越大越好。一般情况下,可能将进程数目设置为CPU数量的2倍。

(2)增大m,即worker的线程数量:在创建线程的时候,最大能够多大呢?由于线程栈是要消耗内存的,因此线程的数量跟系统设置(virtual memory)和(stack size)有关。线程数量太大会不会不太好?(这个肯定不好,我答不上来 TODO)

由此在大并发需求的情况下,我了解到了C10K问题,并进一步学习到I/O的多路复用的epoll,可以避免阻塞调用在某个socket上。比如libevent就是封装了多个平台的高效地I/O多路复用方法,在linux上用的就是epoll。但是这里我们不讨论epoll或者libevent的使用,我们这里引入gevent模块。

gevent协程

gevent在使用时,跟thread的接口很像,但是thread是由操作系统负责调度,而gevent是用户态的“线程”,也叫协程。gevent的好处就是无需等待I/O,当发生I/O调用是,gevent会主动切换到另一gevent进行运行,这样在等待socket数据返回时,可以充分利用CPU资源。

在使用gevent内部实现:

1. gevent 协程切换使用greenlet项目,greenlet其实就是一个函数,及保存函数的上下文(也就是栈),greenlet的切换由应用程序自己控制,所以非常适合对于I/O型的应用程序,发生I/O时就切换,这样能够充分利用CPU资源。

2. gevent在监控socket事件时,使用了libevent,就是高级的epoll。

3. python中有个猴子补丁(monkey patch)的说法,在python进程中,python的函数都是对象,存在于进程的全局字典中,因此,开发者可以通过替换这些对象,来改变标准库函数的实现,这样还不用修改已有的应用程序。在gevent里,也有这样的monkey patch,通过gevent.monkey.patch_all()替换掉了标准库中阻塞的模块,这样不用修改应用程序就能充分享受gevent的优势了。(真是方便啊)

使用gevent需注意的问题

1. 无意识地引入阻塞模块

我们知道gevent通过monkey patch替换掉了标准库中阻塞的模块,但是有的时候可能我们会“无意识”地引入阻塞模块,例如MySQL-Python,pylibmc。这两个模块是通过C扩展程序实现的,都需要进行socket通信,由于调用的底层C的socket接口,所以超出了gevent的管控范围,这样就在使用这两个模块跟mysql或者memcached进行通信时,就退化为了阻塞调用。

这样一个应用场景:在一个gevent进程中,基于MySQL-Python模块,创建一个跟mysql有10个连接的连接池,当并发量大的情况下,我们期望这10个连接可以同时处理对mysql的10个请求。实际如我们期望的这样么?的确跟期望不一样,因为在conn.query()的时候,阻塞了进程,这样意味着同一时刻不可能同时有2个对mysql的访问,所以并发不起来了。如mysql响应很慢的话,那么整个process跟hang住了没什么两样(这个时候,便不如多线程的部署模式了,因为多个线程的话,一个线程hang住,另一个线程还是有机会执行的)。

如何解决:在这些需要考虑并发的效率的场景,尽量避免引入阻塞模块,可以考虑纯python实现的模块,例如MySQL-Python->pymysql, pylibmc->memcached(这个python实现的memcached client可能不太完备,例如一致性hash目前都没实现)。

2. gevent在遇到I/O访问时,会进行greenlet切换。若是某个greenlet需要占用大量计算,那么若是计算任务过多(激进一点,陷入死循环),可能会导致其他greenlet没有机会执行。若是一个gevent进程需要执行多个任务时,若某个任务计算过多,可能会影响其他任务的执行。例如我曾遇到一个进程中,采用生产者任务(统计数据,将结果放入内存)+消费者任务(将计算结果写入磁盘),然而当数据很大的时候,生产者任务占用大量的CPU资源,然而消费者任务不能及时将统计结果写入磁盘,即生产太快,消费太慢,这样内存占用越来越多,一度高达2G内存。所以鉴于此,需要根据任务的特点(I/O密集或者CPU密集),合理分配进程任务。

参考:

https://www.python.org/dev/peps/pep-3333/

http://www.oschina.net/question/12_26400

http://blog.jobbole.com/77240/

http://www.tuicool.com/articles/2aIZZb

 

以上为工作经验总结,在整理成文的时候,才发现有些知识点只是一知半解,所以需要继续完善该文。

uWSGI部署Python Web应用全指南 WSGI(Web Server Gateway Interface)是Python Web开发的核心协议标准,定义了Web服务器与应用框架间的通用接口规范。uWSGI作为高性能WSGI服务器实现,采用C语言编写并支持多进程/多线程架构,能显著提升Python应用的并发处理能力。其技术价值体现在协议兼容性(支持HTTP、uwsgi等)、资源利用率优化以及丰富的扩展插件体系。在Web服务架构中,uWSGI通常与Nginx组成黄金组合,前者负责Python应用执行,后者处理静态资源和负载均衡。本文以Django/ 阅读详情

相关推荐

Python Web服务器选型实战:Gunicorn、uWSGI、Waitress与Uvicorn深度对比

WSGI服务器是Python Web应用的运行时核心,其进程模型、并发机制与系统资源调度直接决定服务稳定性与吞吐能力。理解Gunicorn的Pre-fork模型、uWSGI的多模式混合架构、Waitress的纯Python单进程多线程设计,以及Uvicorn对ASGI和异步事件循环的原生支持,是规避502错误、内存泄漏和CPU瓶颈的关键。在Django同步IO密集场景中,Gunicorn的进程隔离性保障数据库连接稳定性;而在FastAPI高并发API中,Uvicorn结合uvloop与httptools可实

chuiqi9947的博客 306

uwsgi gevent

Gevent循环引擎 Gevent是一个令人惊奇的非阻塞Python网络库,构建在libev和greenlet之上。虽然uWSGI支持Greenlet作为挂起-恢复/绿色线程/协程库,但是还需要大量的努力和代码修改才能对gevent起作用。gevent插件要求gevent 1.0.0 和uWSGI异步/非堵塞模式 (已更新至uWSGI 1.9)模式。 注意 SignalFram...

长门有希的博客 1902

uWSGI部署Python Web应用的核心技术与实践指南

WSGI协议作为Python Web开发的核心标准,定义了Web服务器与应用框架之间的通用接口规范。其工作原理是通过标准化的environ字典和start_response回调实现HTTP请求/响应转换,使开发者能专注于业务逻辑开发。uWSGI作为高性能的WSGI实现,采用事件驱动架构和C语言优化,在并发处理能力和资源利用率上显著优于传统方案。在Django、Flask等主流框架的生产部署中,uWSGI通过进程管理、异步I/O支持和Nginx反向代理等特性,能够稳定支撑3000+并发请求。本文重点解析uWS

cigang4063的博客 459

uwsgi使用经验, uwsgi异步任务

1. nginx 报 readv() failed  uwsgi+nginx搭建的server,发现当用post请求时,会返回数据超时。查了一下nginx中的error.log: [error] 16833#0: *158 readv() failed (104: Connection reset by peer) while reading upstream, client: 10.20.1

toontong的专栏 5799

Google账号找回通用方法(尤其是知道账号密码仍无法登录和找回的)

Google账号找回通用方法【尤其是知道账号密码仍无法登录和找回的】普通找回注意:适用于常用谷歌账户的设备和网络情况下无法使用手机或辅助邮箱验证码进行密码找回特殊找回方法注意;适用于1.新的设备以及网络环境(包括由于非正常原因导致设备系统以及应用信息变更)2.没有开启辅助验证(手机/邮箱)3.知道账号密码但无法登录或找回。通过申诉进行找回 普通找回 注意:适用于 常用谷歌账户的设备和网络情况下 无法使用手机或辅助邮箱验证码进行密码找回 通过恢复页面进行恢复 https://accounts.google

极客代码-极致生活 23万+

Python调用Google Trends官方数据接口实战指南

Google Trends作为全球最权威的搜索热度分析工具,其数据本质是公开、结构化、可编程访问的时序指标,而非需爬取的网页内容。其底层基于标准HTTP协议与JSON API交互,核心原理在于复现用户浏览器行为——通过/explore接口获取token,再凭token请求/widgetdata/multiline等端点获取归一化(0-100)时间序列数据。该技术路径规避了Selenium渲染依赖与非官方库的脆弱性,具备高稳定性、易调试、可监控等工程优势,广泛应用于竞品监测、内容选题验证、地域营销策略制定等业

weixin_29789925的博客 421

uwsgi+gevent+nginx部署实现协程高并发

python 所有用到的库。

guochunbiao0416的博客 748

【25届数字IC秋招总结】面试经验15——比特大陆-算能

25届数字ic面试记录——比特大陆-算能

lalala0635的博客 557

【小沐学Python】Python实现Web服务器(Flask,gevent )

gevent 是一个基于协程的 Python 网络库,它使用 greenlet 在 libev 或 libuv 事件循环之上提供高级同步 API。╮( ̄▽ ̄)╭如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)!!

爱看书的小沐 6143

K8s-K8s部署Zookeeper+Kafka+ELFK+持久化数据

K8s环境下容器化部署`Zookeeper+Kafka+ELFK`日志收集系统

✅ 专注企业级 Linux/DevOps 运维的实战派 ✅ 已输出上百篇可落地方案 ✅ Shell 脚本开箱即用 ✅ K8s/YAML 环境验证 ✅ 故障排查链路完整复现 1915

UE5 Niagara基础知识讲解

在UE5版本中,Niagara粒子系统引入了许多可添加的模块,分别用于控制发射器的生成和更新、粒子的生成和更新以及渲染效果。本文采用虚幻5.2.1版本,以图文方式对Niagara基础知识进行讲解。

一碗清深的博客 2472

python websocket异步高并发_高并发异步uwsgi+web.py+gevent

为什么用web.py?python的web框架有很多,比如webpy、flask、bottle等,但是为什么我们选了webpy呢?想了好久,未果,硬要给解释,我想可能原因有两个:第一个是兄弟项目组用webpy,被我们组拿来主义,直接用了;第二个是我可能当时不知道有其他框架,因为刚工作,知识面有限。但是不管怎么样,webpy还是好用的,所有API的URL和class在一个文件中进行映射,可以很方便地...

weixin_39849153的博客 880

国科大学习资料--人工智能原理与算法-第六次作业解析(学长整理)

国科大学习资料–人工智能原理与算法-第六次作业解析(张文生老师主讲)(6.6、6.7、6.11) 6.6 说明如何通过使用辅助变量把诸如A+B=C这样的三元约束转变成三个二元约束。假设值域是有限的。(提示:考虑引进新变量表示变量对的值,引进约束如“X是Y变量对中的第一个元素”。)然后说明如何把多于三个变量的约束类似地转换为二元约束。说明如何通过改变变量的值域来消除一元约束。这就完整演示了任何CSP都可以转变为只含二元约束的CSP。 答:首先,我们引入一个新变量AB,假设A和B的范围均为N,AB的范围为N×N

无名何许人的博客 2870

uwsgi引入gevent模块报错

将uwsgi日志加入: gevent=100 #gevent协程支持,最大100个 gevent-monkey-patch=true #gevent协程补丁 发现django出现以下错误: django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in th

Kris,Ready Always! 3879

通信算法之334:无人机侦测-DJI 大疆云哨接收机系列

【代码】通信算法之334:DJI 大疆 云哨接收机算法流程。

leegang12的专栏 844

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

关于uwsgi+gevent+web.py的备忘

简单入门: [url=http://projects.unbit.it/uwsgi/]uwsgi[/url]:nginx般的优雅控制 [url=http://www.gevent.org/]gevent[/url]:高效、无缝的接入 [url=http://webpy.org/]web.py[/url]:简洁 关于uwsgi+web.py: [code="python"] impo...

风吹鸡蛋壳 251

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

python怎么测试uwsgi并发量_利用gevent来配置uwsgi提高django项目并发量

add by zhj:在Benchmark of Python WSGI Servers一文中,作者进行详细分析,得出的结论是gevent在所有WSGI Server(包括Tornado、Uwsgi等)中性能最好。另外,我想说gevent适合socket IO,其它类型的IO,如磁盘IO是否适合就不清楚了。我的一个线上web服务在生产中遇到一个性能问题:当初为了方便选择了wsgi(众所周知wsgi...

weixin_39666782的博客 550

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

uwsgi概述和配置

使用c语言开发的wsgi服务器(不止wsgi)官方参考文档,英文官方参考文档,中文WSGI是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。这是把服务器和服务程序分开uwsgi是服务器,调用python写的web应用程序或flask的python框架代码WSGI协议是对http协议的封装,是基于http协议的。比如env[“REQUEST_METHOD”]就是http的method。env[‘wsgi.input’]是消息体(如果是POST方法)

一起学习 3747

0基础python教程 Python项目高并发异步部署实战+压测

接着上一章,往下学习,本章主要讲解Python项目高并发异步部署实战+压测,学习的小伙伴千万不能错过本课,本课是实践课非常的重要哦~~~ ## 1 前言 由于Python有把大锁GIL,会将多个线程在同一时刻,只能有一个线程执行,变成'串行',所以一个多线程python进程,并不能充分使用多核CPU资源,所以对于Python进程,可采用多进程部署方式比较有利于充分利用多核的CPU资源,而uWSGI服务器就是这么一个东西,可以以多进程方式执行WSGI app,其工作模式为 1 master进程 + N w

laoliupython的博客 269

python 高性能web框架 gunicorn+gevent

参考链接: http://rfyiamcool.blog.51cto.com/1030776/1276364/                    http://www.cnblogs.com/nanrou/p/7026789.html 前言 gunicorn 是支持wsgi协议的http服务器,gevent只是它支持的模式之一,是为了解决django、flask这些web框架自带wsgi

Hebe 6965

CentOS 7下uWSGI+Nginx部署Python Web应用实战指南

Web服务器与应用服务器分离是现代Python Web生产部署的基础架构原则。Nginx作为高性能反向代理,负责SSL终止、静态资源服务与连接管理;uWSGI作为WSGI协议实现,专注Python进程调度与请求处理。二者协同构建了高并发、易监控、可伸缩的部署范式。该架构在CentOS 7等企业级Linux发行版上具备深度兼容性,尤其适配systemd服务管理、SELinux安全策略及稳定内核特性。典型应用场景包括Django/Flask/FastAPI等框架的公网上线、政务系统迁移、教育平台扩容等对稳定性与

weixin_30315435的博客 1086

python web框架性能对比_用gunicorn和gevent提高python web框架的性能

这两天在准备ppt,里面有涉及到WSGI的应该用,以前自己在51cto写过关于gunicorn的文章,所以就转了过来。那么不扯淡了。其实比如 Flask,webpy,Django、CherryPy 都带着 WSGI server 。当然性能都不好,自带的web server 更多的是测试用途, 线上发布时,则使用高性能的 wsgi server或者是联合nginx做uwsgi 。诚如那个WSGI的...

weixin_39836063的博客 645

使用nginx+uWSGI部署Flask应用

https://dormousehole.readthedocs.io/en/latest/deploying/uwsgi.html#starting-your-app-with-uwsgi   uWSGIuWSGI 也是部署 Flask 的途径之一,类似的部署途径还有 nginx 、 lighttpd 和 cherokee 。其他部署途径的信息参见 FastCGI 和 独立 WSGI ...

Chopin's nocturnes 582

nginx+(uwsgi/gunicorn)+django+dwebsocket部署

记录一次django使用dwebsocket踩过的坑nginx+uwsgi+django+dwebsocket(放弃)使用nginx做反向代理,配置如下:uwsgi做web服务器,配置如下:settings.py添加如下配置:django测试用例前端html测试用例nginx重启uwsgi启动nginx+gunicorn+django+websocket(使用gunicorn的协程启动)nginx...

weixin_44784018的博客 2474
上一篇: [Python] 技术贴系列之——Django部署方案简介
下一篇: flask
linuxheik
博客等级 码龄15年 865粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值