一个纯 Python WSGI 服务器

230 天前
 abersheeran

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 上已经被使用,于是用了兹白。

3391 次点击
所在节点    Python
22 条回复
FanyFull
230 天前
赞一个先。得空仔细研习一波。
dayeye2006199
230 天前
好奇贵司是做什么业务的,有自研这方面基础软件的需求
shinession
230 天前
先 star, 我有用 uvicorn 启动 fastapi, 有机会试试 op 的
iorilu
230 天前
既然叫中文拼音

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

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

测试环境

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
226 天前
@hutoer #15 我看 gunicorn 你开 gevent 了,你装 zibai 的时候带上 gevent 了吗?看启动日志,里面会显示是否启用了 gevent 。
abersheeran
226 天前
@hutoer #15 https://github.com/abersheeran/zibai/blob/main/benchmark.md GitHub 上我的测试结果和你这个差别有点大
hutoer
226 天前
@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
226 天前
@hutoer #18 那有点怪了,我一会用一个低配 Linux 测一下
abersheeran
225 天前
@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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1029926

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX