মাইক্রোসার্ভিসেস আর্কিটেকচারে কাজ করতে গেলে আপনি নিশ্চয়ই একাধিক সার্ভিসের সম্মুখীন হন। প্রতিটি সার্ভিসের নিজস্ব এন্ডপয়েন্ট, পোর্ট এবং প্রোটোকল থাকে। ক্লায়েন্টের পক্ষে সরাসরি এই সব সার্ভিসের সাথে যোগাযোগ করা জটিল এবং নিরাপত্তার দিক থেকে সমস্যাজনক হতে পারে। এই টিউটোরিয়ালে আমরা শিখবো কিভাবে API Gateway এই সমস্যার সমাধান করে, একটি কেন্দ্রীয় প্রবেশদ্বার হিসেবে কাজ করে যা ক্লায়েন্টের অনুরোধকে সঠিক মাইক্রোসার্ভিসে রাউট করে এবং একই সাথে লোড ব্যালেন্সিং, অথেনটিকেশন ও রেট লিমিটিংয়ের মতো গুরুত্বপূর্ণ ফিচার প্রদান করে।
ভূমিকা (Background)
একটি মাইক্রোসার্ভিসেস আর্কিটেকচারে, প্রতিটি সার্ভিস সাধারণত একটি নির্দিষ্ট ব্যবসায়িক ফিচারের জন্য দায়িত্বপ্রাপ্ত হয়। যেমন, অর্ডার সার্ভিস, পেমেন্ট সার্ভিস, ইউজার সার্ভিস ইত্যাদি। ক্লায়েন্ট (যেমন একটি ওয়েব অ্যাপ বা মোবাইল অ্যাপ) যদি সরাসরি এই সার্ভিসগুলোর সাথে যোগাযোগ করে, তাহলে তাকে প্রতিটি সার্ভিসের এন্ডপয়েন্ট ও পোর্ট জানতে হবে। এটি শুধু জটিলই নয়, বরং নিরাপত্তার দিক থেকেও ঝুঁকিপূর্ণ। কারণ ক্লায়েন্টকে সরাসরি ডেটাবেস বা ইন্টারনাল নেটওয়ার্কের সাথে সংযোগের সুযোগ দেওয়া হয় না।
API Gateway এই সমস্যা সমাধানের জন্য ডিজাইন করা একটি প্যাটার্ন। এটি মূলত একটি রিভার্স প্রক্সি (Reverse Proxy) যা সব ক্লায়েন্টের অনুরোধ প্রথমে গ্রহণ করে, তারপর সেই অনুরোধকে প্রয়োজনীয় মাইক্রোসার্ভিসে ফরওয়ার্ড করে। API Gateway সাধারণত নিচের কাজগুলো করে থাকে:
- রাউটিং (Routing): কোন অনুরোধ কোন সার্ভিসে যাবে তা নির্ধারণ করা।
- লোড ব্যালেন্সিং (Load Balancing): একাধিক ইনস্ট্যান্সের মধ্যে অনুরোধ বিতরণ করে সার্ভিসকে স্কেলেবল করা।
- অথেনটিকেশন ও অথরাইজেশন (Authentication & Authorization): ক্লায়েন্টের পরিচয় যাচাই করে অননুমোদিত অ্যাক্সেস ব্লক করা।
- রেট লিমিটিং (Rate Limiting): একটি নির্দিষ্ট সময়ের মধ্যে কতটি অনুরোধ গ্রহণ করা হবে তা সীমিত করে ডিনায়াল অফ সার্ভিস (DoS) আক্রমণ থেকে রক্ষা করা।
- লগিং ও মনিটরিং (Logging & Monitoring): সব অনুরোধের লগ সংরক্ষণ করে সিস্টেমের পারফরম্যান্স বিশ্লেষণ করা।
পূর্বশর্ত (Prerequisites)
এই টিউটোরিয়ালটি সম্পূর্ণভাবে অনুসরণ করতে আপনার নিম্নলিখিত বিষয়গুলোর সাথে পরিচিতি থাকা প্রয়োজন:
- জাভা (Java): জাভা প্রোগ্রামিং ভাষার মৌলিক ধারণা। বিশেষ করে ক্লাস, ইন্টারফেস এবং মেথড সম্পর্কে জ্ঞান।
- স্প্রিং বুট (Spring Boot): স্প্রিং বুট ফ্রেমওয়ার্কের মৌলিক ধারণা। আপনি যদি
@RestControllerএবং@RequestMappingঅ্যানোটেশন ব্যবহার করে থাকেন, তাহলে এটি বুঝতে সহজ হবে। - মাইক্রোসার্ভিসেস (Microservices): মাইক্রোসার্ভিসেস আর্কিটেকচারের মৌলিক ধারণা, যেমন একটি অ্যাপ্লিকেশনকে ছোট ছোট স্বাধীন সার্ভিসে ভাগ করা।
- মাভেন বা গ্রেডল (Maven/Gradle): আপনার প্রোজেক্টে ডিপেন্ডেন্সি ম্যানেজমেন্টের জন্য এই বিল্ড টুলগুলোর একটি ব্যবহার করতে হবে।
- পোস্টম্যান বা কার্ল (Postman/cURL): API টেস্ট করার জন্য একটি HTTP ক্লায়েন্ট টুল।
আপনার যদি এই পূর্বশর্তগুলোর কোনোটি না থাকে, তাহলে প্রথমে সেগুলো শিখে নিন। তবে চিন্তার কিছু নেই, আমরা ধাপে ধাপে সবকিছু ব্যাখ্যা করবো।
ধাপে ধাপে বাস্তবায়ন (Step-by-step Implementation)
আমরা এখন একটি সাধারণ API Gateway তৈরি করবো যা দুটি মাইক্রোসার্ভিসকে রাউট করবে: একটি ইউজার সার্ভিস এবং একটি অর্ডার সার্ভিস। আমরা স্প্রিং ক্লাউড গেটওয়ে (Spring Cloud Gateway) ব্যবহার করবো, যা স্প্রিং বুটের উপর ভিত্তি করে তৈরি এবং এটি রিয়েক্টিভ (Reactive) ওয়েব ফ্রেমওয়ার্ক ব্যবহার করে।
১. প্রোজেক্ট সেটআপ (Project Setup)
প্রথমে একটি নতুন স্প্রিং বুট প্রোজেক্ট তৈরি করুন। আপনি স্প্রিং ইনিশিয়ালাইজার (Spring Initializr) ব্যবহার করতে পারেন। pom.xml ফাইলে নিচের ডিপেন্ডেন্সিগুলো যোগ করুন:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
এই ডিপেন্ডেন্সিগুলো spring-cloud-starter-gateway ও spring-boot-starter-webflux যোগ করে। spring-cloud-starter-gateway হলো API Gateway তৈরির জন্য স্প্রিং ক্লাউডের স্টার্টার প্যাকেজ, আর spring-boot-starter-webflux হলো রিয়েক্টিভ ওয়েব সার্ভার চালানোর জন্য প্রয়োজনীয়। মনে রাখবেন, স্প্রিং ক্লাউড গেটওয়ে স্প্রিং ওয়েবফ্লাক্সের উপর নির্ভর করে, তাই এটি স্প্রিং এমভিসি (MVC) এর পরিবর্তে রিয়েক্টিভ প্রোগ্রামিং মডেল ব্যবহার করে।
২. গেটওয়ে কনফিগারেশন (Gateway Configuration)
এখন application.yml ফাইলে গেটওয়ের রাউটিং রুলস কনফিগার করি:
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: user-service
uri: http://localhost:8081
predicates:
- Path=/users/**
- id: order-service
uri: http://localhost:8082
predicates:
- Path=/orders/**
এখানে আমরা দুটি রুট ডিফাইন করেছি। user-service রুটটি /users/** পাথের সব অনুরোধকে http://localhost:8081 এ ফরওয়ার্ড করবে। একইভাবে order-service রুটটি /orders/** পাথের অনুরোধকে http://localhost:8082 এ ফরওয়ার্ড করবে। uri ফিল্ডে আমরা টার্গেট মাইক্রোসার্ভিসের এড্রেস দিয়েছি। predicates ফিল্ডে আমরা শর্ত দিয়েছি যে কোন পাথের অনুরোধ এই রুটে ম্যাচ হবে।
৩. মেইন ক্লাস (Main Class)
এখন আমাদের মেইন অ্যাপ্লিকেশন ক্লাস তৈরি করি:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
এই ক্লাসটি @SpringBootApplication অ্যানোটেশন দিয়ে মার্ক করা হয়েছে, যা স্প্রিং বুটকে জানায় যে এটি একটি অটো-কনফিগারেশন ক্লাস। main মেথডটি অ্যাপ্লিকেশন চালু করে। এই ক্লাসটি খুবই সিম্পল — এতে কোনো রাউটিং লজিক নেই, কারণ রাউটিং রুলস আমরা application.yml ফাইলে ডিফাইন করেছি।
সম্পূর্ণ উদাহরণ (Complete Example)
আমরা এখন একটি সম্পূর্ণ রানেবল উদাহরণ তৈরি করবো। ধরা যাক, আমাদের দুটি মাইক্রোসার্ভিস আছে: ইউজার সার্ভিস এবং অর্ডার সার্ভিস। নিচে তাদের সিম্পল কন্ট্রোলার ক্লাস দেওয়া হলো:
ইউজার সার্ভিস (পোর্ট 8081):
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{id}")
public String getUser(@PathVariable String id) {
return "User ID: " + id + ", Name: John Doe";
}
}
অর্ডার সার্ভিস (পোর্ট 8082):
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@GetMapping("/orders/{id}")
public String getOrder(@PathVariable String id) {
return "Order ID: " + id + ", Amount: 100.00";
}
}
এখন আপনার API Gateway অ্যাপ্লিকেশনটি চালু করুন (পোর্ট 8080)। আপনি যদি পোস্টম্যান বা ব্রাউজারে http://localhost:8080/users/1 হিট করেন, তাহলে গেটওয়ে অনুরোধটি http://localhost:8081/users/1 এ ফরওয়ার্ড করবে এবং আপনি User ID: 1, Name: John Doe রেসপন্স পাবেন। একইভাবে http://localhost:8080/orders/1 হিট করলে আপনি Order ID: 1, Amount: 100.00 রেসপন্স পাবেন।
কেন এই উদাহরণটি কাজ করে? কারণ API Gateway ক্লায়েন্টের জন্য একটি একক এন্ট্রি পয়েন্ট তৈরি করে। ক্লায়েন্টকে আর জানতে হবে না যে ইউজার সার্ভিস পোর্ট 8081 এ চলছে আর অর্ডার সার্ভিস পোর্ট 8082 এ চলছে। ক্লায়েন্ট শুধু গেটওয়ে (পোর্ট 8080) এর সাথে যোগাযোগ করে, এবং গেটওয়ে বুদ্ধিমত্তার সাথে অনুরোধকে সঠিক সার্ভিসে ফরওয়ার্ড করে।
সাধারণ সমস্যা ও সমাধান (Common Issues)
API Gateway ব্যবহার করার সময় কিছু সাধারণ সমস্যার সম্মুখীন হতে পারেন। নিচে সেগুলো এবং তাদের সমাধান দেওয়া হলো:
১. সার্কিট ব্রেকার (Circuit Breaker) সমস্যা
যদি কোনো মাইক্রোসার্ভিস ডাউন থাকে, তাহলে গেটওয়ে ক্লায়েন্টকে একটি ত্রুটি বার্তা (যেমন 500 Internal Server Error) পাঠাতে পারে। এটি ঠেকাতে আপনি সার্কিট ব্রেকার প্যাটার্ন ব্যবহার করতে পারেন। স্প্রিং ক্লাউড গেটওয়ে Hystrix বা Resilience4j এর সাথে ইন্টিগ্রেটেড থাকে।
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r.path("/users/**")
.filters(f -> f.circuitBreaker(config -> config
.setName("myCircuitBreaker")
.setFallbackUri("forward:/fallback")))
.uri("http://localhost:8081"))
.build();
}
২. কোরস (CORS) সমস্যা
যদি আপনার ফ্রন্টএন্ড অ্যাপ্লিকেশন (যেমন React বা Angular) ভিন্ন অরিজিন থেকে API Gateway এ অনুরোধ পাঠায়, তাহলে আপনি CORS (Cross-Origin Resource Sharing) কনফিগার করতে পারেন।
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowed-origins: "http://frontend.example.com"
allowed-methods: "*"
৩. রেট লিমিটিং (Rate Limiting) কনফিগারেশন
একটি নির্দিষ্ট ইউজার বা আইপি অ্যাড্রেস থেকে অতিরিক্ত অনুরোধ আসলে, আপনি রেট লিমিটিং কনফিগার করতে পারেন। স্প্রিং ক্লাউড গেটওয়ে RequestRateLimiter ফিল্টার ব্যবহার করে এটি করে।
spring:
cloud:
gateway:
routes:
- id: user-service
uri: http://localhost:8081
predicates:
- Path=/users/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter:
replenishRate: 10
burstCapacity: 20
সারসংক্ষেপ (Summary)
এই টিউটোরিয়ালে আমরা শিখেছি কিভাবে API Gateway মাইক্রোসার্ভিসেস আর্কিটেকচারে একটি কেন্দ্রীয় প্রবেশদ্বার হিসেবে কাজ করে। আমরা দেখেছি যে এটি রাউটিং, লোড ব্যালেন্সিং, অথেনটিকেশন এবং রেট লিমিটিংয়ের মতো জটিল কাজগুলোকে সহজ করে তোলে। আমরা স্প্রিং ক্লাউড গেটওয়ে ব্যবহার করে একটি সম্পূর্ণ উদাহরণ তৈরি করেছি যা দুটি মাইক্রোসার্ভিসকে রাউট করে।
মনে রাখবেন, API Gateway শুধু একটি টুল নয়, এটি একটি ডিজাইন প্যাটার্ন। এটি ব্যবহার করলে আপনার মাইক্রোসার্ভিসেস আর্কিটেকচার আরও স্কেলেবল, নিরাপদ এবং মেইনটেইনেবল হবে। আপনার যদি কোনো প্রশ্ন থাকে, কমেন্ট সেকশনে জানাতে পারেন।