Change FeignClient to Webflux with spring load balancer

2023, Apr 03    

Note.

  • 이전 post(change feignClient to reactiveFeignClient)에서 openfeign의 feign-reactor를 적용해봤는데요.
  • 취약점이 있어서 제품에는 적용하지 않았습니다.(feign-reactor-spring-cloud-starter)
  • 대신 webflux를 직접 구현하는 것으로 방향을 바꿨습니다.
    • 제품은 spring5.x에 spring boot 2.7.x를 적용하고 있기 때문에 http interface를 사용하지 못하는데요. spring 6을 사용하고 있다면 http interface 적용도 도전해볼만합니다.
  • spring cloud square가 정식으로 나온다면, 이것으로 대체가 가능할지도 모르겠습니다!!

환경

  • java 8.x
  • spring 5.x, spring boot 2.7.x

Steps

1. Add dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

2. Create bean WebClient.Builder

@LoadBalancerClient(name="crema-gateway", configuration = {FeignLBInstanceConfigurationWithHealthCheck.class})
public class GatewayClientConfiguration {

    @LoadBalanced
    @Bean
    WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}
  • neflix-ribbon에서 scl로 업그레이드하면서 @LoadBalancerClient를 config로 올린 작업을 진행했었습니다.(spring_upgrade_scl)
  • 거기에 이어서 WebClient만 bean으로 추가하면 됩니다.

3. Write service

@Service
@RequiredArgsConstructor
public class KakaoBotHistoryFlowService {
    private final GatewayClientConfiguration gatewayClientConfiguration;

    public void requestBotHistory(ActiveKakao activeKakao) {
        Flux<KakaoBotHistoryRdo> historyRdoFlux = gatewayClientConfiguration.webClientBuilder()
            .build()
            .post()
            .uri("http://crema-gateway/chatbothistory/")
            .body(Mono.fromSupplier(() -> kakaoBotHistorySdo), KakaoBotHistorySdo.class)
            .retrieve()
            .bodyToFlux(KakaoBotHistoryRdo.class);

        historyRdoFlux.subscribe(historyRdo -> sendMessage(activeKakao, historyRdo));
    }
}
  • bean으로 선언된 webclientbuilder를 통해 외부 챗봇이력을 non-blocking방식으로 조회한 후 메시지 어플리케이션으로 전달하는 로직입니다.
  • config속성이 feignclient처럼 단순하게 분리해서 동작이 되도록 라이브러리가 탄생했음 좋겠네요
  • 전체적으로 보면 gw를 통해서 호출하는 경우와 직접 feign으로 호출하는 코드가 혼재된 상태인데요 가독성도 떨어지고, 처음 보는 사람은 이해하기 어려울 것 같습니다.
  • 리팩토링 포인트가 또 하나 생성되는…

webflux 6 이라면

  • spring developer 유튜브 채널에서 interface clients in spring(https://youtu.be/lsrJu1Ul_fE)영상을 보면 현재 feign client의 단점과 앞으로 어떤 작업을 예정하고 있다는 것과 incubator 프로젝트인 spring cloud square에 대해서 설명하고 있습니다.
  • 내용 중에 HttpServiceProxyFactoryWebClientAdapter구현체를 통해서 webclient를 쉽게 작성할 수 있는 방법이 소개되고 있어서 기록차 기재합니다.
@Bean
public HttpServiceProxyFactory httpServiceProxyFactory(
		WebClient.Builder webClientBuilder, LoadBalancedExchangeFilterFunction lbFunction) {
	WebClient webClient = webClientBuilder.baseUrl("http://verification-service")
			.filter(lbFunction)
			.build();
	return HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient))
			.build();
}

Reference

baeldung spring-cloud-load-balancer

https://happycloud-lee.tistory.com/221