我如何在 $5 VPS 上使用 Bun 与 ElysiaJS 构建高性能社交 API(处理 3.6k 请求/分钟)
Source: Dev.to
目标
我想构建一个 Micro‑Social API——一个能够处理类似 Twitter 的动态、关注和点赞的后端服务,同时不让成本失控。
- 预算: 每月 $5 – $20
- 性能: 延迟低于 300 ms
- 规模: 必须能够应对并发负载(压力测试)
大多数教程只会展示 Hello World。本文展示了当你在一台廉价 VPS 上让 25 个并发用户访问 Hello World 时会发生什么(剧透:它会崩溃)。下面是我的解决方案。
技术栈 🛠️
- 运行时: Bun
- 框架: ElysiaJS(最快的 Bun 框架)
- 数据库: PostgreSQL(通过 Dokploy)
- ORM: Drizzle(轻量且类型安全)
- 托管: 使用 Dokploy 的 VPS(Docker Compose)
“糟糕”时刻 🚨
我部署了第一个版本,对我来说运行良好。随后我使用 k6 进行负载测试,模拟 25 个虚拟用户浏览各种动态。
k6 run tests/stress-test.js
结果
✗ http_req_failed................: 86.44%
✗ status is 429..................: 86.44%
服务器并没有崩溃,但几乎拒绝了所有请求。
诊断
我最初把问题归咎于 Traefik(反向代理)。深入代码后,我发现罪魁祸首是 我自己。
// src/index.ts
// OLD CONFIGURATION
.use(rateLimit({
duration: 60_000,
max: 100 // 💀 100 requests per minute... GLOBAL per IP?
}))
由于我的压力测试(以及可能的任何 NAT 企业网络)所有请求都来自同一个 IP,我实际上在对自己进行 DDOS 攻击。
修复措施 🔧
1. 调整速率限制器
我把限制提升到 2,500 请求/分钟。这可以防止滥用,同时允许大量合法流量(或负载均衡器)通过。
// src/index.ts
.use(rateLimit({
duration: 60_000,
max: 2500 // 对标准可靠的 API 来说要好得多
}))
2. 数据库连接池
默认的 Postgres 连接池大小通常很小(比如 10 或 20)。我的 VPS 只有 4 GB RAM;PostgreSQL 需要内存来维护连接,但不需要 那么多。我把池大小提升到 80 个连接。
// src/db/index.ts
const client = postgres(process.env.DATABASE_URL, {
max: 80
});
3. 使用 Docker 实现水平扩展
Node/Bun 是单线程的。单个容器只能有效利用一个 CPU 核心。我的 VPS 有 2 vCPU,于是我在 docker-compose.dokploy.yml 中添加了 replicas 指令:
api:
build: .
restart: always
deploy:
replicas: 2 # 每个核心一个实例!
Traefik 会在两个容器之间自动进行负载均衡,瞬间将吞吐能力翻倍。
最终结果 🟢
再次运行 k6:
k6 run tests/stress-test.js
结果
✓ checks_succeeded...: 100.00%
✓ http_req_duration..: p(95)=200.45ms
✓ http_req_failed....: 0.00% (excluding auth checks)
0 错误,廉价 VPS 上约 200 ms 延迟。
收获
你不需要 Kubernetes 来支撑一个副项目。只要弄清楚瓶颈所在:
- 应用层: 检查速率限制。
- 数据库层: 检查连接池。
- 硬件层: 利用所有核心(复制实例)。
如果想尝试该 API,它已经在 RapidAPI 上发布,名为 Micro‑Social API:
https://rapidapi.com/ismamed4/api/micro-social
祝编码愉快! 🚀