Resilience4J Ratelimiter не ограничивает доступ к аннотированному методу - PullRequest
0 голосов
/ 07 августа 2020

Я использую библиотеку resilience4j-spring-boot2 (io.github.resilience4j:resilience4j-spring-boot2, версия 1.5.0) и версию Spring Boot 2.3.1.RELEASE. Я создал RateLimiter, который должен позволять только одному потоку выполнять определенный метод каждые 30 секунд. Однако, похоже, нет границы (за исключением настроенного количества потоков, запущенных на сервере Tomcat) для потоков для вызова метода.

Я реализовал простую Службу, которая ожидает в течение заданного количества времени и затем возвращает «Hello!»:

@RequestMapping("/")
@RestController
public class ResilientService {

    @RateLimiter(name = "hello-rl")
    @GetMapping("/hello/{timeout}")
    public String hello(@PathVariable int timeout) throws InterruptedException {
        Thread.sleep(timeout);
        return "Hello!";
    }

}

И настроил Ограничитель скорости следующим образом

resilience4j.ratelimiter:
  instances:
    hello-rl:
      limitForPeriod: 1  # The number of permissions available during one limit refresh period
      limitRefreshPeriod: 30s  # The period of a limit refresh. After each period the rate limiter sets its permissions count back to the limitForPeriod value
      timeoutDuration: 30s  # The default wait time a thread waits for a permission

И я вызвал службу с восемью потоками:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@Slf4j
public class CircuitBreakerTest {

    @Autowired
    TestRestTemplate testRestTemplate;

    @LocalServerPort
    private int port;

    @Value("${server.address}")
    private String serverAddress;

    @Test
    public void t() throws InterruptedException {
        final ExecutorService executorService = Executors.newFixedThreadPool(8);

        for (int i : IntStream.rangeClosed(1, 8).toArray()) {
            executorService.execute(() -> log.error(callService()));
        }

        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.MINUTES);
    }

    private String callService() {
        return testRestTemplate.getForObject(
                "http://" + serverAddress + ":" + port + "/hello/5000",
                String.class
        );
    }

вывод выглядит следующим образом:

2020-08-07 10:41:10,095 ERROR [pool-1-thread-7] CircuitBreakerTest: Hello!
2020-08-07 10:41:10,095 ERROR [pool-1-thread-1] CircuitBreakerTest: Hello!
2020-08-07 10:41:10,095 ERROR [pool-1-thread-8] CircuitBreakerTest: Hello!
2020-08-07 10:41:10,095 ERROR [pool-1-thread-2] CircuitBreakerTest: Hello!
2020-08-07 10:41:10,095 ERROR [pool-1-thread-5] CircuitBreakerTest: Hello!
2020-08-07 10:41:15,104 ERROR [pool-1-thread-3] CircuitBreakerTest: Hello!
2020-08-07 10:41:15,121 ERROR [pool-1-thread-4] CircuitBreakerTest: Hello!
2020-08-07 10:41:15,121 ERROR [pool-1-thread-6] CircuitBreakerTest: Hello!

Кажется, что только пяти потокам разрешено выполнять метод одновременно, но я не знаю почему. Сервер Tomcat работает с> 8 потоками. Я сделал ошибку? Или я неправильно понимаю, как должен работать RateLimiter?

1 Ответ

0 голосов
/ 07 августа 2020

resilience4j-spring-boot2 использует аспекты внутренне, поэтому необходимо добавить зависимость spring-boot-starter-aop к проекту, чтобы аннотации работали:

        <dependency>
            <!-- for rate limiting -->
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>${resilience4j.version}</version>
        </dependency>
        <dependency>
            <!-- needed for Resilience4j -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

Как указано в официальной документации в самом начале ("Настройка") ... совершенно пропустил.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...