Автоматический выключатель Resilience4j: не работает при использовании с декораторамиJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Автоматический выключатель Resilience4j: не работает при использовании с декораторами

Сообщение Anonymous »

Я пытаюсь реализовать Resilience4j программно, а также принудительный переход состояния через конечную точку покоя. Но, к сожалению, автоматический выключатель не работает, когда я использую Декоратор. Интересно, это работает, когда я использую это с WebClient.
Мой класс контроллера:

Код: Выделить всё

@RestController
@RequestMapping("v1/profileinfo")
public class WebController {
public static final Logger LOG = LoggerFactory.getLogger(WebController.class);

@Autowired
private CircuitBreakerRegistry circuitBreakerRegistry;

@Autowired
private AppConstants appConstants;

@Autowired
private ProfileService profileService;

@GetMapping("/{profId}")
public ResponseEntity
 getProfileInfo(@PathVariable("profId") Long profId){

ProfielInfo resp = null;
resp = profileService.getProfileInfo(profId);
return new ResponseEntity(resp, HttpStatus.OK);
}

@PutMapping("circuitbreaker/{state}")
public String setCircuitBreaker(@PathVariable("state") String state) {

if(state.toUpperCase().equals(appConstants.CB_CLOSED)) {
circuitBreakerRegistry.circuitBreaker("benefitService").transitionToClosedState();
}

if(state.toUpperCase().equals(appConstants.CB_OPEN)) {
circuitBreakerRegistry.circuitBreaker("benefitService").transitionToForcedOpenState();
}

return state;
}

}
Служба ProfileInfo:

Код: Выделить всё

....
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;

import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.decorators.Decorators;

@Service
public class ProfileService {
public static final Logger LOG = LoggerFactory.getLogger(ProfileService.class);

@Autowired
private CircuitBreakerConfig circuitBreakerConfig; //ADDED

@Autowired
private CircuitBreakerRegistry circuitBreakerRegistry; //ADDED

@Autowired
private UserInfoService userInfoService;

@Autowired
private BenefitService benefitService;

public ProfielInfo getProfileInfo(Long profId) throws TimeoutException {

CircuitBreaker circuitBreaker = circuitBreakerRegistry
.circuitBreaker("benefitService");

ProfielInfo profileInfo = null;
profileInfo = new ProfielInfo();

UserInfo userInfo = null;
userInfo = userInfoService.getUserInfo(profId);

Benefit benefit = null;
Supplier supplier = () -> benefitService.getBenefitInfo(profId);
LOG.info("||||Calling benefitService...");
benefit = Decorators.ofSupplier(supplier)
.withCircuitBreaker(circuitBreaker) //---> Why it's not Working here ??
.withFallback(e -> buildFallbackBenefitInfo(profId))
.get();

profileInfo.setUserInfo(userInfo);
profileInfo.setBenefit(benefit);

LOG.info("---End of the ProfileService.getProfileInfo()---");
return profileInfo;
}

public Benefit buildFallbackBenefitInfo(Long memId) {
Benefit benefit = null;
benefit = new Benefit();
benefit.setBenefitId("00000");
benefit.setMemeberId("00000");

return benefit;
}
}
Класс BenefitService, который вызывает внешний API с помощью веб-клиента. Здесь работает автоматический выключатель и принимает мои индивидуальные настройки.

Код: Выделить всё

@Service
public class BenefitService {
@Autowired
private CircuitBreakerRegistry circuitBreakerRegistry;

@Autowired
private WebClient benefitApiClient;

public Benefit getBenefitInfo(long profId) {

CircuitBreaker circuitBreaker = circuitBreakerRegistry
.circuitBreaker("benefitService");

return benefitApiClient.get()
.uri("/" + profId)
.retrieve()
.bodyToMono(Benefit.class)
.timeout(Duration.ofSeconds(3))
.transformDeferred(CircuitBreakerOperator.of(circuitBreaker)) // works here
.block();
}
}
Мой класс конфигурации автоматического выключателя:

Код: Выделить всё

@Configuration
public class CircuitBreakerConfigs {

@Value("${circuitbreaker.failureRateThreshold}")
private int failureRateThreshold;

@Value("${circuitbreaker.slowCallRateThreshold}")
private int slowCallRateThreshold;

@Value("${circuitbreaker.waitDurationInOpenState}")
private int waitDurationInOpenState;

@Value("${circuitbreaker.slowCallDurationThreshold}")
private int slowCallDurationThreshold;

@Value("${circuitbreaker.permittedNumberOfCallsInHalfOpenState}")
private int permittedNumHalfOpenState;

@Value("${circuitbreaker.minimumNumberOfCalls}")
private int minimumNumberOfCalls;

@Value("${circuitbreaker.slidingWindowSize}")
private int slidingWindowSize;

@Bean
public CircuitBreakerConfig circuitBreakerConfig() {
return CircuitBreakerConfig.custom()
.failureRateThreshold(failureRateThreshold)
.slowCallRateThreshold(slowCallRateThreshold)
.waitDurationInOpenState(Duration.ofSeconds(waitDurationInOpenState))
.slowCallDurationThreshold(Duration.ofSeconds(slowCallDurationThreshold))
.permittedNumberOfCallsInHalfOpenState(permittedNumHalfOpenState)
.minimumNumberOfCalls(minimumNumberOfCalls)
.slidingWindowType(SlidingWindowType.COUNT_BASED)
.slidingWindowSize(slidingWindowSize)
.enableAutomaticTransitionFromOpenToHalfOpen()
.recordExceptions(IOException.class, TimeoutException.class)
.build();
}

@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
return CircuitBreakerRegistry.of(circuitBreakerConfig());
}

}
application.yml:

Код: Выделить всё

server:
port: 9099

management:
endpoints:
web:
exposure:
include: "*"

resilience4j.circuitbreaker:
configs:
default:
registerHealthIndicator: true

circuitbreaker:
failureRateThreshold: 50
slowCallRateThreshold: 50
waitDurationInOpenState: 60
slowCallDurationThreshold: 60
minimumNumberOfCalls: 1
permittedNumberOfCallsInHalfOpenState: 3
slidingWindowSize: 5
build.gradle:

Код: Выделить всё

plugins {
id 'org.springframework.boot' version '2.7.3'
id 'io.spring.dependency-management' version '1.0.13.RELEASE'
id 'java'
}

group = 'com.demo.ref'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version: '2.7.2'
implementation group: 'io.github.resilience4j', name: 'resilience4j-spring-boot2', version: '1.5.0'
implementation group: 'io.github.resilience4j', name: 'resilience4j-reactor', version: '1.5.0'
implementation group: 'io.github.resilience4j', name: 'resilience4j-all', version: '1.5.0'
implementation group: 'io.micrometer', name: 'micrometer-registry-prometheus', version: '1.9.3'

}

tasks.named('test') {
useJUnitPlatform()
}
Как я уже упоминал выше, автоматический выключатель не работает, когда я использую декораторы из класса ProfileService. Но если я перенесу его в класс BenefitService и использую с WebClient, он будет работать отлично. Мой внешний API (API Benefit) настроен на задержку на 10 секунд, поэтому время ожидания этого вызова здесь истекает) Может кто-нибудь мне помочь?

Подробнее здесь: https://stackoverflow.com/questions/734 ... decorators
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»