মাইক্রোসার্ভিসেস আর্কিটেকচারে প্রতিটি রিকোয়েস্ট একাধিক সার্ভিসের মাধ্যমে যাত্রা করে। এই জটিল পথে কোথাও সমস্যা হলে পুরো সিস্টেমের পারফরম্যান্স বুঝতে অসুবিধা হয়। Distributed tracing (বিতরণকৃত ট্রেসিং) এই সমস্যার সমাধান করে, যা একটি রিকোয়েস্টের সম্পূর্ণ পথ ট্র্যাক করে এবং প্রতিটি ধাপে লেটেন্সি ও ত্রুটি বিশ্লেষণে সাহায্য করে। এই টিউটোরিয়ালে আমরা OpenTelemetry এবং Jaeger ব্যবহার করে Spring Boot মাইক্রোসার্ভিসে distributed tracing বাস্তবায়ন করব।
ভূমিকা (Background)
মাইক্রোসার্ভিসেস ডিজাইনে প্রতিটি সার্ভিস স্বাধীনভাবে কাজ করে। একটি সাধারণ API কল অনেকগুলো সার্ভিসের মধ্য দিয়ে যায় — যেমন অর্ডার সার্ভিস, পেমেন্ট সার্ভিস, ইনভেন্টরি সার্ভিস। যদি এই চেইনের কোনো এক জায়গায় লেটেন্সি বেড়ে যায়, তাহলে ডেভেলপারদের পক্ষে তা চিহ্নিত করা কঠিন হয়ে পড়ে।
Distributed tracing এই সমস্যার সমাধান করে স্প্যান (span) এবং ট্রেস (trace) এর ধারণা ব্যবহার করে:
- প্রতিটি সার্ভিস কল একটি স্প্যান হিসেবে রেকর্ড হয়
- পুরো রিকোয়েস্ট পথ একটি ট্রেস হিসেবে সংযুক্ত থাকে
- প্রতিটি স্প্যানে টাইমস্ট্যাম্প, মেটাডাটা এবং ত্রুটির তথ্য থাকে
জনপ্রিয় টুলস যেমন Jaeger, Zipkin, এবং OpenTelemetry এই কাজে ব্যবহৃত হয়। OpenTelemetry একটি ইন্ডাস্ট্রি স্ট্যান্ডার্ড যা বিভিন্ন ব্যাকএন্ডের সাথে ইন্টিগ্রেট হয়।
পূর্বশর্ত (Prerequisites)
এই টিউটোরিয়াল অনুসরণ করতে আপনার প্রয়োজন:
- Java 17 বা তার উপরের ভার্সন
- Spring Boot 3.x প্রজেক্ট সেটআপ
- Maven বা Gradle বিল্ড টুল
- Docker (Jaeger লোকালি চালানোর জন্য)
- মাইক্রোসার্ভিসেস সম্পর্কে বেসিক জ্ঞান
আপনার pom.xml ফাইলে নিম্নলিখিত ডিপেন্ডেন্সি যোগ করুন:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-jaeger</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>
এই ডিপেন্ডেন্সিগুলো Spring Boot অ্যাপ্লিকেশনে স্বয়ংক্রিয়ভাবে ট্রেসিং কনফিগার করে।
ধাপে ধাপে বাস্তবায়ন (Step-by-step Implementation)
প্রথমে একটি সাধারণ Spring Boot মাইক্রোসার্ভিস তৈরি করি যা দুটি এন্ডপয়েন্ট কল করবে। আমরা OrderService এবং PaymentService নামে দুটি সার্ভিস তৈরি করব।
ধাপ ১: OpenTelemetry কনফিগারেশন
application.properties ফাইলে নিচের কনফিগারেশন যোগ করুন:
otel.service.name=order-service
otel.exporter.otlp.endpoint=http://localhost:4317
এখানে otel.service.name সার্ভিসের নাম নির্ধারণ করে, যা Jaeger ড্যাশবোর্ডে দেখাবে। otel.exporter.otlp.endpoint OpenTelemetry প্রোটোকলের মাধ্যমে ডাটা পাঠানোর ঠিকানা।
ধাপ ২: রেস্ট কন্ট্রোলার তৈরি
নিচের OrderController ক্লাসটি দুটি সার্ভিস কল করে:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public String getOrder(@PathVariable String id) {
// পেমেন্ট সার্ভিস কল
String paymentResponse = restTemplate.getForObject(
"http://localhost:8082/api/payments/" + id,
String.class
);
return "Order: " + id + ", Payment: " + paymentResponse;
}
}
এই ক্লাসে RestTemplate ব্যবহার করে পেমেন্ট সার্ভিসে HTTP কল করা হচ্ছে। OpenTelemetry স্বয়ংক্রিয়ভাবে এই HTTP কলের জন্য একটি স্প্যান তৈরি করবে।
ধাপ ৩: স্প্যানে কাস্টম অ্যাট্রিবিউট যোগ করা
নিচের উদাহরণে আমরা ম্যানুয়ালি স্প্যানে ডাটা যোগ করি:
@GetMapping("/{id}")
public String getOrder(@PathVariable String id) {
Span currentSpan = Span.current();
currentSpan.setAttribute("order.id", id);
currentSpan.setAttribute("order.type", "standard");
// পেমেন্ট সার্ভিস কল
String paymentResponse = restTemplate.getForObject(
"http://localhost:8082/api/payments/" + id,
String.class
);
return "Order: " + id + ", Payment: " + paymentResponse;
}
Span.current() মেথড বর্তমান সক্রিয় স্প্যানটি ফেরত দেয়। এরপর আমরা setAttribute ব্যবহার করে কাস্টম ডাটা যোগ করি, যা পরে ডিবাগিং এবং পারফরম্যান্স বিশ্লেষণে কাজে লাগবে।
সম্পূর্ণ উদাহরণ (Complete Example)
নিচে একটি সম্পূর্ণ Spring Boot অ্যাপ্লিকেশন দেওয়া হলো যা Jaeger-এ ট্রেস পাঠায়:
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public OpenTelemetry openTelemetry() {
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(
JaegerGrpcSpanExporter.builder()
.setEndpoint("localhost:14250")
.build()
).build())
.build();
return OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.build();
}
}
এই কোডে JaegerGrpcSpanExporter Jaeger সার্ভারে gRPC প্রোটোকলের মাধ্যমে ট্রেস ডাটা পাঠায়। BatchSpanProcessor স্প্যানগুলোকে ব্যাচে করে পাঠায়, যা পারফরম্যান্সের জন্য ভালো।
এখন Jaeger ড্যাশবোর্ড চালু করতে Docker কমান্ড ব্যবহার করুন:
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 16686:16686 \
-p 4317:4317 \
-p 14250:14250 \
jaegertracing/all-in-one:1.45
এরপর আপনার ব্রাউজারে http://localhost:16686 খুললে Jaeger UI দেখতে পাবেন। সেখানে আপনার অ্যাপ্লিকেশনের ট্রেস লিস্ট দেখানো হবে।
সাধারণ সমস্যা ও সমাধান (Common Issues)
নিচে কিছু সাধারণ সমস্যা এবং তাদের সমাধান দেওয়া হলো:
-
ট্রেস ড্যাশবোর্ডে দেখা যাচ্ছে না: নিশ্চিত করুন Jaeger কন্টেইনারটি সঠিকভাবে চালু আছে এবং পোর্ট ম্যাপিং ঠিক আছে।
docker psকমান্ড দিয়ে চেক করুন। -
স্প্যানের ডাটা অসম্পূর্ণ: OpenTelemetry এজেন্টের জন্য
otel.javaagent.enabled=trueপ্রপার্টি সেট করুন। এটি Spring Boot অ্যাপ্লিকেশনে স্বয়ংক্রিয় ইনস্ট্রুমেন্টেশন চালু করে। -
লেটেন্সি বেশি হচ্ছে:
BatchSpanProcessorএর ব্যাচ সাইজ কনফিগার করুন। ডিফল্ট 512 স্প্যান, যা বড় অ্যাপ্লিকেশনের জন্য কম হতে পারে। নিচের কনফিগারেশন যোগ করুন:
otel.bsp.max.export.batch.size=1024
otel.bsp.schedule.delay=500
- মাল্টি-সার্ভিস ট্রেসিং কাজ করছে না: প্রতিটি মাইক্রোসার্ভিসে একই
service.nameব্যবহার করবেন না। প্রতিটি সার্ভিসের জন্য আলাদা নাম দিন, যেমনorder-service,payment-service।
সারসংক্ষেপ (Summary)
Distributed tracing মাইক্রোসার্ভিসেস আর্কিটেকচারে একটি অপরিহার্য টুল। এই টিউটোরিয়ালে আমরা শিখেছি:
- OpenTelemetry API ব্যবহার করে স্প্যান এবং ট্রেস তৈরি করা
- Jaeger এক্সপোর্টার দিয়ে ডাটা ভিজুয়ালাইজ করা
- Spring Boot অ্যাপ্লিকেশনে স্বয়ংক্রিয় ট্রেসিং কনফিগার করা
- সাধারণ সমস্যা সমাধানের পদ্ধতি
আপনার প্রোডাকশন সিস্টেমে এই টেকনিক প্রয়োগ করলে ডিবাগিং সময় অনেক কমে যাবে এবং সিস্টেমের পারফরম্যান্স বুঝতে সহজ হবে। পরবর্তী ধাপে আপনি Zipkin বা AWS X-Ray এর মতো অন্যান্য ব্যাকএন্ড ব্যবহার করতে পারেন।