部署在Vercel的站点返回429 TOO_MANY_REQUESTS错误该如何排查
错误原因分析
INTERNAL_FUNCTION_RATE_LIMIT是Vercel对Serverless函数调用的内置限流触发,和站点外部访问流量无关,常见诱因如下:
- Prisma客户端实例重复初始化:你当前的Prisma配置仅在开发环境复用了全局实例,生产环境每次Serverless函数冷启动/调用都会新建PrismaClient实例,频繁冷启动+每次调用都新建数据库连接,会触发Vercel同区域函数的内部调用限流。尤其是你使用了
getServerSideProps,每次页面访问都会触发一次函数调用,就算只有你自己访问,频繁刷新也会快速累积调用次数触达免费/基础套餐的限流阈值。 - 数据库查询耗时过长:你当前的
getPosts查询包含多层关联查询(tags、author、upvoters、comments)+ 模糊搜索+全表count统计,单查询耗时如果超过Vercel函数执行的默认阈值(免费版为10秒),会导致函数自动重试,重复调用累积触发限流。 - 隐式重复请求:页面加载时如果存在资源加载失败自动重试、前端路由跳转时重复触发
getServerSideProps的问题,也会在短时间内产生大量函数调用。
排查步骤
- 查看Vercel函数日志:进入Vercel控制台对应项目的Functions标签,筛选首页路径对应的函数,查看每次调用的耗时、错误日志,确认是否存在调用超时重试、短时间内调用量突增的情况。
- 本地模拟生产环境压测:用生产模式启动项目,多次刷新首页,统计每次
getServerSideProps的执行耗时,确认是否有查询耗时过高的问题。 - 统计函数调用次数:在
getServerSideProps开头添加日志,打印每次请求的时间戳、请求参数,确认是否存在单次页面访问触发多次函数调用的情况。
修复方案
- 优化Prisma客户端生产环境复用逻辑,修改prismaClient配置,生产环境也复用全局实例,避免每次调用都新建连接:
import { PrismaClient } from "@prisma/client"; const globalForPrisma = global as unknown as { prisma: PrismaClient }; export const prisma = globalForPrisma.prisma || new PrismaClient(); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; export default prisma;
- 优化数据库查询:
- 给post表的title、body、authorId、published字段加索引,tag表的slug、name字段加索引,降低模糊搜索和关联查询的耗时。
- 把全表count查询替换为缓存方案,比如定时统计总帖子数存在缓存中,不需要每次访问都执行count统计。
- 非强动态场景下,把
getServerSideProps替换为静态生成+增量更新(ISR),不需要每次访问都触发Serverless函数调用:
// 替换原有getServerSideProps逻辑 export async function getStaticProps({ query }) { // 原有拉取posts的逻辑不变 return { props: { posts, postCount, username }, revalidate: 60, // 按需设置重新生成页面的周期,单位为秒 }; }
- 如果必须使用服务端渲染,可以在Vercel控制台调整对应函数的执行超时时间,最高可调整到30秒,避免查询超时触发重试。
内容的提问来源于stack exchange,提问作者lumenwrites
相关产品推荐
相关产品推荐

