V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
abersheeran
V2EX  ›  Python

一个纯 Python WSGI 服务器

  •  
  •   abersheeran ·
    abersheeran · 24 天前 · 2092 次点击

    https://github.com/abersheeran/zibai

    相比于 gunicorn ,兹白的性能更好,并且可以在 Windows 上直接使用。

    相比于 waitress ,兹白在不使用 gevent 时单进程性能与它相当,在重载情况下比 waitress 更稳定。兹白可以和 gevent 一起使用,并内置了多进程模式。

    兹白还内置了子进程卡死检测,保证了在子进程意外卡死时能得到妥善处理,保证业务稳定。支持了 HUP 、TTIN 、TTOU 信号用于管理子进程,支持零停机更新。使用了 h11 这一被 uvicorn 、httpx 、hypercorn 等库广泛使用的解析器,确保了 HTTP 协议的正确性。


    具体性能测试数据可以查看仓库中的 benchmark 文件。已经在一些公司业务(主要是朋友们的公司业务)上稳定运行,效果良好。还有朋友说运行起来子进程处理请求的均衡性要比 gunicorn 更好。欢迎大家尝试、反馈问题。

    因为兹白是我在维护 uvicorn 时的想法,所以兹白里的多进程管理器我提交 PR 到了 uvicorn 上,这也是 tiangolo 向我捐赠 1000 美金时提到的 PR ,可谓价值千金😝。

    兹白的名称受 gunicorn 、uvicorn 命名的影响,它们都是 unicorn (独角兽)的变种。《山海经》中提到“中曲之山有兽焉,其状如马而白身黑尾,一角,虎牙爪,音如鼓音,其名曰駮,是食虎豹,可以御兵”,《逸周书·王会》又有记载“正北方义渠以兹白,兹白者若白马。锯牙,食虎豹”。所以可以认定兹白就是駮这种长相类似于独角兽的别名,由于駮的名字在 pypi 上已经被使用,于是用了兹白。

    第 1 条附言  ·  22 天前
    今天公司一个服务用的 waitress 发现延迟巨高,切到兹白马上好了。这下也算是正式进入我司自己的产品线了。
    22 条回复    2024-04-12 13:35:44 +08:00
    FanyFull
        1
    FanyFull  
       24 天前 via Android
    赞一个先。得空仔细研习一波。
    dayeye2006199
        2
    dayeye2006199  
       24 天前
    好奇贵司是做什么业务的,有自研这方面基础软件的需求
    shinession
        3
    shinession  
       24 天前
    先 star, 我有用 uvicorn 启动 fastapi, 有机会试试 op 的
    iorilu
        4
    iorilu  
       24 天前
    既然叫中文拼音

    不如干脆用 dujiao 或 dujiaoshou 算了, 好记点
    imzcg2
        5
    imzcg2  
       24 天前
    不支持 fastapi
    abersheeran
        6
    abersheeran  
    OP
       23 天前
    @shinession #3
    @imzcg2 #5

    fastapi 用的 ASGI ,还是用 uvicorn 启动吧。兹白好用的几个特性,一部分已经在 PR 里等合并,一部分正在提交到 uvicorn 的路上。如果用 flask 、django 之类的,再考虑用兹白。
    shinession
        7
    shinession  
       23 天前
    @abersheeran 刚注意到是 WSGI, 那确实不支持 fastapi, 为什么不做 ASGI? flask 有点老了, django 也支持 ASGI 了
    abersheeran
        8
    abersheeran  
    OP
       23 天前 via Android
    @shinession 同步+gevent 生态还是比较无敌的,kui.wsgi 用来跑模型比 fastapi 香多了。
    so1n
        9
    so1n  
       23 天前
    @shinession #7 老不代表不好用啊,gevent+flask 爽多了
    shinession
        10
    shinession  
       23 天前
    @so1n gevent 没用过, 不过 flask 用了有 2 年, 简单是够简单, 个人感觉比起 fastapi 还是少点东西
    abersheeran
        11
    abersheeran  
    OP
       23 天前
    @shinession #10 速来试试 https://kui.aber.sh/wsgi/ 。对于代码能力良莠不齐的团队来说,同步代码要比异步代码更好。新手用 asyncio ,确实是会经常写出来阻塞 loop 的程序。gevent 可以低成本甚至零成本提高同步代码的并发能力,这一点远比 asyncio 强。
    shinession
        12
    shinession  
       23 天前
    @abersheeran #11 回不去了, 架构不能乱改, 团队不是新手, asyncio 问题不大
    founddev
        13
    founddev  
       23 天前
    建议 wsgi+asgi 都支持才有点吸引力,否则一般做业务还是选择 gunicorn+gevent 或者 uvicorn 这种比较成熟的。从个人角度还是可以尝试一下的。
    abersheeran
        14
    abersheeran  
    OP
       23 天前
    @founddev #13 ASGI 有 uvicorn ,我都在维护 uvicorn 了也没必要新开一个项目来对着干。兹白主要解决的就是现有 WSGI 服务器的一些痛点。
    hutoer
        15
    hutoer  
       20 天前
    测试了下,性能不行呀

    测试环境

    OS: Manjaro Linux 23.1.4
    kernel: Linux 6.6.25-1-MANJARO x86_64
    CPU: i5-7500
    MEM: 64 GB

    example.py 是 github 中的例子
    zibai v0.10.2


    $ python -m zibai example:app --max-workers=1000 --no-access-log

    $ wrk -t 8 -c 40 -d 10 http://127.0.0.1:8000
    Running 10s test @ http://127.0.0.1:8000
    8 threads and 40 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 43.96ms 1.94ms 60.47ms 82.18%
    Req/Sec 113.99 12.51 151.00 48.62%
    9087 requests in 10.02s, 0.92MB read
    Requests/sec: 907.12
    Transfer/sec: 94.25KB


    $ waitress-serve --port=8000 --threads=1000 example:app

    $ wrk -t 8 -c 40 -d 10 http://127.0.0.1:8000
    Running 10s test @ http://127.0.0.1:8000
    8 threads and 40 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 4.39ms 5.26ms 155.57ms 98.47%
    Req/Sec 1.25k 282.07 4.03k 81.15%
    99653 requests in 10.10s, 13.97MB read
    Requests/sec: 9867.04
    Transfer/sec: 1.38MB


    $ gunicorn example:app -k gevent --threads=1000

    $ wrk -t 8 -c 40 -d 10 http://127.0.0.1:8000
    Running 10s test @ http://127.0.0.1:8000
    8 threads and 40 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 9.01ms 12.99ms 146.36ms 89.27%
    Req/Sec 1.08k 542.24 3.90k 74.09%
    86008 requests in 10.01s, 14.03MB read
    Requests/sec: 8589.42
    Transfer/sec: 1.40MB
    abersheeran
        16
    abersheeran  
    OP
       20 天前
    @hutoer #15 我看 gunicorn 你开 gevent 了,你装 zibai 的时候带上 gevent 了吗?看启动日志,里面会显示是否启用了 gevent 。
    abersheeran
        17
    abersheeran  
    OP
       20 天前
    @hutoer #15 https://github.com/abersheeran/zibai/blob/main/benchmark.md GitHub 上我的测试结果和你这个差别有点大
    hutoer
        18
    hutoer  
       19 天前
    @abersheeran 启用的。

    python -m zibai example:app --max-workers=1000 --no-access-log
    2024-04-10 14:35:44,944 INFO Listening on 127.0.0.1:8000
    2024-04-10 14:35:45,037 INFO Using gevent for worker pool
    2024-04-10 14:35:45,038 INFO Run in single process mode [268033]
    abersheeran
        19
    abersheeran  
    OP
       19 天前
    @hutoer #18 那有点怪了,我一会用一个低配 Linux 测一下
    abersheeran
        20
    abersheeran  
    OP
       19 天前
    @hutoer #15

    找了一台低配 Linux 服务器跑测试,我发现 -t 8 -c 40 吃不满单核 CPU ,换了一个更高的参数跑。并发更大的是 gunicorn+gevent

    但是看这个数据来说,zibai 的平均请求耗时明明更短,方差更小、最大值也更小。总体并发不知道为什么还没 gunicorn 高,我再深入研究一下。可能 gunicorn 对 Linux 做了针对性优化,毕竟我放在 GitHub 上的 benchmark 来自一台 MacBook ,而那个结果是反过来的,zibai 远高于 gunicorn 。

    ./wrk -t 16 -c 160 -d 1000 http://127.0.0.1:8000
    Running 17m test @ http://127.0.0.1:8000
    16 threads and 160 connections
    ^C Thread Stats Avg Stdev Max +/- Stdev
    Latency 200.00ms 263.38ms 1.47s 81.44%
    Req/Sec 715.51 0.98k 6.19k 86.00%
    254899 requests in 46.36s, 41.57MB read
    Requests/sec: 5498.37
    Transfer/sec: 0.90MB

    ./wrk -t 16 -c 160 -d 1000 http://127.0.0.1:8000
    Running 17m test @ http://127.0.0.1:8000
    16 threads and 160 connections
    ^C Thread Stats Avg Stdev Max +/- Stdev
    Latency 52.27ms 9.08ms 198.67ms 88.68%
    Req/Sec 191.78 23.24 262.00 79.09%
    90721 requests in 29.83s, 9.18MB read
    Requests/sec: 3041.02
    Transfer/sec: 315.20KB
    abersheeran
        21
    abersheeran  
    OP
       18 天前
    @abersheeran #20 查到了,gunicorn 一开 gevent ,连 http 都不自己处理了,全丢给 gevent ,gunicorn 就只管进程。zibai 的用法是只用 gevent monkey patch 。gevent.wsgi 在 Linux 上比 zibai.h11 快的原因还得再查查。
    fzzff
        22
    fzzff  
       17 天前
    https://github.com/emmett-framework/granian 这个也可以了解下, rust 开发性能也不错
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3505 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 04:22 · PVG 12:22 · LAX 21:22 · JFK 00:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.