Resilience
Microservices আর্কিটেকচারে একাধিক সার্ভিস একে অপরের সাথে যোগাযোগ করে। একটি সার্ভিসে সমস্যা হলে সেটির প্রভাব অনেক সময় অন্য সার্ভিসগুলোতেও পড়ে। এই সমস্যার সমাধান করতে ব্যবহৃত হয় Resilience Patterns — যা সিস্টেমকে fault-tolerant, stable, এবং self-healing করে তোলে।
Resilience কী?
Resilience মানে হলো — ব্যর্থতার মাঝেও সিস্টেমের স্বাভাবিক কাজ চালিয়ে যাওয়া। অর্থাৎ, কোনো dependency ব্যর্থ হলে বা network latency বাড়লে পুরো সিস্টেম বন্ধ না হয়ে graceful degradation এর মাধ্যমে কাজ চালিয়ে যাওয়া।
Spring Boot এ Resilience কিভাবে যোগ করা যায়?
Spring Boot এ resilience যোগ করার সবচেয়ে জনপ্রিয় লাইব্রেরি হলো Resilience4j। এটি lightweight, functional, এবং Spring Cloud এর সাথে সুন্দরভাবে ইন্টিগ্রেটেড।
Resilience4j এর প্রধান মডিউলগুলো
| মডিউল | কাজ |
|---|---|
| CircuitBreaker | ব্যর্থ সার্ভিসে অনুরোধ বন্ধ রাখে |
| Retry | ব্যর্থ রিকোয়েস্ট পুনরায় চেষ্টা করে |
| RateLimiter | নির্দিষ্ট সময়ের মধ্যে রিকোয়েস্ট সীমিত করে |
| Bulkhead | সমান্তরাল কল সংখ্যা সীমিত রাখে |
| TimeLimiter | নির্দিষ্ট সময় পর রিকোয়েস্ট টাইমআউট করে |
Circuit Breaker – ব্যর্থ সার্ভিসে চাপ কমানো
Circuit Breaker একটি বৈদ্যুতিক সার্কিট ব্রেকারের মতোই কাজ করে।
যখন একটি সার্ভিস বারবার ব্যর্থ হয়, তখন এটি “Open” হয়ে যায় এবং নির্দিষ্ট সময়ের জন্য নতুন অনুরোধ ব্লক করে রাখে।
Dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
Example
@Service
public class PaymentService {
private final RestTemplate restTemplate;
public PaymentService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
public String callExternalPayment() {
return restTemplate.getForObject("http://external-service/pay", String.class);
}
public String fallbackPayment(Exception ex) {
return "Payment service temporarily unavailable!";
}
}
YAML Configuration
resilience4j:
circuitbreaker:
instances:
paymentService:
slidingWindowSize: 5
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 2
Retry – ব্যর্থ রিকোয়েস্ট আবার চেষ্টা করা
কখনো কখনো ব্যর্থতা অস্থায়ী (transient) হয় — যেমন নেটওয়ার্ক ফ্লাকচুয়েশন বা API timeout।
সেক্ষেত্রে Retry pattern সহায়ক।
Example
@Service
public class ProductService {
private final RestTemplate restTemplate;
public ProductService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
@Retry(name = "productService", fallbackMethod = "fallbackProducts")
public String getProducts() {
return restTemplate.getForObject("http://external-service/products", String.class);
}
public String fallbackProducts(Exception e) {
return "Fallback: Unable to fetch product list.";
}
}
Configuration
resilience4j:
retry:
instances:
productService:
maxAttempts: 3
waitDuration: 500ms
এটি ৩ বার পর্যন্ত retry করবে, প্রতিবার ০.৫ সেকেন্ড করে অপেক্ষা করবে।
TimeLimiter – দীর্ঘ রিকোয়েস্ট টাইমআউট করা
TimeLimiter ব্যবহার করলে কোনো সার্ভিস নির্দিষ্ট সময়ের মধ্যে সাড়া না দিলে সেটি timeout exception ছুঁড়ে দেয়।
@TimeLimiter(name = "slowService", fallbackMethod = "fallbackResponse")
public CompletableFuture<String> getSlowResponse() {
return CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(4000); } catch (InterruptedException e) {}
return "Response after delay";
});
}
public CompletableFuture<String> fallbackResponse(Throwable t) {
return CompletableFuture.completedFuture("Fallback: Service took too long!");
}
YAML
resilience4j:
timelimiter:
instances:
slowService:
timeoutDuration: 2s
Bulkhead – সীমিত concurrent call
Bulkhead pattern মূলত thread isolation দেয়। এটি concurrent কলের সংখ্যা সীমিত রাখে, যাতে অতিরিক্ত রিকোয়েস্টে সার্ভিস ক্র্যাশ না করে।
@Bulkhead(name = "inventoryService", type = Bulkhead.Type.SEMAPHORE)
public String checkInventory() {
return "Inventory checked successfully";
}
resilience4j:
bulkhead:
instances:
inventoryService:
maxConcurrentCalls: 5
maxWaitDuration: 2s
RateLimiter – Request Throttling
RateLimiter ব্যবহার করে নির্দিষ্ট সময়ের মধ্যে কতগুলো রিকোয়েস্ট অনুমোদন করা হবে তা নিয়ন্ত্রণ করা যায়।
@RateLimiter(name = "apiLimiter", fallbackMethod = "apiRateFallback")
public String callApi() {
return "API response success";
}
public String apiRateFallback(RequestNotPermitted e) {
return "Too many requests — please try later.";
}
resilience4j:
ratelimiter:
instances:
apiLimiter:
limitForPeriod: 5
limitRefreshPeriod: 10s
অর্থাৎ প্রতি ১০ সেকেন্ডে সর্বোচ্চ ৫টি রিকোয়েস্ট অনুমোদিত।
একত্রে ব্যবহার
Resilience4j এর সব ফিচার একত্রে ব্যবহার করা যায় — CircuitBreaker + Retry + TimeLimiter ইত্যাদি।
@CircuitBreaker(name = "orderService", fallbackMethod = "fallbackOrder")
@Retry(name = "orderService")
@TimeLimiter(name = "orderService")
public CompletableFuture<String> placeOrder() {
return CompletableFuture.supplyAsync(() -> "Order placed successfully!");
}
Metrics & Monitoring
Spring Boot Actuator ব্যবহার করলে Resilience4j এর মেট্রিকগুলো সহজেই মনিটর করা যায়।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
👉 /actuator/health এবং /actuator/metrics endpoint থেকে সার্ভিসের অবস্থা দেখা যাবে।
Best Practices
- প্রতিটি external সার্ভিস কলের জন্য আলাদা Circuit Breaker instance ব্যবহার করো
- সবসময় fallback method যুক্ত রাখো
- Retry এর limit ছোট রাখো (high load সিস্টেমে ওভারলোড এড়াতে)
- TimeLimiter ব্যবহার করে ধীর API গুলো নিয়ন্ত্রণ করো
- Actuator দিয়ে metrics মনিটর করো