找回密码
 立即注册
首页 业界区 业界 性能提升4倍!使用Granian作为Django项目的ASGI服务器 ...

性能提升4倍!使用Granian作为Django项目的ASGI服务器

官厌 前天 21:05
前言

最近我又继续在开发 DjangoStarter 的新版本了。
之前为了实现 docker 部署,我把 Nginx 打包进了 DjangoStarter 的 compose 配置里了,不过这带来了配置的复杂度,特别是还要搭配框架实现 URL prefix 之类的功能。
从 v3.2.x 版本开始,我就启动了减法计划,简化代码和功能,减少心智负担,这个 Nginx 容器也是我一直想去掉的。
最近发现 Granian 这个 Rust 开发的 ASGI 服务器,性能高,而且还可以支持静态文件,正好完美符合我的需求,于是这次正好拿来替换原本使用的 Daphne
Granian

项目主页: https://github.com/emmett-framework/granian
Granian 是一款高性能 Python Web Server,支持 ASGI、WSGI、RSGI,基于 Rust 编写,启动速度快、并发能力强,非常适合 Django / FastAPI / Starlette。
官方描述为 “A Rust HTTP server for Python applications built on top of Hyper/Tokio”。
特点:

  • 支持 ASGI 3RSGI(Rust-Server-Gateway Interface)和 WSGI 接口。
  • 支持 HTTP/1 和 HTTP/2(未来计划 HTTP/3)协议。
  • 支持静态文件直出 (“Direct static files serving”)。
使用方式

很简单,不需要修改代码,只需要修改启动命令。
目前搭配 DjangoStarter 使用的启动命令是这样的:
  1. granian --interface asgi --host 0.0.0.0 --port 8000 --static-path-route /static --static-path-mount ./static-dist config.asgi:application
复制代码
类似 uvicorn,这个 granian 也支持热重载,加个 --reload 参数就行了
性能测试

本次用 wrk 进行性能测试
测试数据

以下数据在腾讯云 2 cores CPU + 2G 内存的服务器上测得。
django 5.x + ninja + daphne
  1. $ wrk -t4 -c200 -d30s http://127.0.0.1:9876/api/django-starter/monitoring/health
  2. Running 30s test @ http://127.0.0.1:9876/api/django-starter/monitoring/health
  3.   4 threads and 200 connections
  4.   Thread Stats   Avg      Stdev     Max   +/- Stdev
  5.     Latency     1.97s     0.00us   1.97s   100.00%
  6.     Req/Sec    38.55     55.33   343.00     90.23%
  7.   1343 requests in 30.04s, 760.03KB read
  8.   Socket errors: connect 0, read 0, write 0, timeout 1342
  9. Requests/sec:     44.70
  10. Transfer/sec:     25.30KB
复制代码
django 5.x + ninja + granian
  1. $ wrk -t4 -c200 -d30s http://127.0.0.1:9875/api/django-starter/monitoring/hea
  2. lth
  3. Running 30s test @ http://127.0.0.1:9875/api/django-starter/monitoring/health
  4.   4 threads and 200 connections
  5.   Thread Stats   Avg      Stdev     Max   +/- Stdev
  6.     Latency     1.20s    93.05ms   1.72s    82.69%
  7.     Req/Sec    83.13    105.81   460.00     83.72%
  8.   4980 requests in 30.04s, 2.85MB read
  9. Requests/sec:    165.76
  10. Transfer/sec:     97.31KB
复制代码
因为好奇,我还找到之前一个很老的项目,使用WSGI部署的进行对比。
以下数据在私有云的 4 cores CPU + 2G 内存服务器上测得。
因为是完全不同的服务器硬件,数据仅供参考。
Django 3.x + drf + uwsgi + nginx
  1. $ wrk -t4 -c200 -d30s http://127.0.0.1:9001/api/health/
  2. Running 30s test @ http://127.0.0.1:9001/api/health/
  3.   4 threads and 200 connections
  4.   Thread Stats   Avg      Stdev     Max   +/- Stdev
  5.     Latency   295.30ms  373.95ms   1.96s    85.14%
  6.     Req/Sec   205.54     68.42   380.00     73.73%
  7.   19583 requests in 30.09s, 5.83MB read
  8.   Socket errors: connect 0, read 0, write 0, timeout 474
  9.   Non-2xx or 3xx responses: 12
  10. Requests/sec:    650.89
  11. Transfer/sec:    198.32KB
复制代码
Django 3.x + ninja + uwsgi + nginx
  1. $ wrk -t4 -c200 -d30s http://127.0.0.1:9001/api2/health
  2. Running 30s test @ http://127.0.0.1:9001/api2/health
  3.   4 threads and 200 connections
  4.   Thread Stats   Avg      Stdev     Max   +/- Stdev
  5.     Latency   203.75ms  280.30ms   1.95s    88.44%
  6.     Req/Sec   250.81    108.59   500.00     61.21%
  7.   22542 requests in 30.06s, 5.68MB read
  8.   Socket errors: connect 0, read 0, write 0, timeout 420
  9.   Non-2xx or 3xx responses: 12
  10. Requests/sec:    749.88
  11. Transfer/sec:    193.35KB
复制代码
结论

以下是使用 AI 对上面的测试数据进行分析的结论,不过 ASGI 和 uWSGI 不在同一台服务器进行测试,其实很难直接对比。目前看来切换到 Granian 确实可以提高4倍的性能。
① Daphne 在 Django + ASGI 下的性能表现非常差

  • 延迟直接飙到 1.9 秒级别
  • wrk 200 并发几乎把它压扁,
  • 1343 请求里 1342 超时,等于完全顶不住。
说白了:Daphne 更像是开发环境服务器,不推荐上生产高并发。
② Granian 性能比 Daphne 好 3–4 倍,但仍然有限

  • 每秒处理 165 req/s(同机房、同代码)。
  • 延迟仍然在 1.2s 左右,远不算理想(在高并发下仍吃力)。
  • 优点是 ASGI 原生 + Rust 实现,比 Daphne 强太多。
直观感受:Granian 能用,但你别指望它像 uWSGI 那样扛流量。
③ uWSGI(WSGI)表现碾压:单机可达 650–750 req/s 级别

  • 性能直接是 granian 的 4~5 倍
  • 虽然是老架构(WSGI),但调优成熟、稳定、分配机制强,抗压能力远强于同类 ASGI 服务。
简而言之:如果不用异步,WSGI 依旧是 Django 的最强部署方式(性能层面)。
docker-compose

这是精简后的 compose 配置
  1. services:
  2.   app:
  3.     image: ${APP_IMAGE_NAME}:${APP_IMAGE_TAG}
  4.     container_name: $APP_NAME-app
  5.     command:
  6.       - granian
  7.       - --interface
  8.       - asgi
  9.       - --host
  10.       - 0.0.0.0
  11.       - --port
  12.       - "${APP_INTERNAL_PORT:-8000}"
  13.       - --static-path-route
  14.       - /static
  15.       - --static-path-mount
  16.       - /project/static-dist
  17.       - config.asgi:application
复制代码
命令行参数

它的命令行结构很简单:
  1. granian [OPTIONS] APP
复制代码
其中:

  • APP 是入口,例如:config.asgi:application
  • OPTIONS 是各种配置参数
下面按分类整理所有参数(附带说明与建议)。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册