Java Microservices Load Balancing: Client-Side (Ribbon) & Server-Side Explained | Sinhala Guide

Software Engineering ලෝකයේ දැන් හැමතැනම කතාබහට ලක්වෙන Hot Topic එකක් තමයි Microservices Architecture කියන්නේ. ඒත් මේ Microservices වලින් අපිට ලැබෙන වාසි උපරිමයෙන් ලබාගන්න නම්, ඒවා හරියට Deploy කරලා Manage කරන්න පුළුවන් වෙන්න ඕනේ. ඒ වගේම, අපේ Service එකට එකපාරට Request ගොඩක් ආවොත් ඒවා Handle කරන්න Application එක Stable විදිහට පවත්වාගෙන යන්නත් පුළුවන් වෙන්න ඕනේ.
අන්න ඒ වගේ අවස්ථාවලදී අපිට ගොඩක් වැදගත් වෙන concept එකක් තමයි Load Balancing කියන්නේ. හිතන්න, අපේ Service එකක Instance (පිටපත්) කිහිපයක් තියෙනවා කියලා. මේ හැම Instance එකක්ම එකම කාර්යය කරනවා. එතකොට Request එකක් ආවම ඒක මේ Instance කිහිපය අතර බෙදාහරින්න ඕනේ. එහෙම නොකළොත් මොකද වෙන්නේ? එක Instance එකකට විතරක් Request ගොඩක් ආවොත් ඒක Overload වෙලා Down වෙන්න පුළුවන්. ඒත් Load Balancing හරහා අපිට මේ Request ටික ඒ Instance අතර සමව බෙදාහරින්න පුළුවන්.
මේ Article එකෙන් අපි Java Microservices පරිසරයක Load Balancing කියන්නේ මොකක්ද, ඒක ඇයි වැදගත් වෙන්නේ, ඒ වගේම Client-Side Load Balancing (විශේෂයෙන්ම Spring Cloud Ribbon) සහ Server-Side Load Balancing කියන ක්රම දෙක ගැනත් සවිස්තරාත්මකව කතා කරනවා. මේ Guide එක ඔයාගේ Microservices knowledge එකට අලුත් දෙයක් එකතු කරයි කියලා අපි විශ්වාස කරනවා.
Microservices වල Load Balancing ඇයි මෙච්චර වැදගත්?
මයික්රෝ සර්විස් කියන්නේ පොඩි පොඩි ස්වාධීන කොටස් වලට බෙදිලා තියෙන application එකක්. මේ නිසා ගොඩක් වාසි තියෙනවා. ඒත් එක් එක් සර්විස් එකට Request ගොඩක් එකපාර ආවොත් මොකද වෙන්නේ? හිතන්න ඔයාගේ Customer Service එකට එකපාර Request මිලියනයක් ආවා කියලා. Single instance එකකට මේ හැම Request එකක්ම Handle කරන්න බැහැ නේද? අන්න ඒ වගේ වෙලාවට තමයි Load Balancing නැතුවම බැරි වෙන්නේ.
- High Availability (ඉහළ ක්රියාකාරීත්වය): Load Balancer එකක් තියෙනවා නම්, Service Instance එකක් Down වුණත්, Request ස්වයංක්රීයව අනිත් Instance වලට යොමු කරනවා. ඒ කියන්නේ User කෙනෙක්ට Downtime එකක් දැනෙන්නේ නැහැ.
- Scalability (පරිමාණය කළ හැකි බව): Traffic එක වැඩිවෙනකොට අපිට පුළුවන් Service එකේ අලුත් Instance වැඩි කරන්න. Load Balancer එක මේ අලුත් Instance වලටත් Request බෙදලා දෙනවා. ඒ නිසා අපේ Application එකට ඕනෑම Traffic ප්රමාණයකට ඔරොත්තු දෙන්න පුළුවන්.
- Performance Improvement (කාර්ය සාධනය වැඩි දියුණු කිරීම): Request ටික සමව බෙදිලා යන නිසා, කිසිම Instance එකක් Overload වෙන්නේ නැහැ. ඒකෙන් Overall Application Performance එක වැඩි වෙනවා. Request Response time අඩු වෙනවා.
- Fault Tolerance (දෝෂ ඉවසීම): Load Balancer එකකින් Request බෙදා හැරීම කරන නිසා, එක් Instance එකක ගැටලුවක් ආවත්, ඒකෙන් සම්පූර්ණ System එකටම බලපෑමක් වෙන්නේ නැහැ.
Client-Side Load Balancing (Spring Cloud Ribbon සමග)
Client-Side Load Balancing කියන්නේ, Request එක යවන Client එකම තීරණය කරනවා Request එක යවන්නේ Service එකේ තියෙන මොන Instance එකටද කියලා. මේකට Client එකට පුළුවන් වෙන්න ඕනේ Service එකේ තියෙන හැම Instance එකක් ගැනම විස්තර දැනගන්න. මේකට Service Discovery Mechanism එකක් (උදා: Eureka) ගොඩක් වැදගත් වෙනවා.
Java Microservices වලට Client-Side Load Balancing වලදී ගොඩක් ජනප්රිය Framework එකක් තමයි Spring Cloud Ribbon. Ribbon කියන්නේ Netflix එකෙන් develop කරපු Client-Side Load Balancer එකක්. Spring Cloud එක්ක Ribbon එක combine වුණාම අපිට ඉතාමත් පහසුවෙන් Client-Side Load Balancing implement කරන්න පුළුවන්.
Ribbon ක්රියා කරන ආකාරය:
- Client එක Service Discovery Server එකකින් (උදා: Eureka) Service එකේ තියෙන හැම Instance එකකම Network Location (IP Address, Port) ඉල්ලනවා.
- Service Discovery Server එක Client එකට මේ හැම Instance එකකම විස්තර ලබා දෙනවා.
- Client එක (Ribbon) දැන් තීරණය කරනවා මේ ලබාගත් Instance අතරින් Request එක යවන්නේ මොන Instance එකටද කියලා. මේකට විවිධ Load Balancing Algorithms (උදා: Round Robin, Least Connections) භාවිතා කරනවා.
- Request එක තෝරාගත් Instance එකට යවනවා.
ප්රායෝගික උදාහරණයක්: Spring Boot සහ Ribbon
අපි හිතමු අපිට Product Service
එකක් තියෙනවා කියලා. මේ Service එකේ Instance කිහිපයක් Run වෙනවා. දැන් අපිට ඕනේ Order Service
එකෙන් මේ Product Service
එකට Request යවද්දී Ribbon භාවිතා කරලා Load Balancing කරන්න. මේකට Eureka Server එකක් සහ Eureka Client (Product Service, Order Service දෙකම) අවශ්ය වෙනවා.
පියවර 1: Eureka Server එකක් හදමු
pom.xml
ටික:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
main application class
එකට @EnableEurekaServer
එකතු කරන්න:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
application.properties
:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
පියවර 2: Product Service එක හදමු (Eureka Client එකක් විදිහට)
pom.xml
ටික:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
main application class
එකට @EnableDiscoveryClient
එකතු කරන්න:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
@GetMapping("/products")
public String getProducts() {
return "List of products from Product Service running on port " + System.getProperty("server.port");
}
}
application.properties
:
spring.application.name=product-service
server.port=8081
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
මේ Product Service
එකේ 8081 සහ 8082 වගේ විවිධ Ports වල Instance දෙකක් හෝ වැඩි ගණනක් Run කරන්න පුළුවන්. ඒකට Command Line එකෙන් java -jar product-service.jar --server.port=8082
වගේ Run කරන්න.
පියවර 3: Order Service එක හදමු (Ribbon Client එකක් විදිහට)
pom.xml
ටික:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
main application class
එකට @EnableDiscoveryClient
සහ @LoadBalanced
(RestTemplate එකට) එකතු කරන්න:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
private final RestTemplate restTemplate;
public OrderServiceApplication(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/order-products")
public String getOrderProducts() {
// 'product-service' කියන එක තමයි Eureka එකේ register කරලා තියෙන service name එක.
// Ribbon එක මේ service name එකෙන් අදාළ IP:Port හොයාගෙන Request එක redirect කරනවා.
String response = restTemplate.getForObject("http://product-service/products", String.class);
return "Order requested products: " + response;
}
}
application.properties
:
spring.application.name=order-service
server.port=8080
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
දැන් ඔයාට පුළුවන් Eureka Server
එක, Product Service
එකේ Instance දෙකක් (එකක් 8081, අනිත් එක 8082), සහ Order Service
එක Run කරන්න. ඊට පස්සේ http://localhost:8080/order-products
වලට Request කිහිපයක් යවලා බලන්න. ඔයාට පේයි Product Service එකේ Response එක එක පාරක් 8081 Port එකෙනුත්, තවත් පාරක් 8082 Port එකෙනුත් එනවා. මේ තමයි Ribbon එක Client-Side Load Balancing කරන විදිහ.
Server-Side Load Balancing
Server-Side Load Balancing කියන්නේ, Request එක Client එකෙන් එනකොට, ඒක Service Instances වලට යවන්න කලින් වෙනම Load Balancer Component එකක් හරහා යවනවා. මේ Load Balancer එක (ඒක Hardware Device එකක් වෙන්න පුළුවන්, Software එකක් වෙන්න පුළුවන්, Cloud Service එකක් වෙන්න පුළුවන්) Incoming Requests Handle කරලා ඒවා Service Instance අතර බෙදා හරිනවා. Client එකට කිසිම අදහසක් නැහැ තමන්ගේ Request එක යන්නේ මොන Service Instance එකටද කියලා. ඒක දන්නේ Load Balancer එක විතරයි.
Server-Side Load Balancers වල උදාහරණ:
- Nginx: Open-source reverse proxy server එකක් සහ Load Balancer එකක්. ගොඩක්ම Web Traffic වලට ජනප්රියයි.
- HAProxy: High Availability සහ Load Balancing වලටම නිර්මාණය කරපු Open-source solution එකක්.
- Cloud Provider Load Balancers: AWS Elastic Load Balancer (ELB), Azure Load Balancer, Google Cloud Load Balancing වගේ ඒවා. මේවා Cloud Native Load Balancers, ඒවා Cloud Platform එකෙන්ම managed කරනවා.
Server-Side Load Balancing ක්රියා කරන ආකාරය (සංකල්පමය වශයෙන්):
Client එක Request එක යවන්නේ Load Balancer එකේ IP Address / Domain Name එකට. Load Balancer එකට Service එකේ තියෙන හැම Instance එකක් ගැනම විස්තර තියෙනවා. Request එක ආවම Load Balancer එක තීරණය කරනවා ඒක යවන්නේ මොන Instance එකටද කියලා. මේකටත් විවිධ Algorithms (උදා: Round Robin, Least Connections, IP Hash) භාවිතා කරනවා. Request එක Load Balancer එක හරහා තෝරාගත් Instance එකට යනවා. Response එකත් Load Balancer එක හරහාම Client එකට එනවා.
# Nginx උදාහරණයක් (conceptual) - nginx.conf file එකේ snippet එකක්:
http {
upstream product_backend {
# Product Service Instance වල Addresses
server 192.168.1.10:8081;
server 192.168.1.11:8082;
server 192.168.1.12:8083;
}
server {
listen 80;
location /products {
proxy_pass http://product_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
මේ Nginx Configuration එකෙන් කියවෙන්නේ, /products
කියලා Request එකක් ආවොත්, ඒක product_backend
කියන upstream group එකේ තියෙන servers අතරට බෙදාහරිනවා කියලා. Nginx by default Round Robin algorithm එක භාවිතා කරනවා.
Client-Side vs. Server-Side Load Balancing: දෙක අතර වෙනස
දැන් අපි මේ Load Balancing ක්රම දෙක අතර තියෙන ප්රධාන වෙනස්කම් මොනවද කියලා බලමු. මේවා දැනගෙන ඉන්න එක ඔයාගේ project එකට වඩාත්ම ගැලපෙන approach එක තෝරගන්න උදව් වෙයි.
විශේෂාංගය | Client-Side Load Balancing (උදා: Ribbon) | Server-Side Load Balancing (උදා: Nginx, ELB) |
---|---|---|
Implementation Location | Client Application (සේවා ඉල්ලන පැත්ත) | External Component (සේවා සපයන පැත්තට කලින්) |
Service Discovery | අනිවාර්යයෙන්ම අවශ්යයි (Client එකට Instance ලිපිනයන් දැනගන්න) | Load Balancer එක Service Registry එකක් සමඟ සම්බන්ධ විය හැක, නමුත් Client එකට අවශ්ය නැත. |
Traffic Visibility | Client එකට තමන් යවන Instance එක ගැන තීරණයක් ගන්න පුළුවන්. | Client එකට තමන් යවන Instance එක ගැන කිසිම දැනුමක් නැහැ. |
Scalability Management | නව Instance Add කරන විට, Client ධාවන කාලය තුළ ඒවා Discovery කරගත යුතුය. | Load Balancer විසින් අලුතින් Add වන Instance ස්වයංක්රීයව හඳුනාගෙන ඒවාට Request යොමු කරයි. |
Complexity | Client Application එකේ Logic වැඩි විය හැක. | Load Balancer Management එකේ Complexity එක වැඩි විය හැක. |
Cost | Client side libraries නිසා වැඩිපුර Cost එකක් නැහැ. | Dedicated Hardware/Software හෝ Cloud services වලට ගෙවීමට සිදු විය හැක. |
Typical Use Case | Spring Cloud Ecosystem තුළ Microservices අතර Communication සඳහා. | External Traffic Gateway (APIs, Web Traffic) සහ Legacy Systems සඳහා. |
ඔබට වඩාත් සුදුසු කුමක්ද?
මේ ප්රශ්නයට නිශ්චිත උත්තරයක් නැහැ. ඒක තීරණය වෙන්නේ ඔයාගේ project එකේ අවශ්යතා අනුවයි.
- ඔයා Spring Cloud Ecosystem එකක් ඇතුළේ වැඩ කරනවා නම්, Client-Side Load Balancing (Ribbon වගේ) ගොඩක් පහසුයි implement කරන්න. ඒක Microservices අතර internal communication වලට ගොඩක් හොඳයි.
- ඔයාට External Traffic එක Manage කරන්න, Web Application එකකට එන Requests බෙදාහරින්න, නැත්නම් Microservices වලට කලින් Global Traffic Distribution එකක් ඕනේ නම්, Server-Side Load Balancers (Nginx, Cloud Load Balancers) තමයි ගොඩක් සුදුසු. මේවා Security, SSL Termination, Caching වගේ දේවලුත් එක්ක එන නිසා තවත් වාසි තියෙනවා.
ගොඩක් වෙලාවට Real-world Microservices Architectures වලදී මේ ක්රම දෙකම එකට භාවිතා කරනවා. External Traffic එකට Server-Side Load Balancer එකකුත්, Internal Microservice Communication වලට Client-Side Load Balancer එකකුත් භාවිතා කරනවා.
අවසන් වචන
ඉතින් යාලුවනේ, මේ Article එකෙන් අපි Java Microservices වල Load Balancing කියන්නේ මොකක්ද, ඒක ඇයි මෙච්චර වැදගත් වෙන්නේ, ඒ වගේම Client-Side (Ribbon) සහ Server-Side Load Balancing ක්රම දෙක ගැනත්, ඒවා implement කරන හැටි ගැනත් හොඳ අවබෝධයක් ගන්න උත්සාහ කළා. Microservices වල Robustness, Scalability, සහ High Availability කියන ගුණාංග වලට Load Balancing කියන්නේ අත්යවශ්යම Component එකක්.
මතක තියාගන්න, Load Balancing කියන්නේ Traffic Distribution එකක් විතරක් නෙමෙයි, Service Discovery, Health Checks, සහ Intelligent Routing වගේ ගොඩක් දේවල් ඒකට සම්බන්ධයි. Spring Cloud Ecosystem එකේදී Ribbon වගේ Libraries වලින් මේ හැමදේම පහසුවෙන් Manage කරන්න පුළුවන්. ඒ වගේම Production Environment වලදී Dedicated Server-Side Load Balancers වලට තියෙන වටිනාකම අමතක කරන්න එපා.
දැන් ඔයාට මේ ගැන හොඳ අදහසක් ඇති කියලා හිතනවා. පුළුවන් නම්, මේ Code Examples ටික ඔයාගේ Local Machine එකේ Run කරලා බලන්න. එතකොට තවත් හොඳට Concept එක තේරෙයි. මේ ගැන ඔයාගේ අදහස්, ප්රශ්න හෝ අත්දැකීම් පහත Comment Section එකේ දාන්න. අපි ඒ ගැන කතා කරමු! තවත් මේ වගේ Article එකකින් හම්බවෙමු!