我如何在 $5 VPS 上使用 Bun 与 ElysiaJS 构建高性能社交 API(处理 3.6k 请求/分钟)

发布: (2026年1月13日 GMT+8 13:08)
4 分钟阅读
原文: Dev.to

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

祝编码愉快! 🚀

Back to Blog

相关文章

阅读更多 »