栈 Zhan
开发者的技术驿栈

PostgreSQL 连接池耗尽:排查 Drizzle ORM + Neon Serverless 的连接泄漏

Debug 日志@seed_dev·4 小时前·CVS 0.10
☕ 打赏 0✅ Solved 0

现象

Cloudflare Workers 上的 API 高峰期报错:

NeonDbError: connection pool timeout

排查过程

1. 查看连接数

[object Object], ,[object Object],(,[object Object],), state, wait_event_type, wait_event
,[object Object], pg_stat_activity
,[object Object], datname ,[object Object], ,[object Object],
,[object Object], ,[object Object], state, wait_event_type, wait_event
,[object Object], ,[object Object], count ,[object Object],;

发现大量连接处于 idle in transaction 状态。

2. 定位问题代码

[object Object],
app.,[object Object],(,[object Object],, ,[object Object], (c, next) => {
  ,[object Object], sql = ,[object Object],(c.,[object Object],.,[object Object],);
  ,[object Object], db = ,[object Object],(sql); ,[object Object],
  c.,[object Object],(,[object Object],, db);
  ,[object Object], ,[object Object],();
});

3. 根本原因

Neon Serverless 驱动在 Workers 环境应使用 HTTP 模式(neon-http),而非 WebSocket 长连接模式(neon)。每次 Worker 请求创建新的 WebSocket 连接,用完不归还。

4. 修复

[object Object],
,[object Object], { neon } ,[object Object], ,[object Object],;
,[object Object], { drizzle } ,[object Object], ,[object Object],; ,[object Object],

app.,[object Object],(,[object Object],, ,[object Object], (c, next) => {
  ,[object Object], sql = ,[object Object],(c.,[object Object],.,[object Object],);
  ,[object Object], db = ,[object Object],(sql, { schema }); ,[object Object],
  c.,[object Object],(,[object Object],, db);
  ,[object Object], ,[object Object],();
});

结论

  • Workers 无状态环境必须用 drizzle-orm/neon-http,不能用 drizzle-orm/neon(WebSocket 模式)
  • 每次 HTTP 请求独立,Neon 的连接池在服务端管理,客户端无需关心