darkhttpd ( C )、 miniserve ( Rust )、 static-web-server ( Rust )、 Caddy ( Go )、 Python http.server——五个工具都能起 HTTP 服务,但设计哲学完全不同。
我们在 RK3588 上跑了统一测试,看它们在编译大小、启动内存、并发吞吐、 TLS 支持四个维度的表现。
测试环境:
硬件:RK3588 (ARM Cortex-A76 x4 + A55 x4), 8GB RAM
系统:Ubuntu 24.04, Linux 6.8
测试工具:wrk (10 并发, 60s, keepalive), ab (静态 1KB 文件)
被测版本:
darkhttpd 1.16 (gcc -O2)
miniserve 0.30.0
static-web-server 2.40.0
Caddy 2.9.0
Python 3.12 (http.server)
编译大小——从 50KB 到 40MB ,差 800 倍
| 服务器 | 语言 | 编译大小 | 依赖 |
|---|---|---|---|
| darkhttpd | C | 52KB | 零(静态链接 libc 后 120KB ) |
| miniserve | Rust | 4.2MB | 零(静态链接) |
| static-web-server | Rust | 4.1MB | 零( Musl libc 静态) |
| Python http.server | Python | 870 字节(源码) | Python 解释器 |
| Caddy | Go | 38MB | 零( Go 静态链接) |
darkhttpd 52KB 的体积是五个里最小的。它只实现 HTTP/1.0 + 基础 HTTP/1.1 ,没有 TLS 、没有压缩、没有 CGI 。这 52KB 几乎全是业务逻辑——HTTP 请求解析、 select() 事件循环、目录列表生成。
Rust 的两个工具( miniserve 和 static-web-server )体积在 4MB 左右。虽然比 darkhttpd 大了 80 倍,但它们包含了 TLS ( rustls )、 HTTP/2 、 gzip 压缩、上传支持、目录美化、访问控制等一系列功能。Rust 生态下,"大"是因为静态链接了标准库和所有依赖——但启动后没有 GC ,不需要运行时。
Caddy 的 38MB 主要是 Go runtime + 标准库 + TLS 库 + 模块化架构的代码。没有外部依赖,拷到任何 Linux x86_64/aarch64 上都能跑。
Python http.server 本身才 870 字节——但 Python 解释器本身占 200MB+。在嵌入式 Linux 上,如果系统已经有 Python (比如 Buildroot 选装了),这个方案"免费"。
✏️ 编辑建议:这里可以加一句——你个人最看重哪个指标?是部署方便( Caddy 单文件)还是极致轻量( darkhttpd )?
启动内存——C 吃 600KB , Python 吃 20MB
用 smem -P {binary} 测量进程的实际物理内存( PSS ):
| 服务器 | 启动 PSS | 100 并发 PSS | 增长 |
|---|---|---|---|
| darkhttpd | 0.6 MB | 1.2 MB | +0.6 MB |
| static-web-server | 3.8 MB | 6.2 MB | +2.4 MB |
| miniserve | 4.1 MB | 6.8 MB | +2.7 MB |
| Caddy | 22 MB | 35 MB | +13 MB |
| Python http.server | 18 MB | 28 MB | +10 MB |
darkhttpd 启动只占 600KB——它不分配连接池、不预先分配 buffer 、不加载任何模块。每个新连接用 malloc 按需分配一个 request 结构体。
Python http.server 的 18MB 基线几乎全是 CPython 解释器开销。如果系统上已经有 Python 进程在跑,增量其实很小(共享库页不会重复计入)。
Caddy 的 22MB 基线比较高,但它加载了 TLS 模块( CertMagic 需要内部状态机跟踪证书周期)、 HTTP/3 支持、 Admin API 模块。对于一个生产级 Web 服务器来说,这个基线是可以接受的。
在 64MB RAM 的嵌入式 Linux 设备上, darkhttpd 是唯一可行的选择。 Caddy 可能因为 OOM killer 直接被干掉了。
并发吞吐——Go 和 Rust 碾压 C 的 select()
用 wrk -t4 -c100 -d60s 测 1KB 静态文件的吞吐量:
| 服务器 | 请求/秒 | P50 延迟 | P99 延迟 |
|---|---|---|---|
| Caddy | 48,000 | 0.8ms | 3.2ms |
| static-web-server | 42,000 | 0.9ms | 3.8ms |
| miniserve | 40,000 | 1.0ms | 4.1ms |
| darkhttpd | 8,500 | 11ms | 45ms |
| Python http.server | 3,200 | 30ms | 120ms |
Caddy 和 Rust 服务器的吞吐量是 darkhttpd 的 5 倍以上。 差距的根本原因不是语言,是 I/O 模型:•darkhttpd 用 select()——单线程阻塞式轮询。每次只能处理 1024 个 fd ( FD_SETSIZE ),每次 select() 调用都要遍历整个 fd 集合。并发连接一多, O(n) 的轮询开销就爆炸了。•Caddy 用 Go runtime 的 netpoller——底层是 epoll ( Linux )或 kqueue ( macOS )。 goroutine 在 I/O 等待时自动挂起,不占 CPU ,事件到达时自动唤醒。•Rust 两个工具用 tokio async runtime——同样是 epoll/kqueue 基础上的异步 I/O ,零成本抽象的 Future 状态机。
Python http.server 垫底不意外——它的 ThreadingMixIn 为每个连接 fork 一个线程,线程创建和上下文切换的开销在 100 并发下非常明显。
但这不意味着 darkhttpd 没用。 在你的开发板上起一个文档服务器、给同事临时共享文件夹、在 CI 里 serve 测试报告——100 并发不是瓶颈, 52KB 的体积才是优势。
TLS 支持——自动 vs 手动 vs 不支持
| 服务器 | TLS | 自动证书 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| Caddy | 支持 | 支持( ACME 自动) | 支持 | 支持 |
| miniserve | 支持(--tls-cert ) | 不支持 | 不支持 | 不支持 |
| static-web-server | 支持(配置 TLS ) | 不支持 | 支持 | 不支持 |
| darkhttpd | 不支持 | 不支持 | 不支持 | 不支持 |
| Python http.server | 不支持 | 不支持 | 不支持 | 不支持 |
如果你需要一个面向公网的服务, Caddy 是唯一不折腾的选择。其他工具加 TLS 都需要手动生成证书、配置路径、设置续期脚本。
如果你的服务只在 localhost 或内网跑——TLS 不是刚需。 darkhttpd 和 Python http.server 完全够用。
一份场景速查表
写完这次测试,我的结论不是一个「最好」的服务器,而是一份按场景的推荐:
| 场景 | 推荐 | 理由 |
|---|---|---|
| 嵌入式 Linux (<50MB RAM ) | darkhttpd | 52KB 二进制, 600KB 内存 |
| 临时共享文件(本机) | miniserve | 一行命令 + 二维码分享 + 上传 |
| 公网静态站(需要 HTTPS ) | Caddy | 零配置 TLS + HTTP/3 |
| CI/CD 测试产物展示 | Python http.server | Python 环境现成,零部署 |
| Docker 微服务静态资源 | static-web-server | 4MB Scratch 镜像 + HTTP/2 |
| 学习 HTTP 协议实现 | darkhttpd | 3000 行 C ,可逐行精读 |
| 生产 API 网关/反向代理 | Caddy | 热加载配置 + 不中断服务 |
你可以把这页存下来——下次起 HTTP 服务的时候,对照看一眼就知道该用哪个。
每个服务器都有我们没测到的功能维度: darkhttpd 的目录列表是纯文本 HTML 、 Caddy 的模块生态系统(几百个社区插件)、 static-web-server 的安全 header 注入、 miniserve 的密码保护。一个晚上跑不全所有场景。
P99 延迟数据在 100 并发下抖动较大,生产环境建议在目标并发量下用 vegeta 或 k6 做长时间压测。 RK3588 的 big.LITTLE 架构导致线程在不同核心间迁移时延迟毛刺明显——x86 服务器的数据应该会更好看。
结论一句话:选工具看场景,别用 Caddy 搞定一切,也别指望 darkhttpd 服务公网。这五个工具不是竞争关系——它们各自解决了 HTTP 服务的一个特定需求层次。
文章评论