আপনি যখন একটি মাইক্রোসার্ভিসেস আর্কিটেকচারে কাজ করেন, তখন একটি সার্ভিস ডাউন হলে পুরো সিস্টেমের উপর তার প্রভাব পড়তে পারে। এই সমস্যা সমাধানের জন্য Circuit Breaker একটি অপরিহার্য ডিজাইন প্যাটার্ন, যা ফেইলিওর কে ম্যানেজ করে এবং সিস্টেমকে স্থিতিশীল রাখে। এই টিউটোরিয়ালে আমরা দেখব কিভাবে Java এবং Spring Boot ব্যবহার করে একটি কার্যকরী Circuit Breaker ইমপ্লিমেন্ট করা যায়, যাতে আপনি আপনার মাইক্রোসার্ভিসেস কে আরও রেজিলিয়েন্ট করতে পারেন।
ভূমিকা (Background)
মাইক্রোসার্ভিসেস আর্কিটেকচারে, একাধিক সার্ভিস একে অপরের সাথে যোগাযোগ করে। যখন একটি সার্ভিস (যেমন PaymentService) ডাউন হয়ে যায়, তখন অন্য সার্ভিসগুলি (যেমন OrderService) বারবার সেই ডাউন সার্ভিসের কাছে রিকোয়েস্ট পাঠাতে থাকে। এই ক্রমাগত ব্যর্থ রিকোয়েস্টগুলি আপনার সিস্টেমের রিসোর্স (মেমোরি, থ্রেড) নষ্ট করে এবং শেষ পর্যন্ত পুরো সিস্টেমকে ক্র্যাশ করতে পারে।
এটাই হলো Cascading Failure বা ধারাবাহিক ব্যর্থতা। Circuit Breaker প্যাটার্ন এই সমস্যা সমাধানের জন্য একটি স্মার্ট উপায়। এটি একটি ইলেকট্রিকাল সার্কিট ব্রেকারের মতো কাজ করে: যখন একটি সার্ভিস কনসিস্টেন্টলি ব্যর্থ হতে থাকে, তখন এটি "সার্কিট খুলে দেয়" এবং কিছু সময়ের জন্য সেই সার্ভিসে যাওয়া সব রিকোয়েস্ট ব্লক করে দেয়। এরপর কিছুক্ষণ পরে এটি আবার চেষ্টা করে দেখে সার্ভিসটি ঠিক হয়েছে কিনা।
এই প্যাটার্নটি মূলত Resilience4j (Resilience for Java) লাইব্রেরির মাধ্যমে ইমপ্লিমেন্ট করা হয়, যা Spring Boot এর সাথে সুন্দরভাবে ইন্টিগ্রেট হয়। এই টিউটোরিয়ালে আমরা এই লাইব্রেরি ব্যবহার করব।
পূর্বশর্ত (Prerequisites)
এই টিউটোরিয়ালটি অনুসরণ করতে আপনার নিম্নলিখিত জিনিসগুলির প্রয়োজন হবে:
- Java 17 বা তার উপরের ভার্সন: আপনার মেশিনে Java ইনস্টল থাকতে হবে।
- Maven বা Gradle: প্রজেক্ট বিল্ড করার জন্য। আমরা এখানে Maven ব্যবহার করব।
- Spring Boot 3.x: আপনার প্রজেক্টে Spring Boot সেটআপ থাকতে হবে।
- Resilience4j লাইব্রেরি: আপনার
pom.xmlফাইলে এই ডিপেন্ডেন্সি যোগ করতে হবে। - একটি REST API: আমরা একটি ডামি সার্ভিস (যেমন
http://localhost:8080/fail) ব্যবহার করব যা মাঝে মাঝে ব্যর্থ হবে।
আপনার pom.xml ফাইলে নিচের ডিপেন্ডেন্সি যোগ করুন:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
এটি আপনার Spring Boot প্রজেক্টে Resilience4j এবং Web সাপোর্ট যোগ করবে।
ধাপে ধাপে বাস্তবায়ন (Step-by-Step Implementation)
এখন আমরা একটি সহজ Circuit Breaker ইমপ্লিমেন্ট করব। আমরা একটি OrderService তৈরি করব যা একটি এক্সটার্নাল PaymentService কে কল করে। যখন PaymentService ব্যর্থ হবে, তখন Circuit Breaker কাজ করবে।
প্রথম ধাপ: একটি Spring Boot সার্ভিস ক্লাস তৈরি করুন।
@Service
public class PaymentServiceClient {
private final RestTemplate restTemplate;
public PaymentServiceClient(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallback")
public String callPaymentService() {
// একটি এক্সটার্নাল API কল যা ব্যর্থ হতে পারে
return restTemplate.getForObject("http://localhost:8080/fail", String.class);
}
public String fallback(Exception e) {
return "Fallback response: Payment service is currently unavailable.";
}
}
এই কোডে আমরা @CircuitBreaker অ্যানোটেশন ব্যবহার করেছি। name = "paymentService" হলো সার্কিট ব্রেকারের নাম যা আমরা কনফিগার করব। fallbackMethod ডিফাইন করে যখন সার্কিট খোলা থাকবে তখন কি রেসপন্স ফিরিয়ে দেওয়া হবে।
দ্বিতীয় ধাপ: application.yml ফাইলে সার্কিট ব্রেকার কনফিগার করুন।
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-size: 10 # 10টি রিকোয়েস্টের উপর ভিত্তি করে
failure-rate-threshold: 50 # 50% ব্যর্থ হলে সার্কিট খুলবে
wait-duration-in-open-state: 5s # 5 সেকেন্ড পর আবার চেষ্টা করবে
permitted-number-of-calls-in-half-open-state: 3
instances:
paymentService:
base-config: default
এই কনফিগারেশনটি বলছে: যদি শেষ 10টি রিকোয়েস্টের মধ্যে 50% ব্যর্থ হয় (অর্থাৎ 5টি ব্যর্থ), তাহলে সার্কিট ব্রেকার খুলে যাবে এবং 5 সেকেন্ডের জন্য সব রিকোয়েস্ট ব্লক করবে। এরপর এটি Half-Open স্টেটে যাবে এবং 3টি রিকোয়েস্ট পাঠিয়ে দেখবে সার্ভিস ঠিক হয়েছে কিনা।
তৃতীয় ধাপ: একটি REST কন্ট্রোলার তৈরি করুন যা এই সার্ভিসকে এক্সপোজ করবে।
@RestController
@RequestMapping("/orders")
public class OrderController {
private final PaymentServiceClient paymentClient;
public OrderController(PaymentServiceClient paymentClient) {
this.paymentClient = paymentClient;
}
@GetMapping("/process")
public String processOrder() {
return paymentClient.callPaymentService();
}
}
এখন যখন আপনি http://localhost:8080/orders/process কল করবেন, তখন এটি PaymentServiceClient এর মাধ্যমে পেমেন্ট সার্ভিসে রিকোয়েস্ট পাঠাবে। যদি সার্ভিস ডাউন থাকে, তাহলে 5 বার ব্যর্থ হওয়ার পর সার্কিট খুলে যাবে এবং আপনি ফলব্যাক মেসেজ পাবেন।
সম্পূর্ণ উদাহরণ (Complete Example)
নিচে একটি সম্পূর্ণ Spring Boot অ্যাপ্লিকেশন দেওয়া হলো যা আপনি কপি করে চালাতে পারেন। এটি একটি ডামি ফেইলিং সার্ভিস এবং একটি Circuit Breaker সহ আসে।
// MainApplication.java
@SpringBootApplication
public class CircuitBreakerApplication {
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerApplication.class, args);
}
}
// FailingService.java (ডামি সার্ভিস যা মাঝে মাঝে ব্যর্থ হয়)
@RestController
@RequestMapping("/fail")
public class FailingService {
private int counter = 0;
@GetMapping
public String fail() {
counter++;
if (counter % 3 == 0) { // প্রতি ৩য় কল ব্যর্থ হবে
throw new RuntimeException("Service failed!");
}
return "Success: " + counter;
}
}
// PaymentServiceClient.java (সার্কিট ব্রেকার সহ ক্লায়েন্ট)
@Service
public class PaymentServiceClient {
private final RestTemplate restTemplate;
public PaymentServiceClient(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallback")
public String callPaymentService() {
return restTemplate.getForObject("http://localhost:8080/fail", String.class);
}
public String fallback(Exception e) {
return "Fallback: Payment service is down!";
}
}
// OrderController.java
@RestController
@RequestMapping("/orders")
public class OrderController {
private final PaymentServiceClient client;
public OrderController(PaymentServiceClient client) {
this.client = client;
}
@GetMapping("/process")
public String process() {
return client.callPaymentService();
}
}
এই উদাহরণটি চালালে আপনি দেখবেন: প্রথমে FailingService প্রতি ৩য় কল ব্যর্থ হয়। যখন সার্কিট ব্রেকার 50% ব্যর্থতা রেটে পৌঁছায়, তখন এটি ফলব্যাক মেসেজ রিটার্ন করে। এই পুরো সিস্টেমটি আপনার মাইক্রোসার্ভিসেসকে ক্র্যাশ থেকে রক্ষা করে।
সাধারণ সমস্যা ও সমাধান (Common Issues)
Circuit Breaker ইমপ্লিমেন্ট করার সময় কিছু সাধারণ সমস্যা দেখা দিতে পারে। নিচে সেগুলি এবং তাদের সমাধান দেওয়া হলো:
- সার্কিট ব্রেকার কাজ করছে না: যদি আপনার সার্কিট ব্রেকার কখনোই খোলা না হয়, তাহলে চেক করুন
failure-rate-thresholdএবংsliding-window-sizeসঠিকভাবে সেট করা আছে কিনা। উদাহরণস্বরূপ, যদি আপনার সার্ভিস খুব কম ব্যর্থ হয়, তাহলে থ্রেশোল্ড কমিয়ে দিন (যেমন 30%)। - ফলব্যাক মেথড কাজ করছে না: নিশ্চিত করুন যে আপনার
fallbackMethodএর প্যারামিটার সঠিক। এটি সবসময় একটিExceptionবাThrowableটাইপ প্যারামিটার নিতে হবে। যদি আপনি ভিন্ন টাইপের এক্সেপশন ব্যবহার করেন, তাহলে এটি কাজ নাও করতে পারে। - সার্কিট ব্রেকার ব্যাকএন্ড কানেকশন: যদি আপনার সার্ভিসটি একটি ডাটাবেস বা থার্ড-পার্টি API এর সাথে সংযুক্ত থাকে, তাহলে সার্কিট ব্রেকার শুধুমাত্র HTTP কলের জন্য নয়, বরং যেকোনো প্রকারের ফেইলিওর (যেমন ডাটাবেস টাইমআউট) এর জন্যও কাজ করে। তাই
@CircuitBreakerঅ্যানোটেশনটি সঠিকভাবে ব্যবহার করুন। - মাল্টিপল সার্কিট ব্রেকার: যদি আপনার একাধিক সার্ভিস থাকে, তাহলে প্রতিটি সার্ভিসের জন্য আলাদা সার্কিট ব্রেকার ইনস্ট্যান্স তৈরি করুন।
instancesসেকশনে প্রতিটি সার্ভিসের জন্য আলাদা কনফিগারেশন দিতে পারেন।
সারসংক্ষেপ (Summary)
এই টিউটোরিয়ালে আমরা শিখেছি কিভাবে Circuit Breaker প্যাটার্ন ব্যবহার করে মাইক্রোসার্ভিসেস কে ফেইলিওর থেকে রক্ষা করা যায়। আমরা দেখেছি:
- কেন Circuit Breaker প্রয়োজন: এটি Cascading Failure প্রতিরোধ করে এবং সিস্টেমকে স্থিতিশীল রাখে।
- কিভাবে এটি ইমপ্লিমেন্ট করা যায়: Java এবং Spring Boot এর সাথে Resilience4j ব্যবহার করে।
- কনফিগারেশন এর গুরুত্ব: সঠিক
failure-rate-thresholdএবংwait-duration-in-open-stateসেট করে আপনি আপনার সিস্টেমের পারফরমেন্স অপ্টিমাইজ করতে পারেন।
Circuit Breaker শুধুমাত্র একটি ডিজাইন প্যাটার্ন নয়, এটি একটি প্র্যাকটিকাল টুল যা আপনার প্রোডাকশন সিস্টেমকে ডাউনটাইম এবং ইউজার এক্সপেরিয়েন্স থেকে রক্ষা করে। এখন আপনি আপনার নিজের প্রজেক্টে এটি ইমপ্লিমেন্ট করতে পারবেন এবং আপনার মাইক্রোসার্ভিসেস কে আরও রেজিলিয়েন্ট করে তুলতে পারবেন।