Careeroza
Why Resilience Patterns
Cascading Failure
In a monolith, a slow method slows one feature. In microservices, a slow service can take down everything that calls it. If payment-service hangs for 30 seconds, every order-service thread waits on it; soon order-service cannot answer anyone, then the gateway runs out of connections, and the whole site is down because of one service.
payment-service: slow (30 s per call)
^ waiting...
order-service: 200/200 threads blocked -> new requests queue up
^ waiting...
api-gateway: connections pile up -> users see spinning pages
^
users click "Place order" again and again -> even more loadThe Toolbox
| Pattern | Question it answers | ShopEase use |
|---|---|---|
| Timeout / Time limiter | How long do I wait? | Give up on product-service after 2 s |
| Retry | Was it a short glitch? | Retry GET product 3 times with backoff |
| Circuit breaker | Is it broken right now? Stop calling! | Stop calling payment-service for 10 s after many failures |
| Rate limiter | Am I calling too fast? | Max 20 calls/s to the bank API (its contract limit) |
| Bulkhead | How many calls at the same time? | Max 10 concurrent payment calls, so other features keep threads |
| Fallback | What do I return instead? | Cached product, "payment pending" status |
Resilience4j is the standard library for this in Spring Boot 3 (Netflix Hystrix is dead since 2018). Add it to order-service:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
<version>2.2.0</version>
</dependency>
<dependency> <!-- the annotations work through AOP -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>