网站建设使用什么软件网络营销策划书8000字
spring cloud gateway 网关限流
***************************
限流算法:令牌桶
以均匀的速率向令牌桶中添加令牌,令牌数量达到最大后,数量不再增加;
对客户端的请求按key进行分组,请求获得对应令牌桶中的令牌后,发送到后端处理;
如果不能获得令牌,则等待或者服务降级
使用令牌同算法可以有效的应对短时间的大量突发请求
***************************
相关类及接口
RateLimiter:限流接口
public interface RateLimiter<C> extends StatefulConfigurable<C> {Mono<RateLimiter.Response> isAllowed(String routeId, String id);}
RedisRateLimiter:redis限流实现类
@ConfigurationProperties("spring.cloud.gateway.redis-rate-limiter")
public class RedisRateLimiter extends AbstractRateLimiter<RedisRateLimiter.Config> implements ApplicationContextAware {public static final String CONFIGURATION_PROPERTY_NAME = "redis-rate-limiter";public static final String REDIS_SCRIPT_NAME = "redisRequestRateLimiterScript";public static final String REMAINING_HEADER = "X-RateLimit-Remaining";public static final String REPLENISH_RATE_HEADER = "X-RateLimit-Replenish-Rate";public static final String BURST_CAPACITY_HEADER = "X-RateLimit-Burst-Capacity";private Log log = LogFactory.getLog(this.getClass());private ReactiveStringRedisTemplate redisTemplate;private RedisScript<List<Long>> script;private AtomicBoolean initialized = new AtomicBoolean(false);private RedisRateLimiter.Config defaultConfig;private boolean includeHeaders = true;private String remainingHeader = "X-RateLimit-Remaining";private String replenishRateHeader = "X-RateLimit-Replenish-Rate";private String burstCapacityHeader = "X-RateLimit-Burst-Capacity";public Mono<Response> isAllowed(String routeId, String id) {if (!this.initialized.get()) {throw new IllegalStateException("RedisRateLimiter is not initialized");} else {RedisRateLimiter.Config routeConfig = this.loadConfiguration(routeId);int replenishRate = routeConfig.getReplenishRate();int burstCapacity = routeConfig.getBurstCapacity();try {List<String> keys = getKeys(id);List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", Instant.now().getEpochSecond() + "", "1");Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, scriptArgs);return flux.onErrorResume((throwable) -> {return Flux.just(Arrays.asList(1L, -1L));}).reduce(new ArrayList(), (longs, l) -> {longs.addAll(l);return longs;}).map((results) -> {boolean allowed = (Long)results.get(0) == 1L;Long tokensLeft = (Long)results.get(1);Response response = new Response(allowed, this.getHeaders(routeConfig, tokensLeft));if (this.log.isDebugEnabled()) {this.log.debug("response: " + response);}return response;});} catch (Exception var9) {this.log.error("Error determining if user allowed from redis", var9);return Mono.just(new Response(true, this.getHeaders(routeConfig, -1L)));}}}//判断是否通过请求RedisRateLimiter.Config loadConfiguration(String routeId) {RedisRateLimiter.Config routeConfig = (RedisRateLimiter.Config)this.getConfig().getOrDefault(routeId, this.defaultConfig);if (routeConfig == null) {routeConfig = (RedisRateLimiter.Config)this.getConfig().get("defaultFilters");}if (routeConfig == null) {throw new IllegalArgumentException("No Configuration found for route " + routeId + " or defaultFilters");} else {return routeConfig;}}//加载限流配置****************
内部类@Validatedpublic static class Config {@Min(1L)private int replenishRate; //每秒处理的请求数@Min(1L)private int burstCapacity = 1; //每秒最大处理的请求数,一般将此项设置为与replenishRate相同public Config() {
KeyResolver:限流的key接口
public interface KeyResolver {Mono<String> resolve(ServerWebExchange exchange);
}
PrincipalNameKeyResolver:默认根据用户名进行限流
public class PrincipalNameKeyResolver implements KeyResolver {public static final String BEAN_NAME = "principalNameKeyResolver";public PrincipalNameKeyResolver() {}public Mono<String> resolve(ServerWebExchange exchange) {return exchange.getPrincipal().map(Principal::getName).switchIfEmpty(Mono.empty());}
}
***************************
示例
*********************
配置文件
application.yml
spring:cloud:gateway:routes:- id: redis-rate-limiteruri: http://localhost:8080predicates:- Path=/hello/hello2filters:- StripPrefix=1- name: RequestRateLimiterargs:key-resolver: "#{@uriKeyResolver}"redis-rate-limiter.replenishRate: 5redis-rate-limiter.burstCapacity: 10redis:host: 192.168.57.120port: 6379password: 123456
*********************
限流key配置
URIKeyResolver
@Component("uriKeyResolver")
public class URIKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getURI().getPath());}
}
*********************
限流测试