SpringCloud gateway RequestRateLimiter 源码串联分析
2021/10/24 9:09:28
本文主要是介绍SpringCloud gateway RequestRateLimiter 源码串联分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
看了一遍 SpringCloud gateway RequestRateLimiter
源码,本文来串联分析下它是如何用自动化部署方式提供默认的 RedisRateLimiter
支持的。
本文基于 3.1.0-SNAPSHOT 版本的源码进行分析。
自动注入拦截器工厂
GatewayAutoConfiguration
类中关于限流拦截器实例注入的代码如下:
@Bean(name = PrincipalNameKeyResolver.BEAN_NAME) @ConditionalOnBean(RateLimiter.class) @ConditionalOnMissingBean(KeyResolver.class) @ConditionalOnEnabledFilter(RequestRateLimiterGatewayFilterFactory.class) public PrincipalNameKeyResolver principalNameKeyResolver() { return new PrincipalNameKeyResolver(); } @Bean @ConditionalOnBean({ RateLimiter.class, KeyResolver.class }) @ConditionalOnEnabledFilter public RequestRateLimiterGatewayFilterFactory requestRateLimiterGatewayFilterFactory(RateLimiter rateLimiter, KeyResolver resolver) { return new RequestRateLimiterGatewayFilterFactory(rateLimiter, resolver); }
它需要容器中存在两种类的实例 { RateLimiter.class, KeyResolver.class }
,这个条件默认是成立的,因为 GatewayRedisAutoConfiguration
这个类默认为它注入了 RateLimiter
的实现类RedisRateLimiter
实例:
@Bean @ConditionalOnMissingBean public RedisRateLimiter redisRateLimiter(ReactiveStringRedisTemplate redisTemplate, @Qualifier(RedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript<List<Long>> redisScript, ConfigurationService configurationService) { return new RedisRateLimiter(redisTemplate, redisScript, configurationService); }
这样的话,就创建了限流拦截器了。
限流拦截器这两个属性,它们主要用于提供默认的限流算法和请求唯一性 Key 生成这两项信息的。如果程序中想要改变它们的实现类,可以修改拦截器的配置,指定这两个实例引用的 Bean 的名称,这个拦截器的配置类是这样定义的:
public static class Config implements HasRouteId { private KeyResolver keyResolver; private RateLimiter rateLimiter; private HttpStatus statusCode = HttpStatus.TOO_MANY_REQUESTS; private Boolean denyEmptyKey; private String emptyKeyStatus; private String routeId; }
属性装配
C routeConfig = newConfig(); if (this.configurationService != null) { this.configurationService.with(routeConfig).name(this.configurationPropertyName).normalizedProperties(args).bind(); }
配置文件中的:
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: https://example.org filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20
args
参数是怎么被使用的呢?
name
指定的 FilterFactory
类全局有几个,针对每个 Route
的不同配置又是怎么处理的呢?
针对 RedisRateLimiter
的实例的参数配置是怎么在调用 isAllowed
时绑定到特定 Route 上的,这个过程还没有整理明白:
public Mono<Response> isAllowed(String routeId, String id) { if (!this.initialized.get()) { throw new IllegalStateException("RedisRateLimiter is not initialized"); } Config routeConfig = loadConfiguration(routeId); // How many requests per second do you want a user to be allowed to do? int replenishRate = routeConfig.getReplenishRate(); // How much bursting do you want to allow? int burstCapacity = routeConfig.getBurstCapacity(); // How many tokens are requested per request? int requestedTokens = routeConfig.getRequestedTokens(); 。。。后面源码略 }
从这段代码来看,每次调用限流方法 isAllowed
时,读取到的 RouteConfig
中配置都是与该路由有关的。
启示录
因配置可以指定不同 routeId
都指向同一个拦截器工厂,而拦截器工厂实例是单例的,那么各个路由对应的拦截器实例的创建必定是依赖于对应的 args
配置,这样的话 apply(Config)
创建的拦截器实例就是各路由特有的了。
这篇关于SpringCloud gateway RequestRateLimiter 源码串联分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28微服务架构中API版本控制的实践
- 2024-09-28AI给的和自己写的Python代码,都无法改变输入框的内容,替换也不行
- 2024-09-27Sentinel配置限流资料:新手入门教程
- 2024-09-27Sentinel配置限流资料详解
- 2024-09-27Sentinel限流资料:新手入门教程
- 2024-09-26Sentinel限流资料入门详解
- 2024-09-26Springboot框架资料:初学者入门教程
- 2024-09-26Springboot框架资料详解:新手入门教程
- 2024-09-26Springboot企业级开发资料:新手入门指南
- 2024-09-26SpringBoot企业级开发资料新手指南