Microservices Service Discovery Sinhala | Spring Cloud Eureka Tutorial | Java

ආයුබෝවන්, කොහොමද යාළුවනේ?
අද කාලේ Software Development ක්ෂේත්රයේ ගොඩක් දෙනෙක් කතා කරන Topic එකක් තමයි Microservices Architecture කියන්නේ. සාම්ප්රදායික Monolithic Applications වලට වඩා Microservices ගොඩක් වාසි අරන් දෙනවා. ඒ වගේම, එයත් එක්ක එන අභියෝගත් තියෙනවා. මේ අභියෝග අතරින් ප්රධාන එකක් තමයි Service Discovery කියන්නේ. ඒ කියන්නේ, Microservices Architecture එකක තියෙන වෙන වෙනම Services කොහොමද එකිනෙකාව හොයාගෙන කතා කරගන්නේ කියන එක. මේ ලිපියෙන් අපි මේ ගැටලුවට Spring Cloud Eureka කියන Service Discovery Tool එක පාවිච්චි කරලා කොහොමද විසඳුම් හොයන්නේ කියලා කතා කරනවා.
මේ Guide එක අවසාන වෙනකොට ඔයාට Microservices වල Service Discovery වැදගත් වෙන්නේ ඇයි කියන එකත්, Spring Cloud Eureka Server එකක් සහ Client එකක් හදලා services අතර communication පහසු කරගන්නේ කොහොමද කියන එකත් පැහැදිලි අවබෝධයක් ලැබෙයි. එහෙනම් අපි පටන් ගමු!
Service Discovery කියන්නේ මොකක්ද?
ඔයා දන්නවා ඇති, Microservices Architecture එකකදී අපේ Application එක එකිනෙකට ස්වාධීන, කුඩා, වෙන වෙනම deploy කරන්න පුළුවන් Services ගණනාවකින් තමයි හැදිලා තියෙන්නේ. උදාහරණයක් විදියට, Product Service එකක්, Order Service එකක්, User Service එකක් වගේ Services තියෙන්න පුළුවන්.
දැන් හිතන්න, Order Service එකට Product Service එකෙන් Product Details ගන්න ඕන වුණා කියලා. සාමාන්යයෙන් ඔයා Product Service එකේ IP Address එකයි Port එකයි දැනගෙන ඒකට request එකක් යවන්න පුළුවන්. හැබැයි මේක Microservices ලෝකේදී ලොකු ගැටලුවක්.
- Dynamic Scaling: ඔයාගේ Product Service එකට එකපාරටම ඉල්ලුම වැඩි වුණොත්, ඔයාට ඒකේ Instances ගණන වැඩි කරන්න වෙනවා. අලුතින් එන Instance එකට වෙනම IP එකක්, Port එකක් ලැබෙනවා. මේ හැම එකකම IP Address එක මතක තියාගෙන ඉන්න බෑනේ?
- Service Failures: Service එකක් down වුණොත්, ඒකෙන් වැඩ ගන්න Services මොනවද කරන්නේ?
- Load Balancing: එක Service එකක Instances කිහිපයක් තියෙනකොට, request ඒ අතරේ distribute කරන්නේ කොහොමද?
මේ වගේ ප්රශ්නවලට විසඳුම තමයි Service Discovery. සරලව කිව්වොත්, Service Discovery කියන්නේ Microservices වලට තමන්ට අවශ්ය වෙනත් Services කොහෙද තියෙන්නේ කියලා හොයාගන්න උදව් කරන යාන්ත්රණයක්. මේකේදී ප්රධාන කොටස් දෙකක් තියෙනවා:
- Service Registration: අලුතින් Service Instance එකක් ආරම්භ වුණාම, ඒක තමන්ගේ නම, IP Address එක, Port එක වගේ තොරතුරු Service Registry එකක් (Eureka වගේ) ළඟ Register කරනවා.
- Service Lookup: වෙනත් Service එකකට Service එකක් එක්ක කතා කරන්න ඕන වුණාම, ඒක Service Registry එකෙන් අදාළ Service එකේ Instance එකක් තියෙන තැනක් ඉල්ලනවා.
මේ විදියට IP Addresses Hardcode නොකර, Services වලට Dynamic විදියට එකිනෙකාව හොයාගන්න පුළුවන් වෙනවා.
Spring Cloud Eureka Server එක හදමු!
Spring Cloud Eureka කියන්නේ Netflix ආයතනය විසින් හදලා Open Source කරපු Service Discovery Tool එකක්. Spring Cloud Ecosystem එකේදී අපිට පහසුවෙන් Eureka Server එකක් සහ Client එකක් Setup කරගන්න පුළුවන්.
පියවර 1: Spring Boot Project එකක් හදාගමු
මුලින්ම අපි Spring Initializr (https://start.spring.io/
) එකට ගිහින් අලුත් Spring Boot Project එකක් හදාගමු. මේ සඳහා පහත Dependencies තෝරන්න:
- Spring Web
- Eureka Server (Service Discovery යටතේ තියෙනවා)
Group: com.example
, Artifact: eurekaserver
කියලා දෙන්න පුළුවන්. Project එක Generate කරලා Download කරගන්න.
පියවර 2: Maven (pom.xml) Dependencies
Download කරගත්ත Project එකේ pom.xml
ෆයිල් එකේ පහත Dependency එක එකතු වෙලා තියෙනවද කියලා බලන්න. සමහරවිට ඔයා Eureka Server Dependency එක තෝරද්දී මේක auto-add වෙලා ඇති.
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- Other dependencies like Spring Web will be here -->
</dependencies>
<!-- Spring Cloud dependency management section -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
පියවර 3: Eureka Server Enable කරමු
දැන් ඔයාගේ Main Spring Boot Application Class එක (උදා: EurekaServerApplication.java
) එකට @EnableEurekaServer
Annotation එක එකතු කරන්න.
package com.example.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // This annotation enables the Eureka Server functionality
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
පියවර 4: application.yml (හෝ .properties) Configure කරමු
අන්තිමට, src/main/resources
ෆෝල්ඩර් එකේ තියෙන application.yml
ෆයිල් එකේ පහත Configurations එකතු කරන්න.
server:
port: 8761 # Default port for Eureka Server
eureka:
client:
register-with-eureka: false # This is a Eureka server, so it doesn't need to register itself
fetch-registry: false # This is a Eureka server, it doesn't need to fetch registry from itself
server:
enable-self-preservation: true # Prevents Eureka from prematurely evicting clients during network partitions
eviction-interval-timer-in-ms: 60000 # How often Eureka checks for inactive instances
මෙතනදී අපි register-with-eureka: false
සහ fetch-registry: false
කියලා දුන්නේ, මේක Eureka Server එකක් නිසා, තමන්වම Register කරගන්නවත්, තමන්ගෙන්ම Registry එක Fetch කරගන්නවත් අවශ්ය නැති නිසයි. port: 8761
කියන්නේ Eureka Server එකේ Default Port එක.
දැන් ඔයාට මේ Application එක Run කරන්න පුළුවන්. Run කරලා Browser එකේ http://localhost:8761/
කියන URL එකට ගියාම, Eureka Dashboard එක පෙනෙයි. දැනට Services කිසිවක් Register වෙලා නැති නිසා 'Instances currently registered with Eureka' කියන කොටස හිස් වෙලා තියේවි.
Clientsලව Eureka එක්ක Register කරමු!
දැන් අපි බලමු කොහොමද අපේ Microservices (Clients) මේ Eureka Server එකත් එක්ක Register කරන්නේ කියලා. අපි හිතමු අපිට 'Product Service' එකක් හදන්න ඕන කියලා.
පියවර 1: අලුත් Spring Boot Client Project එකක් හදාගමු
Spring Initializr එකට ගිහින් අලුත් Spring Boot Project එකක් හදාගන්න. මේ සඳහා පහත Dependencies තෝරන්න:
- Spring Web
- Eureka Client (Service Discovery යටතේ තියෙනවා)
Group: com.example
, Artifact: productservice
කියලා දෙන්න පුළුවන්. Project එක Generate කරලා Download කරගන්න.
පියවර 2: Maven (pom.xml) Dependencies
Download කරගත්ත Project එකේ pom.xml
ෆයිල් එකේ පහත Dependency එක එකතු වෙලා තියෙනවද කියලා බලන්න.
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Other dependencies like Spring Web will be here -->
</dependencies>
<!-- Spring Cloud dependency management section -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
පියවර 3: Eureka Client Enable කරමු
ඔයාගේ Product Service එකේ Main Application Class එකට (උදා: ProductServiceApplication.java
) @EnableEurekaClient
(හෝ @EnableDiscoveryClient
) Annotation එක එකතු කරන්න.
package com.example.productservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient // This annotation makes this service a Eureka client
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
පියවර 4: application.yml Configure කරමු
දැන් Product Service එකේ application.yml
ෆයිල් එකේ පහත Configurations එකතු කරන්න.
spring:
application:
name: product-service # The name of your service registered in Eureka
server:
port: 8081 # A different port for the Product Service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # URL of the Eureka Server
instance:
hostname: localhost # Or your actual host if deploying to a different machine
මෙහිදී,
spring.application.name: product-service
කියන්නේ මේ Service එක Eureka Server එකේ register වෙන්නේ මේ නමින් කියන එකයි. වෙනත් Services වලට මේ Service එක හොයාගන්න මේ නම තමයි පාවිච්චි කරන්නේ.server.port: 8081
කියන්නේ මේ Product Service එක Run වෙන Port එක.eureka.client.service-url.defaultZone: http://localhost:8761/eureka/
කියන්නේ Eureka Server එක තියෙන තැන.
දැන් මේ Product Service එක Run කරන්න. Eureka Server එක Run කරලා තියෙනවනම්, ටික වෙලාවකින් ඔයාට http://localhost:8761/
Eureka Dashboard එකට ගියාම 'PRODUCT-SERVICE' කියන නමින් ඔයාගේ Product Service එක Register වෙලා තියෙනවා දකින්න පුළුවන් වෙයි.
දැන් අපි Product Service එකට සරල REST Endpoint එකක් එකතු කරමු. ProductController.java
වගේ File එකක් හදලා මේ Code එක දාන්න.
package com.example.productservice.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/products")
public class ProductController {
@GetMapping("/{id}")
public String getProductById(@PathVariable String id) {
return "Product " + id + " from Product-Service";
}
@GetMapping("/status")
public String getStatus() {
return "Product-Service is UP!";
}
}
දැන් ඔයාට http://localhost:8081/products/status
වගේ URL එකකින් මේ Service එක වැඩ කරනවද කියලා බලන්න පුළුවන්.
Eureka පාවිච්චි කරලා Services කැඳවමු!
අපි හිතමු අපිට Order Service එකක් තියෙනවා කියලා. මේ Order Service එකට Product Service එකෙන් Product Details ලබාගන්න ඕන. Service Discovery නැතිනම් Product Service එකේ IP එකයි Port එකයි Hardcode කරන්න වෙනවා. හැබැයි Eureka එක්ක අපිට ඒක ලේසියෙන් කරන්න පුළුවන්.
පියවර 1: Order Service Project එකක් හදාගමු
Product Service එක හැදුවා වගේම Spring Initializr එකෙන් අලුත් Project එකක් හදාගන්න. Dependencies: Spring Web, Eureka Client. Artifact: orderservice
. Port එක 8082
විදියට application.yml
එකේ Configure කරගන්න. Eureka Server URL එකත් අමතක නොකර දෙන්න.
පියවර 2: Order Service එකේ RestTemplate Bean එක Configure කරමු
Order Service එකෙන් Product Service එකට HTTP Request යවන්න අපිට RestTemplate
එකක් පාවිච්චි කරන්න පුළුවන්. හැබැයි මේක Eureka එක්ක වැඩ කරන්න නම්, ඒක @LoadBalanced
වෙන්න ඕන. ඒ කියන්නේ, Service එකේ Multiple Instances තියෙනවනම්, මේ RestTemplate
එක ඒ අතරේ Request බෙදාහරින්න (Load Balance කරන්න) පුළුවන් වෙන්න ඕන.
OrderServiceApplication.java
එකට පහත Bean එක එකතු කරන්න.
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced // This enables client-side load balancing
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
පියවර 3: Order Service Controller එක
දැන් අපි Order Service එකේ Controller එකක් හදලා, Product Service එකෙන් Data ගන්න විදිය බලමු. OrderController.java
වගේ File එකක් හදලා මේ Code එක දාන්න.
package com.example.orderservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{orderId}/product/{productId}")
public String getOrderDetailsWithProduct(@PathVariable String orderId, @PathVariable String productId) {
// Instead of http://localhost:8081, we use the service name 'PRODUCT-SERVICE'
String productInfo = restTemplate.getForObject(
"http://PRODUCT-SERVICE/products/" + productId, String.class);
return "Order " + orderId + " contains " + productInfo;
}
@GetMapping("/status")
public String getStatus() {
return "Order-Service is UP!";
}
}
මේ Code එකේ තියෙන වැදගත්ම දේ තමයි restTemplate.getForObject("http://PRODUCT-SERVICE/products/" + productId, String.class);
කියන Line එක. මෙතනදී අපි Product Service එකේ IP Address එකක් හෝ Port එකක් දුන්නේ නෑ. ඒ වෙනුවට, අපි දුන්නේ Eureka Server එකේ Register වෙලා තියෙන Product Service එකේ නම (PRODUCT-SERVICE
). @LoadBalanced RestTemplate
එකට පුළුවන් මේ නම පාවිච්චි කරලා Eureka Registry එකෙන් Product Service එකේ Active Instance එකක IP Address එකයි Port එකයි හොයාගෙන Request එක ඒකට යවන්න. මේක තමයි Client-Side Service Discovery කියන්නේ.
දැන් ඔයා Eureka Server එක, Product Service එක, සහ Order Service එක (ඒ ඒ Port වලට අදාලව) Run කරලා, Browser එකේ http://localhost:8082/orders/123/product/P001
වගේ URL එකකට ගියාම, Order Service එක Product Service එකෙන් Data අරගෙන Response එක දෙනවා දකින්න පුළුවන් වෙයි.
නිගමනය
ඉතින් යාළුවනේ, අපි මේ ලිපියෙන් Microservices Architecture එකකදී Service Discovery කියන්නේ මොකක්ද කියන එකත්, ඒකට Spring Cloud Eureka කොහොමද පාවිච්චි කරන්නේ කියන එකත් පැහැදිලිව කතා කළා. Eureka Server එකක් Setup කරන විදිය, Clientsලව ඒකට Register කරන විදිය, සහ මේ Clientsලා කොහොමද එකිනෙකාට කතා කරගන්නේ කියන එකට අපි සරල Project එකක් පවා හැදුවා.
Service Discovery කියන්නේ Microservices වල Scalability, Resilience, සහ Maintainability කියන දේවල්වලට අත්යාවශ්ය දෙයක්. Spring Cloud Eureka වගේ Tools පාවිච්චි කරලා මේ සංකීර්ණ ගැටලුව ඉතාම පහසුවෙන් විසඳගන්න පුළුවන්. මේක ඔයාගේ ඊලඟ Microservices Project එකට Implement කරලා බලන්න! ඔයාගේ අත්දැකීම් Comment Section එකේ කියන්නත් අමතක කරන්න එපා. ජයවේවා!