Я хочу реализовать шаблон CircuitBreaker в приложении весенней загрузки. У меня есть два API, и каждый API имеет свою собственную конфигурацию. Я определил эти два метода конфигурации в классе приложения. Кроме того, в классе приложения я определил Spring Bean типа CustomCircuitBreakerFactory. Этот тип является пользовательским классом и будет создан для управления и настройки автоматических выключателей для API. Этот Spring bean-компонент принимает в своем конструкторе три параметра:
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory;
import org.springframework.context.annotation.Bean;
import java.time.Duration;
import java.util.List;
@SpringBootApplication(scanBasePackages = {"com.company.*"})
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
@Bean
@Qualifier("api1CircuitBreakerConfig")
public CircuitBreakerConfig api1CircuitBreakerConfig() {
return CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(10))
.permittedNumberOfCallsInHalfOpenState(10)
.slidingWindowSize(100)
.minimumNumberOfCalls(20)
.recordExceptions(RuntimeException.class, CallNotPermittedException.class)
.build();
}
@Bean
@Qualifier("api2CircuitBreakerConfig")
public CircuitBreakerConfig api2CircuitBreakerConfig() {
return CircuitBreakerConfig.custom()
.failureRateThreshold(40)
.waitDurationInOpenState(Duration.ofSeconds(10))
.permittedNumberOfCallsInHalfOpenState(10)
.slidingWindowSize(150)
.minimumNumberOfCalls(30)
.recordExceptions(RuntimeException.class, CallNotPermittedException.class)
.build();
}
@Bean
public CustomCircuitBreakerFactory customCircuitBreakerFactory(
ReactiveResilience4JCircuitBreakerFactory circuitBreakerFactory,
CircuitBreakerConfig api1CircuitBreakerConfig,
CircuitBreakerConfig api2CircuitBreakerConfig) {
return new CustomCircuitBreakerFactory(circuitBreakerFactory, api1CircuitBreakerConfig, api2CircuitBreakerConfig);
}
}
Это реализация CustomCircuitBreakerFactory. Это класс компонентов для настройки автоматических выключателей и управления ими. Его конструктор принимает три параметра и имеет два метода для создания и настройки экземпляров автоматических выключателей для каждого из базовых API.
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class CustomCircuitBreakerFactory {
private final ReactiveResilience4JCircuitBreakerFactory circuitBreakerFactory;
private final CircuitBreakerConfig api1CircuitBreakerConfig;
private final CircuitBreakerConfig api2CircuitBreakerConfig;
public CustomCircuitBreakerFactory(
ReactiveResilience4JCircuitBreakerFactory circuitBreakerFactory,
@Qualifier("api1CircuitBreakerConfig") CircuitBreakerConfig api1CircuitBreakerConfig,
@Qualifier("api2CircuitBreakerConfig") CircuitBreakerConfig api2CircuitBreakerConfig) {
this.circuitBreakerFactory = circuitBreakerFactory;
this.api1CircuitBreakerConfig= api1CircuitBreakerConfig;
this.api2CircuitBreakerConfig= api2CircuitBreakerConfig;
}
public CircuitBreaker createApi1CircuitBreaker() {
return (CircuitBreaker) circuitBreakerFactory.create("api1");
}
public CircuitBreaker createApi2CircuitBreaker() {
return (CircuitBreaker) circuitBreakerFactory.create("api2");
}
}
Когда я запустил приложение, я получил эту ошибку: Параметр 1 метода customCircuitBreakerFactory в ApiApplication требовал одного bean-компонента, но были найдены 2: - api1CircuitBreakerConfig: определяется методом api1CircuitBreakerConfig в ApiFacadeApplication. - api2CircuitBreakerConfig: определяется методом api2CircuitBreakerConfig в ApiFacadeApplication. Я использовал @Qualifier, но он не работает.
Я использовал @Qualifier, но он не работает.
кажется, вы передаете параметры конструктору, управляемому пружиной, эти параметры управляются неправильно
Ой, подождите, на самом деле он жалуется не на конструктор, а на ApiApplication.customCircuitBreakerFactory. Вы должны использовать @Qualifier в параметрах этого метода.
Да! теперь это работает! Я удалил @Qualifier из определения конструктора CustomCircuitBreakerFactory и добавил его в ApiApplication.customCircuitBreakerFactory.




В вашем коде есть несколько проблем
@Qualifier оказывает эффект, когда компонент вводится, но не предоставляется. Установка пользовательского квалификатора для компонента возможна с помощью аннотаций, создающих компонент: @Bean, @Service, @Component или подобных.@Component, и @Bean добавляют компонент в контекст Spring. Вам следует использовать любой из них, но не оба.@Qualifier следует использовать везде, где происходит процесс автоподключения.Итак, шаги, которые помогут вашему коду работать:
@Qualifier на api1CircuitBreakerConfig() и api2CircuitBreakerConfig() и вместо этого добавьте имена в аннотации @Bean. Обратите внимание, что по умолчанию Spring использует квалификатор, равный имени метода/класса, поэтому в вашем случае он избыточен.@Component из CustomCircuitBreakerFactory@Qualifer к параметрам ApiApplication.customCircuitBreakerFactory
Не хватает
@Autowiredв конструкторе?