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

前言

最近我又继续在开发 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 使用的启动命令是这样的:

/* by yours.tools - online tools website : yours.tools/zh/togif.html */
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

$ wrk -t4 -c200 -d30s http://127.0.0.1:9876/api/django-starter/monitoring/health
Running 30s test @ http://127.0.0.1:9876/api/django-starter/monitoring/health
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.97s     0.00us   1.97s   100.00%
    Req/Sec    38.55     55.33   343.00     90.23%
  1343 requests in 30.04s, 760.03KB read
  Socket errors: connect 0, read 0, write 0, timeout 1342
Requests/sec:     44.70
Transfer/sec:     25.30KB

django 5.x + ninja + granian

$ wrk -t4 -c200 -d30s http://127.0.0.1:9875/api/django-starter/monitoring/hea
lth
Running 30s test @ http://127.0.0.1:9875/api/django-starter/monitoring/health
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.20s    93.05ms   1.72s    82.69%
    Req/Sec    83.13    105.81   460.00     83.72%
  4980 requests in 30.04s, 2.85MB read
Requests/sec:    165.76
Transfer/sec:     97.31KB

因为好奇,我还找到之前一个很老的项目,使用WSGI部署的进行对比。

以下数据在私有云的 4 cores CPU + 2G 内存服务器上测得。

因为是完全不同的服务器硬件,数据仅供参考。

Django 3.x + drf + uwsgi + nginx

$ wrk -t4 -c200 -d30s http://127.0.0.1:9001/api/health/
Running 30s test @ http://127.0.0.1:9001/api/health/
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   295.30ms  373.95ms   1.96s    85.14%
    Req/Sec   205.54     68.42   380.00     73.73%
  19583 requests in 30.09s, 5.83MB read
  Socket errors: connect 0, read 0, write 0, timeout 474
  Non-2xx or 3xx responses: 12
Requests/sec:    650.89
Transfer/sec:    198.32KB

Django 3.x + ninja + uwsgi + nginx

$ wrk -t4 -c200 -d30s http://127.0.0.1:9001/api2/health
Running 30s test @ http://127.0.0.1:9001/api2/health
  4 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   203.75ms  280.30ms   1.95s    88.44%
    Req/Sec   250.81    108.59   500.00     61.21%
  22542 requests in 30.06s, 5.68MB read
  Socket errors: connect 0, read 0, write 0, timeout 420
  Non-2xx or 3xx responses: 12
Requests/sec:    749.88
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 配置

/* by yours.tools - online tools website : yours.tools/zh/togif.html */
services:
  app:
    image: ${APP_IMAGE_NAME}:${APP_IMAGE_TAG}
    container_name: $APP_NAME-app
    command:
      - granian
      - --interface
      - asgi
      - --host
      - 0.0.0.0
      - --port
      - "${APP_INTERNAL_PORT:-8000}"
      - --static-path-route
      - /static
      - --static-path-mount
      - /project/static-dist
      - config.asgi:application

命令行参数

它的命令行结构很简单:

granian [OPTIONS] APP

其中:

  • APP 是入口,例如:config.asgi:application
  • OPTIONS 是各种配置参数

下面按分类整理所有参数(附带说明与建议)。

🧩 基础参数(启动必要项)

参数说明默认值
APP要启动的应用入口(如 mysite.asgi:application必填
--interface接口类型:asgi / asginl / rsgi / wsgirsgi
--host监听地址127.0.0.1
--port端口8000
--uds使用 Unix Domain Socket
--httpHTTP 版本:12autoauto
--workersWorker 进程数1

👉 Django、FastAPI 用户一般写:

--interface asgi

🗂️ 静态文件服务(Django 专用配置)

Granian 内置静态文件服务:

参数说明默认值
--static-path-routeURL 路由前缀,例如 /static/static
--static-path-mount文件目录,例如 /project/static-dist
--static-path-expires缓存时间(秒)86400

示例:

--static-path-route /static --static-path-mount /project/static-dist

⚙️ 多进程、线程、事件循环选项

Worker / Thread

参数说明
--workersWorker 数量
--blocking-threads阻塞线程数
--runtime-threadsRuntime 线程数
--runtime-blocking-threadsRuntime I/O 阻塞线程

建议:

  • CPU × 2 左右的 worker 容量通常够用
  • 大部分 ASGI 项目不需要调 thread 参数

🔁 事件循环 & Runtime

参数说明
--loop事件循环:autoasynciorloopuvloop
--task-impltask 执行器:asyncio / rust
--runtime-mode单线程 st / 多线程 mt

适用建议:

  • 普通项目:用默认即可
  • 高并发:--task-impl rust 性能更强

🔒 HTTP/1 与 HTTP/2 相关参数

类别常用配置
HTTP/1--http1-buffer-size--http1-keep-alive
HTTP/2--http2-* 一系列参数控制 flow control、窗口、keepalive、stream 数量等

大部分项目无需调整,默认即可。

📜 日志(Logging)

参数说明默认
--log / --no-log启用日志enabled
--log-level日志等级info
--log-config使用 JSON 配置文件
--access-log开启 access logdisabled
--access-log-fmtAccess log 格式

如果你希望生产环境有 Nginx 样式的 access log:

--access-log --access-log-fmt "%a %r %s %b"

🔁 热重载(开发环境用)

参数说明
--reload开启自动重载
--reload-paths指定监控目录
--reload-ignore-*忽略目录、路径、pattern

例如:

--reload --reload-paths src/

🔐 HTTPS

参数说明
--ssl-certificate证书文件
--ssl-keyfile密钥文件
--ssl-caCA
--ssl-client-verify客户端证书验证

(一般反向代理交给 Nginx 做 HTTPS)

🧰 其他有用但不常改的参数

参数说明
--working-dir切换 WorkDir
--env-files加载环境变量文件
--factoryAPP 是 factory function 时使用
--url-path-prefix应用挂载前缀
--process-name自定义进程名
--pid-file写入 PID 文件
--version显示版本
--help显示帮助
微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值