Need help understanding why rate limiter doesn't behave like I think it should?
See original GitHub issueHi,
I’m using resilience4j and the rate-limiting module together with Spring project reactor. The code I have looks essentially like this:
public class App {
private final WebClient webClient;
private final InMemoryRateLimiterRegistry rateLimiterRegistry;
public App(int port, int rps) {
webClient = WebClient.builder()
.baseUrl("http://localhost:" + port)
.build();
rateLimiterRegistry = new InMemoryRateLimiterRegistry(RateLimiterConfig.ofDefaults());
rateLimiterRegistry.rateLimiter("test", RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(1))
.limitForPeriod(rps)
.timeoutDuration(Duration.ofHours(1))
.build());
}
public Mono<String> makeRequest() {
RateLimiter rateLimiter = rateLimiterRegistry.rateLimiter("test");
Mono<String> result = webClient.post()
.uri("/testing")
.accept(ALL)
.contentType(TEXT_PLAIN)
.syncBody("hello world")
.retrieve().bodyToMono(String.class);
return result.transform(RateLimiterOperator.of(rateLimiter));
}
}
I’ve tried creating a test case in which I’d like to verify that the rate limiter actually limits the requests per second to 10. The test case looks like this:
public class AppTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule();
@Test
public void whyDoesntThisWorkQuestionMarkQuestionMark() {
// Given
int numberOfRequests = 30;
int rps = 10;
App app = new App(wireMockRule.port(), rps);
wireMockRule.addStubMapping(stubFor(post(urlPathEqualTo("/testing"))
.willReturn(aResponse().withStatus(200).withBody("hello hello!"))));
// When
ParallelFlux<String> flux = Flux.range(0, numberOfRequests)
.parallel()
.runOn(Schedulers.parallel())
.flatMap(___ -> app.makeRequest());
long startTime = new Date().getTime();
StepVerifier.create(flux).expectNextCount(numberOfRequests).verifyComplete();
long endTime = new Date().getTime();
assertThat(endTime - startTime)
.describedAs("I don't understand why this is not taking longer than this")
.isGreaterThanOrEqualTo((numberOfRequests / rps) * 1000);
}
}
But this fails with:
whyDoesntThisWorkQuestionMarkQuestionMark(se.haleby.AppTest) Time elapsed: 2.376 sec <<< FAILURE!
java.lang.AssertionError: [I don't understand why this is not taking longer than this]
Expecting:
<1466L>
to be greater than or equal to:
<3000L>
at se.haleby.AppTest.whyDoesntThisWorkQuestionMarkQuestionMark(AppTest.java:43)
I don’t really understand why the test is only taking roughly 1,5 seconds instead of the expected 3 seconds (since I’m making 30 requests with an RPS of 10 requests per second). I’m probably missing something quite essential here and I’m ready to be schooled 😃.
My code can be found here: https://github.com/johanhaleby/resilience4j-ratelimiter-question
Issue Analytics
- State:
- Created 5 years ago
- Comments:24 (22 by maintainers)
Top Results From Across the Web
Rate-limiting strategies and techniques - Google Cloud
Introduction. This document explains why rate limiting is used, describes strategies and techniques for rate limiting, and explains where ...
Read more >Rate Limiting: What It Is & Why It Matters | Traefik Labs
Rate limiting your network traffic is critical to ensuring your infrastructure remains resilient and secure. Read our 101 article to learn more.
Read more >Rate Limiting and Velocity Checking - Coding Horror
Rate limiting isn't always a precise science. But it's necessary, even with the false positives -- consider how dangerous a login entry with...
Read more >What is rate limiting? | Rate limiting and bots - Cloudflare
Typically, rate limiting is based on tracking the IP addresses that requests are coming from, and tracking how much time elapses between each...
Read more >How to Design a Scalable Rate Limiting Algorithm with Kong API
Without rate limiting, each user may make a request as often as they like, leading to “spikes” of requests that starve other consumers....
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I’ve created a PR where I test a delay of a subscription.
@martin-tarjanyi
Please see: https://github.com/resilience4j/resilience4j/blob/0ab113cb7caa4c60a93e13dcc97d2461c0653569/resilience4j-reactor/src/main/java/io/github/resilience4j/reactor/ratelimiter/operator/MonoRateLimiter.java#L37-L47
@RobWin Oh, that probably explains it. I think I get it now and it makes sense. Thanks a lot for taking the time to explain this, really appreciated. And thanks for all the work on resilience4j.