Reactive programming is used to handle asynchronous, non-blocking operations efficiently, allowing systems to scale and respond faster under high load.
Example of load testing on reactive vs imperative code
@RestController
public class ReactiveController {
private final List<String> users = List.of("Alice", "Bob", "Charlie");
@GetMapping("/users-reactive")
public Flux<String> getUsers() {
// Simulate a delay (e.g., simulating a network call or DB access)
return Flux.fromIterable(users)
.delayElements(Duration.ofMillis(100)); // Delay each element by 100ms
}
}
@RestController
public class ImperativeController {
@GetMapping("/users-imperative")
public List<String> getUsers() throws InterruptedException {
// Simulate some processing or latency
Thread.sleep(100); // Optional: simulate delay for testing
return List.of("Alice", "Bob", "Charlie");
}
}
After running the service, I used a program called 'hey' to perform local load testing on the APIs.
It can be seen that because of the non-blocking behavior, the reactive controller performs better.