Ограничение скорости api Rest с использованием spring cloud gateway не работает

#spring-boot #spring-webflux #java-11 #spring-cloud-gateway

Вопрос:

Я попытался запустить, но я не понимаю, почему не отображается ошибка, когда возникает ограничение скорости для rest api.

GatewaySecureRateLimiterTest — я наблюдаю только за успешностью запросов, но не вижу ошибок при ограничении запросов.

Кроме того, я хотел бы уточнить для себя (я не нашел этого в документации):

Я хотел бы уточнить для себя (я не нашел этого в документации):

  • как изменить код ошибки на адрес, на который был отправлен ответ о том, что ресурс в данный момент занят
  • можно ли собрать статистику и посмотреть, какой IP генерирует больше запросов, чем может обработать наша конечная точка
  • ограничение скорости может быть настроено только с помощью *. yml, или оно также может быть настроено с помощью Java, в то время как ?
  • Я хотел бы увидеть это в тестах. что такое ограничение-оно срабатывает и получает подробную информацию(например, с какого IP и сколько запросов и в какую единицу времени).
  • Я также не до конца понял, в чем смысл этих параметров:
    • ключевой определитель: «#{@userRemoteAddressResolver}»
    • ограничитель скорости повторного использования.Ставка пополнения: 1
    • ограничитель скорости повторного использования.Пропускная способность: 1

Например, я хотел бы знать, каково количество запросов в этих параметрах и какова единица времени, в течение которой это количество запросов должно работать ?

 server:
  port: ${PORT:8085}

logging.pattern.console: "%clr(%d{HH:mm:ss.SSS}){blue} %clr(---){faint} %clr([.15t]){yellow} %clr(:){red} %clr(%m){faint}%n"

spring:
  application:
    name: gateway-service
  redis:
    host: 192.168.99.100
    port: 6379
  output.ansi.enabled: ALWAYS
  cloud:
    gateway:
      routes:
      - id: account-service
        uri: http://localhost:8085
        predicates:
        - Path=/account/**
        filters:
        - RewritePath=/account/(?<path>.*), /${path}
        - name: RequestRateLimiter
          args:
              key-resolver: "#{@userKeyResolver}"
              redis-rate-limiter.replenishRate: 10
              redis-rate-limiter.burstCapacity: 20

 
  • конфигурация-безопасность
  @Configuration
//@ConditionalOnProperty("rateLimiter.secure")
@EnableWebFluxSecurity
public class SecurityConfig {


    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

        http.authorizeExchange(exchanges ->
                exchanges
                        .anyExchange()
                        .authenticated())
                .httpBasic();
        http.csrf().disable();
        return http.build();
    }

    @Bean
    public MapReactiveUserDetailsService users() {

        UserDetails user1 = User.builder()
                .username("user1")
                .password("{noop}1234")
                .roles("USER")
                .build();

        UserDetails user2 = User.builder()
                .username("user2")
                .password("{noop}1234")
                .roles("USER")
                .build();

        UserDetails user3 = User.builder()
                .username("user3")
                .password("{noop}1234")
                .roles("USER")
                .build();
        return new MapReactiveUserDetailsService(user1, user2, user3);

    }

}

 
  • config
 @Configuration
public class GatewayConfig {

    @Bean
    @Primary
    @ConditionalOnProperty("rateLimiter.non-secure")
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just("1");
    }

   // @Bean
   // @ConditionalOnProperty("rateLimiter.secure")
    KeyResolver authUserKeyResolver() {

        return exchange -> ReactiveSecurityContextHolder.getContext()
                .map(securityContext -> securityContext.getAuthentication()
                        .getPrincipal()
                        .toString()
                );
    }
}
 
  • test
 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
                properties = {"rateLimiter.non-secure=true"})
@RunWith(SpringRunner.class)
public class GatewayRateLimiterTest {

    private static final Logger LOGGER =
            LoggerFactory.getLogger(GatewayRateLimiterTest.class);

    private Random random = new Random();

    @Rule
    public TestRule benchmarkRun = new BenchmarkRule();

    private static final DockerImageName IMAGE_NAME_MOCK_SERVER =
            DockerImageName.parse("jamesdbloom/mockserver:mockserver-5.11.2");

    @ClassRule
    public static MockServerContainer mockServer =
            new MockServerContainer(IMAGE_NAME_MOCK_SERVER);


    @ClassRule
    public static GenericContainer redis =
            new GenericContainer("redis:5.0.6")
                    .withExposedPorts(6379);

    @Autowired
    TestRestTemplate testRestTemplate;



    @Test
    @BenchmarkOptions(warmupRounds = 0, concurrency = 6, benchmarkRounds = 600)
    public void testAccountService() {

        String username = "user"   (random.nextInt(3)   1);

        HttpHeaders headers = createHttpHeaders(username,"1234");
        HttpEntity<String> entity = new HttpEntity<>(headers);

        ResponseEntity<Account> responseEntity =
                testRestTemplate.exchange("/account/{id}",
                        HttpMethod.GET,
                        entity,
                        Account.class,
                        1);



        LOGGER.info("Received: status->{}, payload->{}, remaining->{}",
                responseEntity.getStatusCodeValue(),
                responseEntity.getBody(),
                responseEntity.getHeaders()
                        .get("X-RateLimit-Remaining"));


    }

    private HttpHeaders createHttpHeaders(String user, String password) {

        String notEncoded = user   ":"   password;

        String encodedAuth = Base64.getEncoder().encodeToString(notEncoded.getBytes());

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Basic "   encodedAuth);

        return headers;
    }

}

 
  • repository

here