0x00 Why

为何做这件事,在去年的一个项目中,算法同学要使用在线模型训练,不得不使用python的tf框架,这样我们不得不是python web框架,当时因为团队里面没人懂python相关的知识,只是简单的用tornado搭建的一个。但是在后期使用过程中,压测发现了tornado在低耗时的接口不够稳定,波动比较大。我们的接口一般20ms,但是经常波动到40ms,并发其实也不大。所以经历了痛苦过后,为了满足后续类似的场景,我们需要打造一款内部使用的python web框架,能够支持低耗时接口的稳定性,以及稍微性能强点。

0x01 How

基于以上的出发点,开始调研python web相关性能比较高的框架,看到了sanic。说是性能比较高。先看下sanic作者开发sanic的动机,是因为他看下了下面这篇文章:

uvloop: Blazing fast Python networking

是因为python3.4推出了asyncio,解决令人诟病的异步io性能问题,3.5后推出了uvloop,基于libuv,libuv是一个使用C语言实现的高性能异步I/O库,uvloop用来代替asyncio默认事件循环,可以进一步加快异步I/O操作的速度,而tornado在python3中还没有使用uvloop。

首先来看下uvloop的性能表现:

0x02 tornado vs sanic

口说无凭,直接压测看数据,我们同时构造两个框架的一个接口,接口里面没有任务逻辑,就是简单的返回一个helloworld,都是起一个进程,实测的数据

  • sanic:18000/s
  • tornado:5000/s

就框架本身而言,sanic确实性能高。然后我又对各个耗时阶段的接口进行压测,来判断不同耗时,两个框架的表现。

Sanic

Sleep(ms)\Thread 1 10 50 100
1 1-3之间波动,波动范围为0%~300%,周期性的 1-6之间波动,波动范围为0%~600%,周期性的 1-11之间波动,波动范围为0%~1100%,周期性的 1-7之间波动,波动范围为0%~700%,周期性的
10 11-15之间波动,波动范围为10%~50%,周期性的 12-17之间波动,波动范围为20%~70%,周期性的 11-20之间波动,波动范围为10%~100%,周期性的 11-31之间波动,波动范围为10%~310%,周期性的
50 51-56,周期性的波动 54-60,周期性 54-71,周期性的 51-61,周期的
100 101-106之间波动,波动范围为1%~6%,周期性的 103-110之间波动,波动范围为3%~10%,周期性的 103-120之间波动,波动范围为3%~20%,周期性的 105-130之间波动,波动范围为5%~30%,周期性的

Tornado

Sleep(ms)\Thread 1 10 50 100
1 2-4之间波动,波动范围为200%~400%,周期性的 6-11之间波动,波动范围为600%~1100%,周期性的 21-56之间波动,波动范围为2100%~5600%,周期性的 50-106之间波动,波动范围为5000%~10600%,周期性的
10 11-15之间波动,波动范围为110%~150%,周期性的 11-18之间波动,波动范围为110%~180%,周期性的 28-43之间波动,波动范围为280%~430%,周期性的 62-104之间波动,波动范围为620%~1040%,周期性的
50 52-57之间波动,周期性的 54-62,周期性的 51-80,周期性的 53-75,周期性的
100 101-108之间波动,波动范围为1%~8%,周期性的 101-111之间波动,波动范围为1%~11%,周期性的 101-111之间波动,波动范围为1%~11%,周期性的 101-140之间波动,波动范围为1%~40%,周期性的

result

sleep 1ms&100个线程压的情况

Sanic波动为1-7ms,而Tornado已经最低到50ms,最高飙到100多ms,显然在10ms以内的接口,并发超过50的,不适合使用Tornado,推荐使用Sanic,Sanic赢一局,Sanic1:0Tornado

sleep 10ms &100个线程压的情况

Sanic波动为11-31ms,而Tornado已经最低到62了,最高到100多毫秒,显然在100毫秒内,并发超过50的时候,还是Sanic更胜一筹,Sanic再赢一局,Sanic2:0Tornado

sleep 50ms&100个线程压的情况

Sanic波动为51-61,Tornado为53-73,两个框架之间差别不大,建议使用Sanic,Sanic3:0Tornado。

sleep 100ms & 100个线程压的情况

Sanic波动为105到130,Tornado波动为101-140,选择谁都可以。这次打个平手Sanic3:1Tornado

综上所述,sanic性能确实优于tornado。所以新框架采用sanic来开发。

0x04 框架设计

  • log库:传递logid和自我生成logid,且能支撑多进程,不丢日志的情况。
  • redis库:拥有连接池,
  • mysql库:拥有连接池。
  • python版本库管理要简单,易发布,易部署。
  • 要有利用新框架新建项目,更新框架的工具,不用用户每次自己下载然后copy,改名。

基于以上的设计,调研了一下用到的库。

sanic

  • python3.7+
  • sanic最新版

redis

redis-py:官方推荐,配合hiredis-py会得到性能的极致提升。

mysql

pymysqlpool:mysql连接池,包装pymysql提供连接池的功能。
还可以使用pymysql+dbutils自己编写连接池的代码。

config

配置文件支持ini格式的,保持跟go的一样。
ConfigParser

官方使用py的配置文件,采用该方式更方便。

logging

  • 日志库要有logid
  • sanic自带有log库,使用的就是python自带的基础库logging。
  • 解决多进程丢日志的问题使用concurrent-log-handler,不要使用ConcurrentLogHandler很久不更新了,bug多。
  • concurrent-log-handler只支持日志大小滚动,不支持时间滚动。
  • 目前python最吃香的log库是loguru,我们也集成了,该库支持多线程,虽然不是进程安全的,但是也有方式支持多进程log。
  • 需要对比下这两个库在sanic下性能,选择一个最优的。
  • logging(logging.handlers.TimedRotatingFileHandler多进程丢日志)
  • logging(concurrent-log-handler),带了进程锁以后严重影响了框架性能.
  • loguru
  • 对于高qps的场景下,可以让其丢日志,使用普通的TimedRotatingFileHandler。对于qps要求低的场景,建议使用concurrent-log-handler保证多进程下日志不丢失。

pipenv

click构建命令行工具

利用click开发。一条命令就能新建一个新的项目,直接可运行。

框架性能

目前框架开发已经完成,内部已经发布了第一个版本,对该框架的性能也进行了一个压测。

sanic空逻辑性能测试(只返回一个json串)

  • 1个线程压1个进程qps:6000
    [外链图片转存失败(img-BIfFmlHV-1564486132773)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-1-0.png?version=1&modificationDate=1551344460885&api=v2)]
  • 1个线程压2个进程qps:6600
    [外链图片转存失败(img-qJTE6AUK-1564486132776)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-19-30.png?version=1&modificationDate=1551345570836&api=v2)]
  • 2个线程压1个进程qps:10000
    [外链图片转存失败(img-0QoilXpj-1564486132777)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-9-38.png?version=1&modificationDate=1551344978585&api=v2)]
  • 4个线程压1个进程qps:9600,单进程支持4个并发时出现瓶颈。
    [外链图片转存失败(img-V7meBSlK-1564486132778)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-14-33.png?version=1&modificationDate=1551345273895&api=v2)]

单进程处理能力比较强,建议优先单进程

  • 2个线程压2个进程qps:11000
    [外链图片转存失败(img-wo5T8inM-1564486132779)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-5-32.png?version=1&modificationDate=1551344733146&api=v2)]
  • 4个线程压4个进程qps:13000
    [外链图片转存失败(img-GuNSWQlh-1564486132784)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-45-30.png?version=1&modificationDate=1551343531237&api=v2)]
  • 8个线程压8个进程qps:14000
    [外链图片转存失败(img-JUR153qO-1564486132786)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-50-31.png?version=1&modificationDate=1551343831785&api=v2)]
  • 16个线程压8个进程qps:13000,瓶颈出现
    [外链图片转存失败(img-XFHhtmXG-1564486132788)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-55-27.png?version=1&modificationDate=1551344128185&api=v2)]

sanic加入log测试(打印一条log到文件,多进程不丢日志,启用进程安全的log)

  • 1个线程压1个进程qps:1500
    [外链图片转存失败(img-zBxk8dny-1564486132788)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-33-52.png?version=1&modificationDate=1551346433148&api=v2)]

  • 1个线程压2个进程qps:1300
    [外链图片转存失败(img-PG31QNwF-1564486132789)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-47-31.png?version=1&modificationDate=1551347252229&api=v2)]

  • 2个线程压1个进程qps:1900
    [外链图片转存失败(img-QnxAf9L4-1564486132791)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-37-36.png?version=1&modificationDate=1551346656957&api=v2)]

  • 4个线程压1个进程qps:2100,但是耗时已经上来了。
    [外链图片转存失败(img-1KtUmhHH-1564486132792)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-42-29.png?version=1&modificationDate=1551346950180&api=v2)]

  • 2个线程压2个进程qps:2000
    [外链图片转存失败(img-NJAnwbI1-1564486132793)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-52-12.png?version=1&modificationDate=1551347533190&api=v2)]

  • 4个线程压4个进程qps:2400,耗时已经增加许多,瓶颈
    [外链图片转存失败(img-QXcF6hUG-1564486132795)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_17-56-53.png?version=1&modificationDate=1551347813472&api=v2)]

  • 8个线程压8个进程qps:2600,耗时增加。
    [外链图片转存失败(img-557784AT-1564486132797)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-2-3.png?version=1&modificationDate=1551348124106&api=v2)]

  • 16个线程压8个进程qps:2800,耗时已经飙升了。

[外链图片转存失败(img-iaN0caBt-1564486132798)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-6-50.png?version=1&modificationDate=1551348410945&api=v2)]

sanic加入log测试(打印一条log到文件,多进程丢日志,不启用进程安全的log)

  • 1个线程压1个进程qps:3200

[外链图片转存失败(img-1R4oDbOU-1564486132799)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-24-33.png?version=1&modificationDate=1551349473601&api=v2)]

  • 1个线程压2个进程qps:2200

[外链图片转存失败(img-sqPx5wHL-1564486132801)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-42-23.png?version=1&modificationDate=1551350543341&api=v2)]

  • 2个线程压1个进程qps:4800
    [外链图片转存失败(img-dmRQiIZn-1564486132803)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-28-51.png?version=1&modificationDate=1551349731483&api=v2)]

  • 4个线程压1个进程qps:4800
    [外链图片转存失败(img-VDQSHUp7-1564486132804)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-33-2.png?version=1&modificationDate=1551349982456&api=v2)]

  • 2个线程压2个进程qps:4000
    [外链图片转存失败(img-1nUruIK1-1564486132806)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-38-17.png?version=1&modificationDate=1551350297944&api=v2)]

  • 4个线程压4个进程qps:5200
    [外链图片转存失败(img-RjN6rqi5-1564486132807)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-48-0.png?version=1&modificationDate=1551350881217&api=v2)]

  • 8个线程压8个进程qps:4400
    [外链图片转存失败(img-fMaT8tbK-1564486132808)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-20-15.png?version=1&modificationDate=1551349215384&api=v2)]

sanic加入redis性能测试

  • redis(set)操作,1个线程压1个进程qps:3700

[外链图片转存失败(img-SuMtJhJN-1564486132808)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-25-58.png?version=1&modificationDate=1551342358845&api=v2)]

  • redis(set)操作,1个线程压2个进程qps:3200,反而降低了。

[外链图片转存失败(img-VXMeEEM7-1564486132809)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-31-48.png?version=1&modificationDate=1551342708962&api=v2)]

  • redis(set)操作,2个线程压1个进程qps:4700
    [外链图片转存失败(img-SAQ0lBTD-1564486132810)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-22-4.png?version=1&modificationDate=1551342124433&api=v2)]

  • redis(set)操作,4个线程压1个进程qps:4600,单进程出现瓶颈。
    [外链图片转存失败(img-tH4T0n8V-1564486132812)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_17-26-31.png?version=1&modificationDate=1551345992059&api=v2)]

  • redis(set)操作,2个线程压2个进程qps:5500

[外链图片转存失败(img-Q7pcyOC8-1564486132815)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-24-29.png?version=1&modificationDate=1551342270259&api=v2)]

  • redis(set)操作,4个线程压4个进程qps:8100

[外链图片转存失败(img-QmklzX2O-1564486132817)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-36-37.png?version=1&modificationDate=1551342998171&api=v2)]

  • redis(set)操作,8个线程压8个进程qps:8000,下降,瓶颈

[外链图片转存失败(img-rXt7GnBu-1564486132817)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-20-50.png?version=1&modificationDate=1551342050887&api=v2)]

  • redis(set)操作,16个线程压8个进程qps:8300,瓶颈

[外链图片转存失败(img-mbhyJbN3-1564486132819)(http://wiki.sftcwl.com/download/attachments/19274227/image2019-2-28_16-25-16.png?version=1&modificationDate=1551342316400&api=v2)]

Redis稳定性较好,且增加线程或者进程呈线性增长,直到到达瓶颈。且尝试增加服务能力的时候,最好是起和并发量一样的进程数,不然来回切进程反而会降低qps。

压测结果分析

建议采用单进程,开启普通log,无包装多进程安全的log。
最后我们测试了下4个线程压一个进程,打印一条log(普通log),set一次redis的业务,qps:3200
[外链图片转存失败(img-TMpNzH08-1564486132820)(http://wiki.sftcwl.com/download/attachments/19279544/image2019-2-28_18-57-39.png?version=1&modificationDate=1551351459395&api=v2)]

在不要求日志不丢的,耗时可以放宽的情况下,可以提升进程数来提升性能。

0x05

虽然sanic框架性能很好,但是python自身的性能,以及python库的一些影响,仍然不能达到go的性能。但是应付一些中小型项目是可以了。后面持续优化,有机会开源出来。

基于sanic打造python web框架相关推荐

  1. “脚踢各大Python Web框架”,Sanic真有这能耐么?

    在Github上,Sanic第一句介绍语就是: "Sanic is a Flask-like Python 3.5+ web server that's written to go fast ...

  2. 篇一、Flask打造 Python Web 开发的灵活框架,实现简易登录。要求有 Python、HTML 和 CSS 基础。

    ⭐ 简介:大家好,我是zy阿二,我是一名对知识充满渴望的自由职业者. ☘️ 最近我沉溺于Python的学习中.你所看到的是我的学习笔记. ❤️ 如果对你有帮助,请关注.点赞,让我们共同进步.有不足之处 ...

  3. python web框架介绍对比

    Django Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django.要说Django是Python框架里最好的,有人同意也有人 坚决反对,但说Django的文档最完善.市场占 ...

  4. python的web框架哪个最好学_2018年要学习的10大Python Web框架

    通过为开发人员提供应用程序开发结构,框架使开发人员的生活更轻松.他们自动执行通用解决方案,缩短开发时间,并允许开发人员更多地关注应用程序逻辑而不是常规元素. 在本文中,我们分享了我们自己的前十大Pyt ...

  5. python web 框架例子_最快的 Python Web 框架入门

    原标题:最快的 Python Web 框架入门 来源:Python开发 ID:PythonPush 速度比较 框架 实现基础 每秒请求数 平均时间 Sanic Python 3.5 + uvloop ...

  6. 一文读懂Python web框架和web服务器之间的关系

    我们都知道 Python 作为一门强大的语言,能够适应快速原型和较大项目的制作,因此被广泛用于 web 应用程序的开发中. 在面试的过程中,大家或多或少都被问到过这样一个问题:一个请求从浏览器发出到数 ...

  7. python写web难受-(2017)你最不建议使用的Python Web框架?

    原标题:(2017)你最不建议使用的Python Web框架? 前言 这是一篇发在知乎专栏的文章,内容是之前我提的「(2017)你最不建议使用的Python Web框架?」下的回答.不过有些话没有说完 ...

  8. python web框架互相融合, Pyramid或取代Django

    Django用久了,难免会感觉到自由度不够.不可否认,这种自由度的牺牲能够带来一些好处.比如,一体化的框架(full-stack framework)能够提供全面的solution,你不需要再为cac ...

  9. python web框架对比_Python六大开源框架对比

    Python 是一门动态.面向对象语言.其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性.除了语言本身的设计目的之外,Python标准 库也是值得大家称赞的,Python甚至还 ...

最新文章

  1. 【微信小程序之画布】四:手指触摸绘波浪线
  2. 机器视觉之医学诊断应用
  3. 5分钟搞定开机引导界面
  4. javascript --- 使用ajax与服务器进行通信
  5. Power BI:M与DAX以及度量与计算列
  6. JAVA 简单的抽奖程序
  7. PAT 1068. 万绿丛中一点红(20)-乙级
  8. 锁屏界面提示某些设置已隐藏_OPPO手机忘记锁屏密码怎么办?教你一招轻松解开!...
  9. mathtype——小白安装
  10. 极速PDF打开文件后工具栏不显示怎么办
  11. Savitzky-Golay 滤波器
  12. 使用scrapy爬取dota2贴吧数据并进行分析
  13. 如何用C++写一个简单的小游戏?
  14. [论文笔记]Rob-GAN: Generator, Discriminator, and Adversarial Attacker(CVPR 2019)
  15. 计算机设计大赛作品抄袭会怎么样,如何界定借鉴和抄袭?看这7位设计大咖怎么说!...
  16. [异常] Encountered a duplicated sql alias [name] during auto-discovery of a native-sql query;
  17. Java EE 7 Hands-on Lab,CDI deployment failure:WELD-000072,解决办法
  18. linux ldap客户端工具,openldap(3)linux客户端 启用ldap、sssd 认证
  19. Java210道常见的面试
  20. (CodeForces) D. Kilani and the Game (搜索)

热门文章

  1. 【经验分享】IT领域7年工作经验和建议
  2. 宋宝华:slab在内核内存管理和用户态Memcached的双重存在
  3. 弥散磁共振影像处理的黎曼 芬斯勒几何方法研究
  4. Restful风格的springMVC配搭ajax请求的小例子
  5. lr_Analysis结果分析工具
  6. 云服务器突发性能实例t5与通用型服务器的区别?
  7. 在idea配置虚拟机参数与虚拟机内存溢出
  8. 虚拟产品哪个平台引流比较好?虚拟产品有哪些平台可以引流
  9. 基于单片机超声波视力保护系统设计-基于51单片机8音键电子琴仿真设计-基于8086八路模拟信号采集均值显示系统设计-基于8086八路数据电压温度采集系统-基于8086波形发生器仿真设计【毕设课设分享】
  10. pdf怎么压缩文件到最小?如何将pdf文档怎么压缩最小?软件工具在线网站哪个好?