2879 字
14 分钟
数据库流量过大:网关入口限流的四种工程方案

一、问题背景#

当大量请求同时进入系统时,业务服务可能产生大量数据库查询,导致数据库 CPU 升高、连接池耗尽、SQL 执行变慢,甚至服务不可用。

例如:

  • 系统突然收到每秒 10,000 个请求。
  • 数据库在当前业务查询负载下只能稳定承受每秒 2,000 次查询。
  • 如果不限制流量,大量请求可能持续访问数据库,导致数据库过载。

解决思路:在请求进入业务服务之前进行入口限流,减少进入后端的请求量。

注意:请求 QPS 不等于数据库查询 QPS,一个请求可能触发多条 SQL,也可能命中缓存。

二、方案一:Spring Cloud Gateway 限流#

1. 适用场景#

适用于 Java、Spring Cloud 微服务项目,需要在统一入口控制请求流量的场景。

2. 工程流程#

客户端请求 → Spring Cloud Gateway → 限流检查 → 业务服务 → 数据库。

3. 具体实施步骤#

第一步:制定限流规则。

根据接口的重要程度和数据库承载能力设置规则,例如:

  • 单个用户每秒最多请求 10 次。
  • 某个查询接口全局每秒最多放行 200 次。
  • 对复杂报表查询设置更严格的限制。

具体阈值需要通过压测和线上监控确定。

第二步:接入限流组件。

使用 Spring Cloud Gateway 提供的 RequestRateLimiter 过滤器,配合 Redis 限流器实现请求速率限制。

主要配置包括:

  • KeyResolver:确定限流维度,例如用户 ID。
  • RedisRateLimiter:配置令牌桶的填充速率和容量。
  • RequestRateLimiter:在请求转发前执行限流检查。

第三步:处理超限请求。

  • 未超过限制:转发到业务服务。
  • 超过限制:拒绝请求,返回 HTTP 429。
  • 根据业务需要返回统一错误码和友好提示。

第四步:压测与监控。

观察网关请求量、拒绝率、响应时间、数据库 QPS 和连接池使用情况,调整限流规则。

4. 优缺点#

优点:

  • 统一管理多个微服务的入口流量。
  • 与 Spring Cloud 体系集成方便。
  • 可以按用户或接口配置规则。

缺点:

  • 需要部署和维护网关。
  • 仅限制单个用户不能保证数据库安全,还需要接口级全局限制。
  • 使用 Redis 限流时,需要考虑 Redis 的可用性和访问开销。

三、方案二:Nginx 限流#

1. 适用场景#

适用于已有 Nginx 作为反向代理或 HTTP 入口的系统,适合快速实现基础流量保护。

2. 工程流程#

客户端请求 → Nginx → 限流检查 → 后端业务服务 → 数据库。

3. 具体实施步骤#

第一步:确定需要保护的接口。

例如,复杂报表接口 /api/report/query 会执行成本较高的 SQL,需要设置单独的限流规则。

第二步:配置限流规则。

使用 Nginx 的 limit_req_zone 和 limit_req:

http {
limit_req_zone $binary_remote_addr
zone=report_limit:10m rate=5r/s;
server {
location /api/report/query {
limit_req zone=report_limit burst=10;
limit_req_status 429;
proxy_pass http://backend;
}
}
}

配置含义:

  • limit_req_zone:创建限流区域,按客户端 IP 记录请求速率。
  • rate=5r/s:平均速率限制为每秒 5 个请求。
  • burst=10:允许一定程度的短时突发请求。
  • limit_req_status 429:超限时返回 HTTP 429。
  • proxy_pass:通过限流检查后才转发请求。

默认情况下,突发请求可能被延迟处理;如果配置 nodelay,允许的突发请求可以立即处理,但不会改变长期速率限制。

第三步:验证效果。

通过压测确认超限请求被拒绝,并观察后端请求量和数据库负载是否下降。

4. 优缺点#

优点:

  • 配置相对简单。
  • 性能开销较低。
  • 可以在请求进入应用前进行拦截。

缺点:

  • 原生规则主要围绕 IP、请求速率等维度,业务身份识别能力有限。
  • 多个 Nginx 实例独立计数时,不会自动形成统一的全局额度。
  • 需要正确处理反向代理和客户端 IP,避免限流规则失效。

四、方案三:Redis + Lua 分布式限流#

1. 适用场景#

适用于多个应用实例需要共享限流额度,或者需要灵活实现用户级、接口级业务限流的场景。

2. 工程流程#

客户端请求 → 网关或业务服务中的限流代码 → Redis + Lua 检查额度 → 放行或拒绝。

关键点:Redis 负责记录和判断额度,真正执行拦截的是调用 Redis 的代码。

如果在网关中调用 Redis,属于入口限流;如果在业务服务中调用 Redis,则请求已经进入应用,不能完全替代网关防护。

3. 具体实施步骤#

第一步:确定限流维度。

例如:

  • 单用户每秒最多请求 5 次。
  • 整个报表接口每秒最多放行 500 次。

前者防止单个用户占用过多资源,后者控制接口总流量。

第二步:设计 Redis Key。

例如:

rate:user:1001:report:window
rate:global:report:window

分别记录用户级和接口全局级的请求额度。实际实现中,需要正确设计时间窗口或令牌桶状态。

第三步:使用 Lua 原子检查。

将计数更新、额度检查和放行判断放在同一个 Lua 脚本中执行,避免并发请求之间发生计数竞争。

常见算法包括:

  • 固定窗口:实现简单,但窗口边界可能出现突发流量。
  • 滑动窗口:更精细地控制时间范围内的请求数量。
  • 令牌桶:允许一定程度的突发流量,同时限制长期请求速率。

第四步:根据判断结果处理请求。

  • 额度充足:放行请求。
  • 超过限制:返回 HTTP 429。
  • Redis 不可用:根据业务重要性制定故障策略,不能不加判断地全部放行。

第五步:保证集群运行稳定。

考虑 Redis 高可用、故障切换、网络延迟和限流状态的一致性。

4. 优缺点#

优点:

  • 限流规则灵活。
  • 多个实例可以共享限流额度。
  • 适合用户级和全局业务级限流。

缺点:

  • 需要维护 Redis 和限流代码。
  • 每次判断会产生 Redis 访问开销。
  • Redis 故障可能影响请求处理。
  • 应放在合适的入口位置,避免请求已经占用大量业务资源才开始限流。

五、方案四:云 API 网关 / WAF 限流#

1. 适用场景#

适用于部署在云上的系统,希望使用托管式流量管理和安全防护能力的场景。

2. 工程流程#

客户端请求 → 云 API 网关或 WAF → 云上业务服务 → 数据库。

3. 具体实施步骤#

第一步:统一接入云端入口。

让客户端请求通过云 API 网关进入后端,避免客户端绕过网关直接访问业务服务。

第二步:配置流量和安全规则。

例如:

  • 按接口设置请求速率上限。
  • 按账号、用户或 IP 设置请求配额。
  • 对异常流量配置拦截规则。
  • 对不同业务设置不同的流量额度。

需要注意:API 网关主要负责 API 管理与流量控制;WAF 更侧重 Web 攻击检测和恶意流量防护。WAF 不能替代数据库容量保护。

第三步:设置超限处理。

根据云产品的功能设置请求拒绝、错误响应和告警等动作。

第四步:验证防护效果。

观察超限请求是否被拦截、后端请求量是否下降,以及数据库 CPU、连接数和查询延迟是否改善。

4. 优缺点#

优点:

  • 减少自建中间件的部署和维护工作。
  • 可以利用云平台已有的流量管理和安全能力。
  • 适合云上业务的统一入口管理。

缺点:

  • 依赖云厂商的产品能力和计费规则。
  • 复杂的业务级限流可能仍需应用逻辑或 Redis 配合。
  • 必须避免后端存在绕过入口的访问路径。

六、四种方案对比#

方案主要特点适合场景
Spring Cloud Gateway微服务统一入口、规则灵活Java 微服务
Nginx配置简单、入口拦截开销较低已有 Nginx 的系统
Redis + Lua共享额度、业务规则灵活分布式业务限流
云 API 网关 / WAF托管式流量与安全防护云上系统

四种方案不一定互斥。例如,可以使用 Nginx 做基础限流,在 Spring Cloud Gateway 中做业务级限流,并通过 Redis 共享额度。

但不必一开始就全部部署,应根据现有架构、实际瓶颈和维护成本选择。

七、针对数据库过载的推荐方案#

如果是 Java 微服务项目,可以采用以下分层防护方案:

  1. 入口层:网关限流。 限制用户级请求频率和接口总流量,超限请求直接返回 429。
  2. 共享限流层:Redis。 为多个网关实例提供统一额度,避免每台网关各自计数导致总流量超标。
  3. 应用层:并发控制。 使用线程池、并发信号量等机制限制同时执行数据库操作的任务数量。
  4. 数据访问层:连接池保护。 设置最大连接数、获取连接超时和合理的查询超时,避免连接耗尽。
  5. 数据库层:SQL 优化与监控。 排查慢 SQL、检查索引和执行计划,必要时使用缓存、读写分离等措施。

注意:连接池限制的是数据库连接数量,不等于限制每秒查询次数;入口 QPS 也不能直接等同于数据库 QPS。

八、面试口播答案#

如果面试官问:“数据库流量过大时,网关入口限流有哪些工程实现?”

可以这样回答:

网关入口限流常见有四种工程实现。第一种是 Spring Cloud Gateway 自带的限流组件,适合 Java 微服务项目,可以按用户或接口设置请求上限;第二种是 Nginx 限流,通过请求速率限制在 HTTP 入口拦截超限请求;第三种是 Redis 配合 Lua 实现分布式限流,让多个实例共享用户额度和接口额度;第四种是使用云厂商提供的 API 网关或 WAF,利用托管式流量管理和安全防护能力。

针对数据库流量过大的场景,我会优先在入口层限制请求流量,同时通过 Redis 统一协调全局额度,再在应用层控制数据库访问并发,并使用连接池限制最大连接数。最后结合压测、数据库 QPS、慢 SQL、连接池使用率和请求拒绝率持续调整阈值,形成多层防护。

记忆主线:入口限流 → 共享额度 → 应用并发控制 → 连接池保护 → 数据库优化。

相关文章#

数据库流量过大:网关入口限流的四种工程方案
https://blog.xqcherry.top/posts/interview/scenarios/database-overload-gateway-rate-limiting/
作者
xqcherry
发布于
2026-10-23
许可协议
CC BY-NC-SA 4.0