Created
January 30, 2025 14:56
-
-
Save Phury/ada6bd39ea36cf89351bad6ec52056ce to your computer and use it in GitHub Desktop.
Test to illustrate starvation on a webclient call
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import org.junit.jupiter.api.Test; | |
| import org.junit.jupiter.api.extension.ExtendWith; | |
| import org.mockito.junit.jupiter.MockitoExtension; | |
| import org.springframework.http.client.reactive.ReactorClientHttpConnector; | |
| import org.springframework.web.reactive.function.client.WebClient; | |
| import reactor.netty.http.client.HttpClient; | |
| import reactor.netty.resources.ConnectionProvider; | |
| import java.time.Duration; | |
| import java.util.concurrent.CountDownLatch; | |
| import java.util.concurrent.TimeUnit; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| @ExtendWith(MockitoExtension.class) | |
| public class WebClientStarvationTest { | |
| private WebClient createWebClient(int maxConnections) { | |
| ConnectionProvider connectionProvider = ConnectionProvider.builder("test_pool") | |
| .maxConnections(maxConnections) // Low limit to simulate starvation | |
| .pendingAcquireTimeout(Duration.ofSeconds(5)) // Timeout for acquiring a connection | |
| .maxIdleTime(Duration.ofSeconds(10)) | |
| .build(); | |
| HttpClient httpClient = HttpClient.create(connectionProvider); | |
| return WebClient.builder() | |
| .clientConnector(new ReactorClientHttpConnector(httpClient)) | |
| .build(); | |
| } | |
| @Test | |
| public void testConnectionStarvation() throws InterruptedException { | |
| WebClient webClient = createWebClient(2); // Only 2 connections allowed | |
| CountDownLatch latch = new CountDownLatch(2); | |
| // Simulate long-running requests to the first service | |
| Runnable longRunningRequest = () -> { | |
| webClient.get() | |
| .uri("https://httpbin.org/delay/10") // Simulates a 10-second delay | |
| .retrieve() | |
| .bodyToMono(String.class) | |
| .doFinally(signal -> latch.countDown()) // Release when done | |
| .subscribe(); | |
| }; | |
| new Thread(longRunningRequest).start(); | |
| new Thread(longRunningRequest).start(); | |
| // Wait a short time to let those requests consume all connections | |
| Thread.sleep(500); | |
| // Third request should get blocked and eventually timeout | |
| assertThrows(Exception.class, () -> { | |
| try { | |
| webClient.get() | |
| .uri("https://httpbin.org/get") // Different host | |
| .retrieve() | |
| .bodyToMono(String.class) | |
| .block(Duration.ofSeconds(10)); // Should timeout | |
| } catch (Exception e) { | |
| System.out.println(e); | |
| throw e; | |
| } | |
| }); | |
| // Wait for long requests to complete | |
| latch.await(15, TimeUnit.SECONDS); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment