#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