Spring Cloud Gateway限流:基于Redis的请求限流实现

在这里插入图片描述

文章目录

    • 引言
    • 一、Spring Cloud Gateway限流基础
      • 1.1 限流机制概述
      • 1.2 Redis分布式限流原理
    • 二、实现基于Redis的限流方案
      • 2.1 环境准备与依赖配置
      • 2.2 配置限流策略
      • 2.3 自定义限流响应
    • 三、高级应用与最佳实践
      • 3.1 动态限流规则调整
      • 3.2 优先级与降级策略
      • 3.3 监控与告警
    • 总结

引言

在微服务架构中,API网关作为客户端与后端服务之间的中间层,承担着流量控制、安全防护和请求路由等重要职责。随着业务规模的扩大,如何有效保护后端服务免受流量突增影响成为关键挑战。Spring Cloud Gateway作为Spring生态系统中的新一代API网关,提供了强大的限流功能,特别是结合Redis实现的分布式限流方案,为构建高可用、高性能的微服务架构提供了坚实基础。本文深入探讨Spring Cloud Gateway基于Redis的请求限流实现,包括核心原理、配置方法和实践优化。

一、Spring Cloud Gateway限流基础

1.1 限流机制概述

Spring Cloud Gateway的限流功能基于令牌桶和漏桶算法实现,支持单机限流和分布式限流。令牌桶算法以恒定速率向桶中添加令牌,每个请求消耗一个令牌,当桶空时请求被拒绝,适合处理突发流量;漏桶算法则以固定速率处理请求,多余请求等待或拒绝,更适合稳定速率控制。Spring Cloud Gateway通过RequestRateLimiter过滤器工厂将这些算法与路由规则集成,提供灵活的限流配置。

/*** 限流过滤器工厂配置示例*/
@Configuration
public class RateLimiterConfig {/*** 配置基于Redis的限流过滤器工厂*/@Beanpublic RedisRateLimiter redisRateLimiter() {// 参数含义:replenishRate=每秒允许的请求数, burstCapacity=令牌桶容量return new RedisRateLimiter(5, 10);}/*** 自定义限流响应配置*/@Beanpublic KeyResolver ipKeyResolver() {// 使用请求IP作为限流键return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}
}

1.2 Redis分布式限流原理

在分布式环境中,单机限流无法应对集群部署的情况。Spring Cloud Gateway集成了Redis实现分布式限流,核心实现是通过Redis的原子操作和Lua脚本保证在分布式环境下的计数一致性。当请求到达网关时,限流算法通过Redis检查并更新令牌计数,实现跨多个网关实例的统一流量控制。这种方式确保了无论请求被路由到哪个网关实例,都能保持总体流量符合预设限制。

/*** Redis分布式限流的核心Lua脚本逻辑(简化版)* Spring Cloud Gateway内部使用类似实现*/
// 这段代码展示了Redis Lua脚本的核心逻辑
String luaScript = "local tokens_key = KEYS[1] " +"local timestamp_key = KEYS[2] " +"local rate = tonumber(ARGV[1]) " +"local capacity = tonumber(ARGV[2]) " +"local now = tonumber(ARGV[3]) " +"local requested = tonumber(ARGV[4]) " +"local fill_time = capacity/rate " +"local ttl = math.floor(fill_time*2) " +"local last_tokens = tonumber(redis.call('get', tokens_key)) " +"if last_tokens == nil then " +"  last_tokens = capacity " +"end " +"local last_refreshed = tonumber(redis.call('get', timestamp_key)) " +"if last_refreshed == nil then " +"  last_refreshed = 0 " +"end " +"local delta = math.max(0, now-last_refreshed) " +"local filled_tokens = math.min(capacity, last_tokens+(delta*rate)) " +"local allowed = filled_tokens >= requested " +"local new_tokens = filled_tokens " +"if allowed then " +"  new_tokens = filled_tokens - requested " +"end " +"redis.call('setex', tokens_key, ttl, new_tokens) " +"redis.call('setex', timestamp_key, ttl, now) " +"return { allowed, new_tokens }";

二、实现基于Redis的限流方案

2.1 环境准备与依赖配置

实现Redis限流首先需要引入相关依赖,包括Spring Cloud Gateway、Spring Data Redis和Spring Boot Actuator,后者提供了监控端点便于观察限流情况。配置Redis连接信息后,需要启用限流过滤器并定义限流键解析器,确定基于什么维度(IP、用户ID或API路径等)进行限流。

/*** Maven依赖配置*/
// pom.xml依赖配置
// <dependencies>
//     <!-- Spring Cloud Gateway -->
//     <dependency>
//         <groupId>org.springframework.cloud</groupId>
//         <artifactId>spring-cloud-starter-gateway</artifactId>
//     </dependency>
//     
//     <!-- Redis支持 -->
//     <dependency>
//         <groupId>org.springframework.boot</groupId>
//         <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
//     </dependency>
//     
//     <!-- 监控支持 -->
//     <dependency>
//         <groupId>org.springframework.boot</groupId>
//         <artifactId>spring-boot-starter-actuator</artifactId>
//     </dependency>
// </dependencies>/*** 应用配置示例*/
// application.yml基础配置
// spring:
//   application:
//     name: api-gateway
//   redis:
//     host: localhost
//     port: 6379
//   cloud:
//     gateway:
//       routes:
//         - id: user-service
//           uri: lb://user-service
//           predicates:
//             - Path=/api/users/**
//           filters:
//             - name: RequestRateLimiter
//               args:
//                 redis-rate-limiter.replenishRate: 10
//                 redis-rate-limiter.burstCapacity: 20
//                 key-resolver: "#{@ipKeyResolver}"

2.2 配置限流策略

Spring Cloud Gateway支持多种限流策略配置方式,包括基于配置文件的声明式配置和基于代码的编程式配置。对于复杂场景,可以针对不同路由定义不同的限流规则,例如为重要API设置更高的访问限制,为公共API设置较低限制。此外,还可以基于请求属性(如请求方法、请求头和查询参数等)灵活调整限流规则。

/*** 多维度限流配置示例*/
@Configuration
public class RateLimiterConfiguration {/*** 基于IP地址的限流键解析器*/@Beanpublic KeyResolver ipKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}/*** 基于用户标识的限流键解析器*/@Beanpublic KeyResolver userKeyResolver() {return exchange -> Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst("X-User-Id")).defaultIfEmpty("anonymous");}/*** 基于API路径的限流键解析器*/@Beanpublic KeyResolver apiPathKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getPath().value());}/*** 针对不同场景的组合限流键解析器*/@Beanpublic KeyResolver compositeKeyResolver() {return exchange -> {String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");String path = exchange.getRequest().getPath().value();// 组合用户ID和API路径作为限流键return Mono.just(String.format("%s:%s", userId != null ? userId : "anonymous", path));};}
}

2.3 自定义限流响应

当请求被限流时,默认情况下网关返回HTTP 429(Too Many Requests)状态码。为了提升用户体验,可以自定义限流响应,包括返回友好的错误信息、设置重试时间和提供备用资源链接等。通过实现GatewayFilterFactory,可以完全控制限流后的响应处理逻辑。

/*** 自定义限流响应处理*/
@Component
public class CustomRateLimiterGatewayFilterFactory extends RequestRateLimiterGatewayFilterFactory {private final RedisRateLimiter redisRateLimiter;public CustomRateLimiterGatewayFilterFactory(RedisRateLimiter redisRateLimiter) {super(redisRateLimiter);this.redisRateLimiter = redisRateLimiter;}@Overridepublic GatewayFilter apply(Config config) {KeyResolver keyResolver = getKeyResolver(config);return (exchange, chain) -> {Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);return keyResolver.resolve(exchange).flatMap(key -> redisRateLimiter.isAllowed(route.getId(), key)).flatMap(response -> {if (!response.isAllowed()) {// 请求被限流,返回自定义响应ServerHttpResponse serverResponse = exchange.getResponse();serverResponse.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);serverResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);// 构建友好的错误信息Map<String, Object> errorResponse = new HashMap<>();errorResponse.put("code", 429);errorResponse.put("message", "请求频率超限");errorResponse.put("timestamp", System.currentTimeMillis());// 添加限流信息errorResponse.put("allowed", response.getTokensRemaining());errorResponse.put("burst", redisRateLimiter.getBurstCapacity(route.getId()));// 添加重试建议long waitTime = response.getHeaders().getFirst("X-RateLimit-Reset") != null ?Long.parseLong(response.getHeaders().getFirst("X-RateLimit-Reset")) : 1000;errorResponse.put("retryAfter", waitTime);byte[] responseBody = null;try {responseBody = new ObjectMapper().writeValueAsBytes(errorResponse);} catch (JsonProcessingException e) {return Mono.error(e);}return serverResponse.writeWith(Mono.just(serverResponse.bufferFactory().wrap(responseBody)));}// 请求未被限流,添加限流信息到响应头ServerHttpResponse originalResponse = exchange.getResponse();originalResponse.getHeaders().add("X-RateLimit-Remaining", String.valueOf(response.getTokensRemaining()));return chain.filter(exchange);});};}
}

三、高级应用与最佳实践

3.1 动态限流规则调整

在实际业务场景中,限流规则通常需要根据业务波动、系统负载和用户重要性等因素动态调整。Spring Cloud Gateway结合Spring Cloud Config或Nacos等配置中心,可以实现限流规则的动态更新,无需重启服务。更进一步,结合监控系统可以实现自适应限流,根据系统负载自动调整限流阈值。

/*** 动态限流规则配置*/
@Configuration
@RefreshScope
public class DynamicRateLimiterConfig {@Value("${rate-limit.default-replenish-rate:10}")private int defaultReplenishRate;@Value("${rate-limit.default-burst-capacity:20}")private int defaultBurstCapacity;@Bean@RefreshScopepublic RedisRateLimiter redisRateLimiter() {return new RedisRateLimiter(defaultReplenishRate, defaultBurstCapacity);}/*** 路由级别限流配置*/@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("user_service", r -> r.path("/api/users/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()).setKeyResolver(userKeyResolver()))).uri("lb://user-service")).route("order_service", r -> r.path("/api/orders/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(orderRateLimiter()).setKeyResolver(apiPathKeyResolver()))).uri("lb://order-service")).build();}/*** 订单服务专用限流器*/@Bean@RefreshScopepublic RedisRateLimiter orderRateLimiter() {// 为订单服务配置更严格的限流规则return new RedisRateLimiter(5, 10);}
}

3.2 优先级与降级策略

在高负载场景下,除了限流外,还可以结合优先级策略和降级机制提升系统韧性。优先级策略确保重要请求(如付款、订单)优先处理;降级策略则在系统超载时提供备用服务或简化功能。Spring Cloud Gateway可以与Sentinel、Resilience4j等熔断降级框架集成,构建更完善的流量治理方案。

/*** 优先级与降级配置*/
@Configuration
public class ResilienceConfig {/*** 基于用户等级的优先级限流*/@Beanpublic KeyResolver userTierKeyResolver() {return exchange -> {// 获取用户等级String userTier = exchange.getRequest().getHeaders().getFirst("X-User-Tier");// 为不同用户等级设置不同的限流键前缀,从而应用不同的限流策略if ("premium".equals(userTier)) {return Mono.just("premium:" + exchange.getRequest().getPath().value());} else if ("standard".equals(userTier)) {return Mono.just("standard:" + exchange.getRequest().getPath().value());} else {return Mono.just("basic:" + exchange.getRequest().getPath().value());}};}/*** 服务降级逻辑*/@Beanpublic RouterFunction<ServerResponse> fallbackRoute() {return RouterFunctions.route().GET("/fallback", request -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Map.of("message", "服务暂时不可用,请稍后再试"))).build();}/*** 整合限流与熔断的路由配置*/@Beanpublic RouteLocator resilientRoutes(RouteLocatorBuilder builder) {return builder.routes().route("payment_service", r -> r.path("/api/payments/**").filters(f -> f// 配置限流.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()).setKeyResolver(userTierKeyResolver()))// 配置熔断.circuitBreaker(c -> c.setName("paymentCircuitBreaker").setFallbackUri("forward:/fallback"))// 配置超时.setResponseTimeout(Duration.ofSeconds(3))).uri("lb://payment-service")).build();}
}

3.3 监控与告警

有效的限流系统离不开完善的监控和告警机制。Spring Boot Actuator提供了限流指标的监控端点,可以与Prometheus、Grafana等监控系统集成,实时观察限流情况。通过设置合理的告警阈值,当限流频率超过预期时及时通知运维人员,防止系统长时间处于限流状态影响用户体验。

/*** 限流监控配置*/
@Configuration
public class RateLimitMonitoringConfig {/*** 自定义限流指标收集*/@Beanpublic MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {return registry -> registry.config().commonTags("application", "api-gateway");}/*** 限流事件监听器*/@Componentpublic class RateLimitEventListener {private final Counter rateLimitCounter;private final Counter rejectedRequestCounter;public RateLimitEventListener(MeterRegistry registry) {this.rateLimitCounter = registry.counter("gateway.ratelimit.count");this.rejectedRequestCounter = registry.counter("gateway.ratelimit.rejected");}@EventListenerpublic void onRateLimitEvent(RequestRateLimiterEvent event) {rateLimitCounter.increment();if (!event.isAllowed()) {rejectedRequestCounter.increment();// 记录被限流的详细信息log.warn("Rate limited request: key={}, routeId={}", event.getKey(), event.getRouteId());// 检查限流频率,超过阈值时触发告警double rejectRate = rejectedRequestCounter.count() / rateLimitCounter.count();if (rejectRate > 0.2) {  // 拒绝率超过20%时告警sendAlert(event.getRouteId(), rejectRate);}}}private void sendAlert(String routeId, double rejectRate) {// 实现告警逻辑,如发送邮件、短信或调用告警APIlog.error("High rate limit rejection detected: routeId={}, rejectRate={}",routeId, rejectRate);}}
}

总结

Spring Cloud Gateway基于Redis的限流实现为微服务架构提供了强大的流量控制能力。通过令牌桶算法和Redis分布式协调,它能够在集群环境下提供一致的限流体验。本文介绍了限流的基本原理、配置方法和自定义扩展,同时探讨了动态限流规则、优先级策略和监控告警等高级应用。在实际开发中,合理利用这些特性可以构建出更具韧性的API网关,有效保护后端服务免受流量突增影响,提高系统整体可用性。随着微服务架构的不断演进,Spring Cloud Gateway的限流功能将继续发挥重要作用,帮助开发者构建更加健壮的分布式系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903381.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

keil修改字体无效,修改字体为“微软雅黑”方法

在网上下载了微软雅黑字体&#xff0c;微软雅黑参考下载链接 结果在Edit->Configuration中找不到这个字体 这个时候可以在keil的安装目录中找到UV4/global.prop文件 用记事本打开它进行编辑&#xff0c;把字体名字改成微软雅黑 重新打开keil就发现字体成功修改了。 这个…

CSS文字特效实例:猜猜我是谁

CSS文字特效实例&#xff1a;猜猜我是谁 引言 在之前的文章中&#xff0c;我们分别实现了空心文字、文字填充、文字模糊、文字裂开等效果。本文将使用一个小实例&#xff0c;组合使用相关特效&#xff1a;当鼠标悬停在图片上时&#xff0c;其余图片模糊&#xff0c;且文字会上…

美团社招一面

美团社招一面 做题 1、面试题 <style> .outer{width: 100px;background: red;height: 100px; }.inner {width: 50px;height: 50px;background: green; }</style> <div class"outer"><div class"inner"></div> </div>…

InitializingBean接口和@PostConstruct-笔记

1. InitializingBean 简介 1.1 功能简介 InitializingBean 是 Spring 框架中的一个接口&#xff0c;用在 Bean 初始化后执行自定义逻辑。它提供了 afterPropertiesSet() 方法&#xff0c;该方法在以下时机被 Spring 容器自动调用&#xff1a; 属性注入完成后&#xff08;即所…

《代码整洁之道》第9章 单元测试 - 笔记

测试驱动开发 (TDD) 是一种编写整洁代码的“规程”或“方法论”&#xff0c;而不仅仅是测试技术。 JaCoCo 在运行测试后生成详细的覆盖率报告的工具&#xff0c; maven 引用。 测试驱动开发 测试驱动开发&#xff08;TDD&#xff09;是什么&#xff1f; TDD 不是说写完代码…

openGauss新特性 | DataKit支持PostgreSQL到openGauss的迁移能力

Postgresql-\>openGauss迁移工具debezium-connector-postgres 可获得性 本特性自openGauss 7.0.0-RC1版本开始引入。 特性简介 debezium-connector-postgres工具是一个基于Java语言的Postgresql到openGauss的复制工具。该工具提供了初始全量数据及对象&#xff08;视图、…

在MySQL Shell里 重启MySQL 8.4实例

前一段时间看到MySQL官方视频的Oracle工程师在mysql shell里面重启mysql实例&#xff0c;感觉这个操作很方便&#xff0c;所以来试试&#xff0c;下面为该工程师的操作截图 1.MySQL Shell 通过root用户连上mysql&#xff0c;shutdown mysql实例 [rootmysql8_3 bin]# mysqlshMy…

truffle

文章目录 truffle目录结构各文件作用在本地测试合约 truffle 项目来自https://github.com/Dapp-Learning-DAO/Dapp-Learning/blob/main/basic/04-web3js-truffle/README-CN.md Truffle 是基于 Solidity 语言的一套开发框架&#xff0c;它简化了去中心化应用&#xff08;Dapp&…

SpringCloud核心组件Eureka菜鸟教程

关于Spring Cloud Eureka的核心概念 Eureka 是 Netflix 开源的一款基于 REST 的服务发现工具&#xff0c;主要用于中间层服务器的云端负载均衡。它通过维护一个服务注册表来实现服务之间的通信1。在 Spring Cloud 中&#xff0c;Eureka 提供了一个高可用的服务注册与发现机制&a…

职业教育新形态数字教材的建设与应用:重构教育生态的数字化革命

教育部新时代职业学校名师(名匠)名校长培养计划专题 四川省第四批职业学校名师(名匠)培养计划专题 在某职业院校的智能制造课堂上&#xff0c;学生佩戴VR设备&#xff0c;通过数字教材中的虚拟工厂完成设备装配训练&#xff0c;系统实时生成操作评分与改进建议。这一场景折射出…

基于Python的携程国际机票价格抓取与分析

一、项目背景与目标 携程作为中国领先的在线旅行服务平台&#xff0c;提供了丰富的机票预订服务。其国际机票价格受多种因素影响&#xff0c;包括季节、节假日、航班时刻等。通过抓取携程国际机票价格数据&#xff0c;我们可以进行价格趋势分析、性价比评估以及旅行规划建议等…

Windows 图形显示驱动开发-初始化WDDM 1.2 和 PnP

(WDDM) 1.2 及更高版本显示微型端口驱动程序的所有 Windows 显示驱动程序都必须支持以下行为&#xff0c;以响应即插即用 (PnP) 基础结构启动和停止请求。 根据驱动程序返回成功或失败代码&#xff0c;或者系统硬件是基于基本输入/输出系统 (BIOS) 还是统一可扩展固件接口 (UEF…

【1区SCI】Fusion entropy融合熵,多尺度,复合多尺度、时移多尺度、层次 + 故障识别、诊断-matlab代码

引言 2024年9月&#xff0c;研究者在数学领域国际顶级SCI期刊《Chaos, Solitons & Fractals》&#xff08;JCR 1区&#xff0c;中科院1区 Top&#xff09;上以“Fusion entropy and its spatial post-multiscale version: Methodology and application”为题发表最新科学研…

高并发架构设计之缓存

一、引言 缓存技术作为高并发架构设计的基石之一&#xff0c;通过数据暂存和快速访问机制&#xff0c;在提升系统性能、降低后端负载方面发挥着不可替代的作用。优秀的缓存设计能够将系统吞吐量提升数个数量级&#xff0c;将响应时间从秒级降至毫秒级&#xff0c;甚至成为系统…

Unity AI-使用Ollama本地大语言模型运行框架运行本地Deepseek等模型实现聊天对话(一)

一、Ollama介绍 官方网页&#xff1a;Ollama官方网址 中文文档参考&#xff1a;Ollama中文文档 相关教程&#xff1a;Ollama教程 Ollama 是一个开源的工具&#xff0c;旨在简化大型语言模型&#xff08;LLM&#xff09;在本地计算机上的运行和管理。它允许用户无需复杂的配置…

Docker Python 镜像使用指南

1. 使用 Python 镜像创建容器 docker run -itd -v /data:/data python:latest 作用&#xff1a;创建一个基于 python:latest 镜像的容器&#xff0c;并后台运行。 参数说明&#xff1a; -itd&#xff1a;交互式后台运行&#xff08;-i 交互模式&#xff0c;-t 分配伪终端&…

matlab中Simscape的调用-入门

Simscape 是由 MathWorks 公司开发的一款基于物理建模的仿真工具&#xff0c;它建立在 MATLAB/Simulink 平台之上&#xff0c;专门用于建模和仿真多领域物理系统。 主要特点 多领域建模&#xff1a;Simscape 提供了丰富的物理元件库&#xff0c;涵盖了机械、电气、液压、气动…

Flowable7.x学习笔记(十三)查看部署流程图

前言 Flowable 的流程图是 Flowable Modeler 或 Process Editor 中&#xff0c;使用拖拽和属性面板基于 BPMN 2.0 元素&#xff08;如任务、网关、事件、序列流等&#xff09;渲染出的业务流程图形界面​。 一、将图形导出可查看的作用 ① 可视化建模 帮助业务分析师和开发者…

Bootstrap 模态框

Bootstrap 模态框 Bootstrap 模态框&#xff08;Modal&#xff09;是 Bootstrap 框架中的一个组件&#xff0c;它允许你在一个页面中创建一个模态对话框&#xff0c;用于显示内容、表单、图像或其他信息。模态框通常覆盖在当前页面上&#xff0c;提供了一种不离开当前页面的交…

python-69-基于graphviz可视化软件生成流程图

文章目录 1 Graphviz可视化软件1.1 graphviz简介1.2 安装部署2 基于python示例应用2.1 基本示例2.2 解决中文显示乱码2.3 显示多个输出边2.4 显示输出引脚名称2.5 从左至右显示布局2.6 设置节点为方形3 参考附录1 Graphviz可视化软件 1.1 graphviz简介 Graphviz(Graph Visua…