调研 gunicorn && uwsgi 性能

背景: 随着业务增长,API 接口 499,502 的数量也呈现增长的趋势。当下使用的 nginx + gunicorn + flask 的框架结构看起来已经到达了瓶颈。
故探索使用 nginx + uwsgi + flask 的架构来提示性能。

名词解释:gunicorn/uwsgi都是wsgi协议(python web server gateway interface)的实现,
它们做的事情是协议转换,协议的一头是web app(如flask, django等framework的app),
另一头是web server(如apache, nginx等),gunicore/uwsgi在默认的情况下都是同步模型,
但都比通常的web framework实现得好。

使用的版本:

gunicorn==20.0.4
 
uWSGI==2.0.20

测试服务器信息:

CPU&内存
8核16 GiB
操作系统
Ubuntu 16.04 64位更换操作系统
实例规格
ecs.t5-c1m2.2xlarge(性能约束实例)升降配
实例规格族
ecs.t5

开始测试:

uwsgi 配置详情

# http 方式
[uwsgi]
http = :5001
chdir = /home/www/xxx/xxx/
wsgi-file = scripts/web.py
callable = app
processes = 1,4,8,16
threads = 1
 
# socket 方式
[uwsgi]
module = scripts.web:app
 
master = true
processes = 1,4,8,16
 
socket = hebe.sock
chmod-socket = 660
vacuum = true
 
die-on-term = true

gunicorn 配置详情

./ve gunicorn --preload \
     --backlog 2 \
     -w 1, 4, 8, 16 \
     -b 10.111.1.180:8011 \
     -b 127.0.0.1:8011 \
     -c /home/www/xxx/xxx/scripts/gunicorn_config.py \
     scripts.server:app

测试工具 wrk

`[root@jerrik /]# wrk -t12 -c100 -d30s [http://www.baidu.com ](http://www.baidu.com%20/)`
`Running 30s test @ [http://www.baidu.com](http://www.baidu.com/)`
`12 threads and 100 connections`
`Thread Stats   Avg      Stdev     Max   +/- Stdev`
`Latency   211.76ms  304.92ms   1.97s    88.17%`
`Req/Sec    72.93     68.72   797.00     90.97%`
`23725 requests in 30.05s, 347.47MB read`
`Socket errors: connect 0, read 48, write 0, timeout 50`
`Requests/sec:    789.57`
`Transfer/sec:     11.56MB`
解释说明
  • 12 threads and 100 connections:
    • 总共是12个线程,100个连接(不是一个线程对应一个连接)
  • latency和Req/Sec:
    • 代表单个线程的统计数据,latency代表延迟时间,Req/Sec代表单个线程每秒完成的请求数,他们都具有平均值, 标准偏差, 最大值, 正负一个标准差占比。一般我们来说我们主要关注平均值和最大值. 标准差如果太大说明样本本身离散程度比较高. 有可能系统性能波动很大.
  • 23725 requests in 30.05s, 347.47MB read
    • 在30秒之内总共有23725个请求,总共读取347.47MB的数据
  • Socket errors: connect 0, read 48, write 0, timeout 50
    • 总共有48个读错误,50个超时.
  • Requests/sec和Transfer/sec
    • 所有线程平均每秒钟完成了789.57个请求,每秒钟读取11.56MB数据量

CPU 密集型测试:

@app.route('/py.cpu')
def python_cpu():
    """
    测试 cpu 性能
    :return:
    """
    def double_fact(x):
        ans = 1
        for i in range(1, x + 1):
            if i % 2 == x % 2:
                ans *= i
        return ans
 
    def asin(x, t):
        answer = 0
        for k in range(0, t + 1):
            a = (double_fact(2 * k - 1) / double_fact(2 * k)) * (pow(x, 2 * k + 1) / (2 * k + 1))
            print("k=%d,a=%s" % (k, a))
            answer += a
 
        return answer
    app.logger.info(asin(1, 100) * 2)
    return success(dict(version=sys.version))

IO 密集型测试:

@app.route("/py.io")
def python_io():
    """
    测试网络 io 性能
    :return:
    """
    import requests
 
    url = "https://www.idejian.com/"
    requests.get(url)  # 发get请求
    app.logger.info(sys.version)
 
    return success(dict(version=sys.version))

结果比较: ./wrk -t 16 -c 100 -d 10 https://xxxx.com/py.cpu

CPU 密集型API

20211217182527.jpg

结果比较: ./wrk -t 16 -c 100 -d 10 https://xxxx.com/py.io

IO 密集型API

20211217182648.jpg

结论:同步调用下,uwsgi 并没有比 gunicorn 更高性能。和预期不符,不知道是否是测量的方式有问题。 暂时不考虑使用 uwsgi ,继续优化 gunicorn

gunicorn 优化项目

  • 调整进程数据为 cpu *2 + 1
  • gunicorn worker_class = "eventlet"
  • gunicorn preload 关掉
  • gunicorn backlog 调整为 2048
在测试环境中测下来,上面的四项调整有明显的性能提升,但也带来了新的问题。
  • 异步的为每个连接创建一个“绿色”线程,在处理IO机密型程序时,有明显的性能提升。
  • 弊端是为每个连接创建一个“绿色”线程,在高峰期的时候,mysql 等其他有连接池的工具,不能提供足够的链接。导致程序报错。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容

  • 前言: 该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新. http://xi...
    amyhy阅读 2,387评论 0 0
  • CD-Python-JY-1809班项目阶段教学内容 开篇 - 就业形势分析 就业方向Python后端开发工程师(...
    ychaochaochao阅读 940评论 0 1
  • 为什么学习Python? 通过什么途径学习的Python? 上网收集视频,资料 关注公证号 买教程,书籍 Pyth...
    130920阅读 1,202评论 0 0
  • 看了很多文章,很多大牛都提到要关注自己程序的性能问题。比如说,除了你的程序可以work之外,还需要考虑你的程序的c...
    DayDayUpppppp阅读 2,307评论 0 1
  • 安装Nginx:yum install -y nginxsystemctl start nginxsystemct...
    碧潭飘雪ikaros阅读 697评论 0 1