Resilience4j Spring Cloud Circuit Breaker Sinhala Tutorial | Hystrix Migration Guide

කට්ටියටම ආයුබෝවන්! ✋ අද අපි කතා කරන්න යන්නේ මේ දවස්වල Software Engineering ලෝකයේ ගොඩක් වැදගත් වෙන මාතෘකාවක් ගැන – ඒ තමයි Microservices architecture එකේදී අපේ applications resilient කරගන්නේ කොහොමද කියන එක. විශේෂයෙන්ම, Circuit Breakers ගැන සහ ඒකට අලුතින් ආපු, Hystrix වෙනුවට පාවිච්චි කරන්න පුළුවන් Resilience4j කියන library එක Spring Cloud එක්ක කොහොමද පාවිච්චි කරන්නේ කියලා. කලින් Hystrix පාවිච්චි කරපු කෙනෙක් නම් මේක ඔයාට ගොඩක් වැදගත් වෙයි. එහෙනම් අපි බලමු මේ වැඩේ කොහොමද ගොඩදාගන්නේ කියලා!
මොකක්ද මේ Circuit Breaker?
හරි, මුලින්ම බලමු මේ Circuit Breaker කියන්නේ මොකක්ද කියලා. හිතන්නකෝ, ඔයාගේ ගෙදර තියෙන විදුලි පරිපථ කඩනය (electrical circuit breaker) වගේමයි මේකත්. සමහර වෙලාවට අපේ Microservices applications වලදී, එක service එකක් තව service එකකට call කරනකොට ඒ service එක down වෙන්න පුළුවන්, නැත්නම් response දෙන්න පරක්කු වෙන්න පුළුවන්. එහෙම වුණාම, calling service එක ඒ service එකට continue කරලා call කරනවා. අන්තිමට මොකද වෙන්නේ? අපේ whole system එකම slow වෙලා crash වෙන්න පුළුවන්.
මේ වගේ තත්ත්වයක් වළක්වන්න තමයි Circuit Breaker pattern එක පාවිච්චි කරන්නේ. මේකෙන් කරන්නේ, අර failed වෙන service එකට යන calls ටික තාවකාලිකව නවත්වන එක. ඒක හරියට "Open" වෙනවා වගේ. ඊට පස්සේ ටික වෙලාවකින් ආයෙත් "Half-Open" වෙලා චෙක් කරනවා service එක හරිද කියලා. හරි නම් "Closed" වෙනවා, නැත්නම් ආයෙත් "Open" වෙනවා. මේකෙන් අපේ application එකේ stability එකයි, fault tolerance එකයි වැඩි වෙනවා.
Hystrix ඇයි ආයුබෝවන් කිව්වේ?
කලින් කාලේ, මේ Circuit Breaker functionality එකට ගොඩක් ජනප්රිය වුණේ Netflix Hystrix කියන library එක. Hystrix එක කාලෙකට ගොඩක් හොඳට වැඩ කරා. ඒත්, Netflix සමාගම 2018දී Hystrix active development එක නවත්තන බව නිවේදනය කළා. ඒගොල්ලෝ කිව්වේ, Hystrix එකේ තියෙන shortcomings ටිකක් නිසා, ඒ වෙනුවට Reactive Programming libraries වගේ දේවල් යොදාගන්න කියලා. ඉතින්, දැන් අලුත් projects වලට Hystrix පාවිච්චි කරන එක එච්චර හොඳ දෙයක් නෙවෙයි. ඒ වගේම, කලින් Hystrix පාවිච්චි කරපු project වලටත් අලුත් solution එකකට migrate වෙන්න වෙනවා.
Resilience4j වෙත මාරුවීම
අන්න එතකොට තමයි Resilience4j කියන library එක ඉස්මතු වෙන්නේ. Resilience4j කියන්නේ Lightweight, easy-to-use, and highly configurable fault tolerance library එකක්. මේක ReactiveX (RxJava) වගේ libraries වලට dependency නැහැ. ඒ නිසා memory footprint එක අඩුයි. මේකෙන් Circuit Breaker විතරක් නෙවෙයි, Rate Limiter, Retry, Bulkhead වගේ තව ගොඩක් patterns provide කරනවා.
Spring Cloud Circuit Breaker project එකත් දැන් Resilience4j තමයි default implementation එක විදියට recommend කරන්නේ. අපි බලමු මේක අපේ Spring Boot project එකකට add කරගෙන Circuit Breaker එකක් implement කරගන්නේ කොහොමද කියලා.
පියවර 1: Dependencies එකතු කරගැනීම (Adding Dependencies)
මුලින්ම ඔයාගේ pom.xml
(Maven නම්) හෝ build.gradle
(Gradle නම්) file එකට මේ dependencies ටික එකතු කරගන්න ඕනේ:
Maven (pom.xml
):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<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-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
</dependencies>
<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>
spring-cloud.version
එක ඔයාගේ Spring Boot version එකට ගැලපෙන විදියට දාගන්න. උදාහරණයක් විදියට, Spring Boot 2.7.x නම් 2021.0.5
වගේ එකක්, Spring Boot 3.x නම් 2022.0.x
වගේ එකක්.
පියවර 2: Service එකක් නිර්මාණය කිරීම (Creating a Service)
දැන් අපි simple service එකක් හදමු. මේ service එකෙන් තව external service එකකට call කරනවා කියලා හිතමු. ඒ call එක fail වෙන්න පුළුවන්.
MyService.java
:
package com.example.resilience4jdemo.service;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private static final String SERVICE_NAME = "externalService";
private int attempt = 0;
@CircuitBreaker(name = SERVICE_NAME, fallbackMethod = "fallbackForExternalService")
public String callExternalService() {
attempt++;
System.out.println("Attempting to call external service. Attempt #" + attempt);
// Simulate a failure for the first few attempts
if (attempt < 3) {
throw new RuntimeException("External Service is down!");
}
return "External Service Data: Success!";
}
public String fallbackForExternalService(Throwable t) {
System.out.println("Fallback method called because: " + t.getMessage());
return "Fallback response: External service is currently unavailable. Please try again later.";
}
}
මේ code එකේ callExternalService()
කියන method එකට @CircuitBreaker
annotation එක දාලා තියෙනවා. name
එක externalService
කියලා දීලා තියෙනවා. මේක තමයි Resilience4j configuration වලට පාවිච්චි කරන්නේ. fallbackMethod
එක විදියට fallbackForExternalService
කියන method එක දීලා තියෙනවා. callExternalService()
එක fail වුණොත් මේ method එක run වෙනවා.
පියවර 3: Configuration එක (Configuration)
Resilience4j Circuit Breaker එකේ behaviors control කරන්න පුළුවන් application.yml
file එක හරහා.
application.yml
:
spring:
application:
name: resilience4j-demo
cloud:
circuitbreaker:
resilience4j:
enabled: true
resilience4j:
circuitbreaker:
configs:
default: # Default configuration for all circuit breakers
slidingWindowType: COUNT_BASED # or TIME_BASED
slidingWindowSize: 5 # Number of calls to consider for error rate
failureRateThreshold: 50 # % threshold of failures before opening
waitDurationInOpenState: 5s # How long the circuit stays open
permittedNumberOfCallsInHalfOpenState: 3 # Number of calls allowed in half-open state
automaticTransitionFromOpenToHalfOpenEnabled: true # Automatically transition after waitDurationInOpenState
recordExceptions:
- org.springframework.web.client.ResourceAccessException
- java.io.IOException
- java.util.concurrent.TimeoutException
- java.lang.RuntimeException # For our example
instances:
externalService: # Specific configuration for "externalService"
baseConfig: default # Inherit from default config
# You can override specific properties here if needed for this instance
# failureRateThreshold: 60
මේ configuration එකෙන් අපි externalService
කියන Circuit Breaker එකට default settings ටිකක් දීලා තියෙනවා.
slidingWindowSize: 5
: අන්තිම calls 5 ක data analyze කරනවා.failureRateThreshold: 50
: ඒ calls 5න් 50%කට වඩා fail වුණොත් Circuit Breaker එක "Open" වෙනවා.waitDurationInOpenState: 5s
: "Open" වුණාම තත්පර 5ක් එහෙම්ම ඉන්නවා.permittedNumberOfCallsInHalfOpenState: 3
: තත්පර 5න් පස්සේ "Half-Open" state එකට ගිහින් calls 3ක් allow කරනවා test කරන්න. ඒ calls fail වුණොත් ආයෙත් "Open" වෙනවා. Success වුණොත් "Closed" වෙනවා.
පියවර 4: Controller එකක් (Creating a Controller)
දැන් අපි Controller එකක් හදලා මේ service එකට call කරමු.
MyController.java
:
package com.example.resilience4jdemo.controller;
import com.example.resilience4jdemo.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/call")
public String callService() {
return myService.callExternalService();
}
}
පියවර 5: Application එක run කරලා බලමු (Running and Testing the Application)
දැන් ඔයාට Spring Boot application එක run කරලා http://localhost:8080/call
එකට calls ටිකක් දෙන්න පුළුවන්.
- මුලින්ම: පළවෙනි calls 2-3 fail වෙලා
fallbackMethod
එකෙන් response එක එනවා. (Circuit Breaker එකCLOSED
state එකේ ඉඳන්OPEN
වෙනකල්). Console එකේ "Attempting to call external service." කියලා print වෙලා "Fallback method called..." කියලා එනවා. - Circuit Open වුණාම: ඊට පස්සේ එන calls වලට
fallbackMethod
එකෙන් කෙලින්ම response එක එනවා, service method එක run වෙන්නේ නැහැ. (Circuit Breaker එකOPEN
state එකේ). Console එකේ "Attempting to call external service." කියලා print වෙන්නේ නැහැ, කෙලින්ම "Fallback method called..." කියලා එනවා. - Half-Open වුණාම: තත්පර 5කට පස්සේ (application.yml එකේ waitDurationInOpenState අනුව), Circuit Breaker එක
HALF_OPEN
state එකට යනවා. එතකොට ආයෙත් calls 3ක් allow කරනවා. ඒ calls success වුණොත් Circuit Breaker එකCLOSED
වෙනවා. (අපේ code එකේ 3න් පස්සේ success නිසා, 3-4-5 attempts වලදී fail වෙලා, 6-7-8 attempts වලදීHALF_OPEN
එකේ ඉඳන් success වෙලාCLOSED
වෙනවා.)
ඔයාට Actuator endpoints පාවිච්චි කරලා Circuit Breaker එකේ status එක බලන්නත් පුළුවන්. http://localhost:8080/actuator/health
හෝ http://localhost:8080/actuator/metrics/resilience4j.circuitbreaker.state
වගේ.
මේකෙන් ඔයාට තේරෙන්න ඕනේ, අපේ main business logic එකට හානියක් නොවී, අනිත් service එක down වුණාම ඒක manage කරන්න Circuit Breaker එක කොච්චර උදව් වෙනවද කියලා.
අවසන් වචන...
ඉතින් අද අපි බැලුවා Spring Cloud Circuit Breaker pattern එක Resilience4j එක්ක කොහොමද පාවිච්චි කරන්නේ කියලා. Hystrix එකට වඩා Resilience4j එක lightweight, modern, and performant solution එකක්. Microservices ලෝකයේදී Fault Tolerance කියන්නේ නැතුවම බැරි දෙයක්. මේ වගේ Circuit Breaker libraries පාවිච්චි කිරීමෙන් ඔයාගේ application එකේ stability එකයි, user experience එකයි ගොඩක් වැඩි දියුණු කරගන්න පුළුවන්.
මතක තියාගන්න, හොඳ software engineer කෙනෙක් වෙන්න නම් මේ වගේ modern practices ගැන updated වෙලා ඉන්න එක ගොඩක් වැදගත්.
මේක ඔයාගේ project වලටත් implement කරලා බලන්න. ඔයාට ප්රශ්න තියෙනවා නම්, නැත්නම් ඔයාගේ අත්දැකීම් කොහොමද කියලා පහලින් comment එකක් දාන්න! අපි කතා කරමු! 🎉