-
Spring Cloud Feign FallbackFactory가 동작하지 않는다Spring Framework 2023. 7. 6. 00:01728x90
공식문서를 살펴보자
If Spring Cloud CircuitBreaker is on the classpath and spring.cloud.openfeign.circuitbreaker.enabled=true, Feign will wrap all methods with a circuit breaker.
CircuitBeaker가 classpath에 존재하고, spring.cloud.openfeign.circuitbraker.enabled=true가 되어있으면 circuit braker로 모든 feign 메서드를 래핑 한다.
기본옵션은 false
Fallback Factory 구현
import org.springframework.cloud.openfeign.FallbackFactory import org.springframework.cloud.openfeign.FeignClient import org.springframework.http.ResponseEntity import org.springframework.stereotype.Component import org.springframework.web.bind.annotation.GetMapping @FeignClient( name = "test", url = "localhost:8081", fallbackFactory = TestClient.TestFallbackFactory::class ) interface TestClient { @GetMapping("/test") fun get(): ResponseEntity<WrongFeignDataClass> @Component class TestFallbackFactory : FallbackFactory<FallbackWithFactory> { override fun create(cause: Throwable): FallbackWithFactory { println(cause.message) return FallbackWithFactory() } } class FallbackWithFactory : TestClient { override fun get(): ResponseEntity<WrongFeignDataClass> { println("fallback start") return ResponseEntity.notFound().build() } } } data class WrongFeignDataClass( val notExistProperty: String, )
의도적으로 WrongFeignDataClass로 이상한 클래스를 넣어 파싱에러가 나도록 하였습니다.
application.yml에 옵션
spring: cloud: openfeign: circuitbreaker: enabled: true alphanumeric-ids: enabled: true client: config: default: connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic
하지만 동작하지 않는다 : CircuitBreakerPresentFeignBuilderConfiguration
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(CircuitBreaker.class) @ConditionalOnProperty("spring.cloud.openfeign.circuitbreaker.enabled") protected static class CircuitBreakerPresentFeignBuilderConfiguration { @Bean @Scope("prototype") @ConditionalOnMissingBean({ Feign.Builder.class, CircuitBreakerFactory.class }) public Feign.Builder defaultFeignBuilder(Retryer retryer) { return Feign.builder().retryer(retryer); } @Bean @Scope("prototype") @ConditionalOnMissingBean @ConditionalOnBean(CircuitBreakerFactory.class) public Feign.Builder circuitBreakerFeignBuilder() { return FeignCircuitBreaker.builder(); } }
찾아보다 보니 CircuitBreakerPresentFeignBuilderConfiguration클래스를 발견했으며 해당 클래스에서 Property 옵션이 true인 경우에 적용되는 것을 볼 수 있습니다.
그리고 디버깅으로 쫓아가보니 FeignCircuitBreaker가 등록되어야 할 것 같은데 Fenign.builder()가 호출되고 있었습니다.
그러면 여기서 조건인 CircuitBrakerFactory 클래스가 존재해야 한다는 것이 마음에 걸립니다.
위의 문서에서 간과했던 것이 CircuitBeaker가 classpath에 존재해야 한다는 것이었습니다.
Dependencies 추가
dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework:spring-webmvc") implementation(enforcedPlatform("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}")) implementation("org.springframework.cloud:spring-cloud-starter-openfeign") implementation("io.github.openfeign:feign-okhttp") implementation("org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j:1.0.2.RELEASE") }
맨 하단의 circuitbraker를 추가해주고 나니 이제 정상적으로 동작합니다.
Spring 문서에서는 서킷브레이커의 의존성을 명시해주지 않아서 조금 아쉬웠습니다.
Fallback이 드디어 동작한다
Error while extracting response for type [class com.example.client.feign.WrongFeignDataClass] and content type [application/json] fallback start
참고자료
https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/appendix.html
'Spring Framework' 카테고리의 다른 글
FeignClient vs WebClient vs RestTemplate (2) 2023.07.13 FeignClient 헤더 가져오기 (0) 2023.07.12 Spring Boot 2 to Spring Boot 3 마이그레이션 (0) 2023.06.07 ThreadLocal이란? (0) 2023.05.19 Controller에서 List 받기(+ dto로 받고 validation) (0) 2023.03.22