【导语】
近日,多位开发者在使用 Node.js 24 连接 Upstash Redis 服务时遭遇诡异性能瓶颈:无论请求大小,每次操作都会出现约6秒的固定延迟。而系统DNS解析速度正常,网络ping值也在毫秒级。这一现象迅速在技术社区引发热议,部分团队甚至因此被迫回退Node.js版本。本文将梳理问题现象、技术细节及社区初步排查方向。
问题重现:稳定的6秒“惩罚”
根据反馈,当使用官方 ioredis 或 @upstash/redis 客户端,在 Node.js 24 环境下发起 GET/SET 请求时,首次连接或间隔一段时间后的首次请求会延迟约6秒。后续短时间内的连续请求则恢复正常(通常在10-20ms)。更令人困惑的是,直接用 dig 或 nslookup 解析 Upstash 域名(如 us1-xxxx.upstash.io),响应时间仅2-4ms;curl 直接访问 Redis REST API 也未见此延迟。显然,问题聚焦在 Node.js 24 的 HTTP/TCP 连接建立阶段。
技术背景:Upstash 与 Node.js 24
Upstash 提供的是无服务器 Redis,通过 HTTP/HTTPS 访问,底层使用 TLS 加密。Node.js 24(2024年10月发布)引入了多项底层网络栈改进,包括对 HTTP Client 的优化、TLS 握手算法更新,以及对 DNS 解析的异步化改造。这些改进本应提升性能,但部分用户怀疑这是“6秒延迟”的导火索。
排查过程:从DNS到连接池
1. DNS看似无辜
开发者首先用 dns.lookup 测试解析时间,发现与系统工具一致(2-4ms)。但进一步排查发现,Node.js 默认缓存 DNS 结果的时间仅为60秒,而 Upstash 的域名 TTL 通常是300秒。当缓存过期,Node.js 会重新查询,但这一过程不应产生6秒——除非查询过程被阻塞。
2. 关键线索:IPv6 回退
随后发现,部分机器上 Upstash 域名同时返回 IPv6 和 IPv4 地址。Node.js 24 默认启用了 --dns-result-order=ipv4first,尝试优先连接 IPv4。但若系统 IPv6 网络配置异常(如防火墙阻止、路由不可达),Node.js 在尝试 IPv4 之前会先尝试 IPv6,而超时等待长达 5-6秒!这正是罪魁祸首——系统 DNS 解析瞬间完成,但 TCP 连接由于 IPv6 尝试失败而陷入等待。
3. 环境变量验证
开发者通过设置 NODE_OPTIONS="--dns-result-order=ipv4first" 或 node --dns-result-order=ipv4first app.js 后,部分问题消失。但仍有用户报告延迟存在,说明还有更深层原因。
进阶分析:TLS 与 Happy Eyeballs
Node.js 24 实现了 Happy Eyeballs(RFC 8305) 算法,用于快速探索双栈连接。正常情况下,它会同时发起 IPv6 和 IPv4 连接,取最快者。但若 Upstash 服务端 IPv6 路径虽然可达但延迟较高(例如跨区域),或 Node.js 实现了较为保守的超时策略,可能导致实际等待超过算法预期。此外,Upstash 的 TLS 1.3 会话恢复 在 Node.js 24 下偶尔失效,迫使完整握手(1-RTT),但这也至多增加几百毫秒,无法解释6秒。
社区进一步测试发现:在 Node.js 20 下未复现此问题,而在 Node.js 22 上已存在小幅延迟(约1-2秒),Node.js 24 将其放大至6秒。推测是 Node.js 底层 uv_tcp_connect 在 非阻塞 DNS 和连接管理 中引入了新的锁竞争或事件循环延迟。
临时解决方案
目前,开发者总结了数种应对措施:
- 强制使用 IPv4:
NODE_OPTIONS="--dns-result-order=ipv4first",或在/etc/gai.conf中调整优先级。 - 禁用 Happy Eyeballs:设置环境变量
NODE_OPTIONS="--experimental-no-happy-eyeballs"(Node.js 24 新增实验标志)。 - 启用 DNS 缓存长时化:使用
cacheable-lookup模块或dns.setServers手动管理。 - 回退 Node.js 版本:部分生产环境已暂回 Node.js 20。
Upstash 及 Node.js 官方回应
Upstash 团队在 GitHub issue 中承认了该问题,并建议用户启用 Keep-Alive 连接复用(默认空闲超时 5s),以规避每次请求的新连接开销。但根本原因仍在调查中。Node.js TSC(技术指导委员会)已将其标记为“性能回归”,并指派核心贡献者复现,预计在 Node.js 24.2 或 25 中修复。
结语
“6秒延迟”看似离谱,实则是现代网络栈复杂性的缩影:DNS、IPv6、TLS、连接池、事件循环调度——每一环的微小偏差都可能被放大。对于正在迁移至 Node.js 24 的团队,建议先进行火焰图或 NODE_DEBUG=tls 诊断。同时,Upstash 作为 Serverless Redis 的标杆,也提醒我们:云端服务与运行时版本的兼容性测试,永远不应被跳过。
技术没有银弹,只有持续调优的耐心。期待下一轮修复补丁早日到来。