接口限流怎么做:个人项目也能落地的 4 种简单策略

接口限流怎么做:个人项目也能落地的 4 种简单策略

很多个人项目刚上线时流量不大,大家对限流这件事往往不着急。等到哪天接口突然被刷,或者前端某个请求写错了重试逻辑,服务一下子就扛不住,才发现系统里完全没有“刹车”。

限流最容易被误解成大厂专属能力,实际上只要你的接口会被重复调用、被公开访问、或者会连数据库和第三方服务,限流就已经值得做了。

限流真正保护的不是 QPS,而是下游

很多人一提限流,脑子里只有“每秒多少请求”。但对中小项目来说,更关键的是这些问题:

  1. 数据库会不会被同类查询打满
  2. 第三方接口额度会不会被瞬间耗掉
  3. 某个高消耗接口会不会拖垮整站
  4. 单个用户或单个 IP 会不会把共享资源占满

也就是说,限流本质上是在保护系统的关键下游,而不是单纯为了图一个监控曲线好看。

第一种:按 IP 的固定窗口限流

这是最容易上手的一种。思路很简单:给每个 IP 设一个时间窗口,例如 1 分钟,窗口内允许最多 60 次请求,超了就拒绝。

优点是实现简单,适合:

  1. 登录接口
  2. 短信发送接口
  3. 评论或表单提交接口
  4. 公开查询接口

缺点也很明显:窗口切换边界不够平滑,用户可能在窗口交界处瞬间打出双倍请求。

但如果你的目标只是先挡掉最粗暴的滥刷,这种方式已经很有用。

第二种:滑动窗口,处理会更自然

如果你觉得固定窗口太生硬,可以改成滑动窗口。它不是按整块时间粗暴切,而是看最近一段时间里的真实请求数量。

这种方式的好处是:

  1. 请求分布更平滑
  2. 不容易在窗口边界钻空子
  3. 对用户体验更友好

它比固定窗口稍微复杂一点,但如果你已经在用 Redis,做起来并不难。

第三种:令牌桶,更适合有突发流量的接口

有些接口不是一直高频,而是偶尔会出现短时突发。例如:

  1. 页面初始化并发拉多个数据
  2. 某个操作触发前端短时间连点
  3. 业务高峰时用户集中刷新

这时候令牌桶会更合适。它允许一定程度的突发,但整体平均速率仍然可控。

对用户来说,这种方式的感受通常比“硬性一刀切”更自然,因为系统允许短时间 burst,只是不允许长期失控。

第四种:按接口成本分级限流

我更推荐中小项目早点做的一件事,是别把所有接口都当成同一个成本。

例如:

  1. 读缓存接口成本低
  2. 直接查数据库接口成本中等
  3. 带聚合计算或第三方调用的接口成本高
  4. 导出、报表、批处理接口成本最高

如果这些接口全用同一套阈值,最后不是保护不到贵接口,就是把普通接口也限得太死。

更稳的做法是按接口成本做分级:

  1. 轻量接口放宽
  2. 重型接口收紧
  3. 核心接口额外加用户级限制

这样系统资源会更好分配。

限流失败后的返回也要设计

不少项目限流做了,但用户体验依然很差,因为只返回一个模糊的报错。更合理的处理通常是:

  1. 返回明确的状态码
  2. 告知“请求过于频繁”
  3. 最好给出建议重试时间
  4. 前端对应做节流提示,不要继续盲重试

限流不是把用户“拍死”,而是让系统能平稳地拒绝超出能力的请求。

别只盯着网关层,业务层也要看

很多人一提限流,第一反应是放到网关。网关限流当然重要,但业务层也有自己该做的保护。

例如:

  1. 同一个用户每天导出次数限制
  2. 同一个手机号验证码发送频率限制
  3. 某个昂贵查询接口按用户等级限流

这些规则不是通用网关能天然理解的,而是业务层才知道怎么判。

所以更稳的结构通常是:

  1. 网关层挡掉粗暴流量
  2. 应用层兜业务规则

两层都做,系统才会更稳。

中小项目里最容易忽略的 3 个点

1. 只限匿名,不限登录用户

有些系统只按 IP 限,结果登录用户可以一直刷。实际上登录后的高成本接口,往往更需要按用户维度做限制。

2. 被限流后前端疯狂重试

如果前端没有停下来,而是不断重试,被限流接口反而会被打得更厉害。

3. 没有监控和日志

限流不是配完就结束。你至少要知道:

  1. 哪些接口经常触发限流
  2. 是真实流量高,还是恶意请求
  3. 阈值是否过紧或过松

没有这些信息,后面调阈值只能靠猜。

一个更适合个人项目的落地顺序

如果你的项目还不大,我更建议按下面的顺序做:

  1. 先给登录、验证码、评论、搜索接口做基础限流
  2. 再给高成本接口加用户级限制
  3. 如果已有 Redis,再升级成滑动窗口或令牌桶
  4. 最后补监控、告警和更细的分级策略

这样做实现成本不高,但对系统稳定性的提升会非常直接。

结语

限流不是为了让系统显得“高级”,而是给项目一个最基本的保护边界。对个人项目来说,真正有价值的不是一上来就堆复杂算法,而是先把最容易失控的接口拦住。

只要先做出第一层保护,后面再慢慢细化,你的服务韧性就已经和完全裸奔的系统不一样了。