spring cloud gateway整合redis实现限流问题

gateway 依赖


	org.springframework.cloud
	spring-cloud-starter-gateway

redis 依赖


	org.springframework.boot
	spring-boot-starter-data-redis-reactive

配置文件

spring:
  application:
    name: gateway-limit
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: test-ip
          # 转发的服务名称
          uri: lb://test-ip
          # 请求路径
          predicates:
            - Path=/test-ip/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter:
                  replenishRate: 1
                  burstCapacity: 2
                key-resolver: '#{@ipKeyResolver}'

这个依赖正常启动,但是 spring-boot-starter-data-redis-reactive 默认使用的 redis client 是 lettuce,这个在连接网络时会有问题

如何通过客户端程序连接Redis_云数据库 Redis 版-阿里云帮助中心

连接最后有介绍

所以改成了 jedis


	org.springframework.boot
	spring-boot-starter-data-redis-reactive
	
		
			lettuce-core
			io.lettuce
		
	



	redis.clients
	jedis



	org.apache.commons
	commons-pool2

在连接过程中也是有问题,最终源码打断点跟到了 LettuceConnectionFactory 和 JedisConnectionFactory,发现 LettuceConnectionFactory 加了一个接口 ReactiveRedisConnectionFactory,而 JedisConnectionFactory 没有,导致了这个问题。

public class LettuceConnectionFactory
		implements InitializingBean, DisposableBean, RedisConnectionFactory, ReactiveRedisConnectionFactory {

public class JedisConnectionFactory implements InitializingBean, DisposableBean, RedisConnectionFactory {
package org.springframework.cloud.gateway.config;

import java.util.List;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.validation.Validator;
import org.springframework.web.reactive.DispatcherHandler;

@Configuration
@AutoConfigureAfter(RedisReactiveAutoConfiguration.class)
@AutoConfigureBefore(GatewayAutoConfiguration.class)
@ConditionalOnBean(ReactiveRedisTemplate.class)
@ConditionalOnClass({ RedisTemplate.class, DispatcherHandler.class })
class GatewayRedisAutoConfiguration {

	@Bean
	@SuppressWarnings("unchecked")
	public RedisScript redisRequestRateLimiterScript() {
		DefaultRedisScript redisScript = new DefaultRedisScript<>();
		redisScript.setScriptSource(new ResourceScriptSource(
				new ClassPathResource("META-INF/scripts/request_rate_limiter.lua")));
		redisScript.setResultType(List.class);
		return redisScript;
	}

	@Bean
	// TODO: replace with ReactiveStringRedisTemplate in future
	public ReactiveRedisTemplate stringReactiveRedisTemplate(
			ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
		RedisSerializer serializer = new StringRedisSerializer();
		RedisSerializationContext serializationContext = RedisSerializationContext
				.newSerializationContext().key(serializer)
				.value(serializer).hashKey(serializer).hashValue(serializer).build();
		return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory,
				serializationContext);
	}

	@Bean
	@ConditionalOnMissingBean
	public RedisRateLimiter redisRateLimiter(
			ReactiveRedisTemplate redisTemplate,
			@Qualifier(RedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript> redisScript,
			Validator validator) {
		return new RedisRateLimiter(redisTemplate, redisScript, validator);
	}

}

gateway 与 redis 的自动装配类 GatewayRedisAutoConfiguration 中需要 ReactiveRedisConnectionFactory 这个 bean。

由此得知,还是使用 redis 默认的客户端。jedis 不支持响应式连接。

你可能感兴趣的:(redis,限流,redis,spring,java)