실무에서 알게된 내용

시스템 별로 Feign Client readTimeout 설정 때문에 내부 동작 코드 분석

사람냄새나는 개발자 2022. 6. 14. 17:06

현재 내가 담당하고 있는 서비스는 Feign Client로 OkHttpClient를 사용하고 있었다.

feign.okhttp.enabled: true

위 yml 설정 때문에, 아래 코드를 보면 Feign Client로 OkHttpClient를 사용하게 된다.

 

[OkHttpFeignLoadBalancedConfiguration 클래스]

다만, 아래 이미지를 보면 OkHttpClient 가 바로 호출되는 건 아니고 현재 내가 담당하고 있는 서비스에서 사용 중인 sleuth 의존성 때문에 TraceLoadBalancerFeignClient(LoadBalancerFeignClient의 하위 클래스)가 호출돼서 내부에서 LazyTracingFeignClient로 위임, 마지막으로 OkHttpClient로 위임하는 구조를 가지고 있었다.

참고로 yml에서 feign.okhttp.enabled = true를 제거하면 아래와 같이 feign에서 제공하는 Default Client가 사용되는 것을 확인했다. 

그런데, 코드를 보다 보니 동일한 설정 값을 가진 okhttp3.OkHttpClient 하나를 가지고 각 시스템 별로 만들어진 Feign Client에서 모두 사용하고 있었다.

 

[OkHttpFeignConfiguration 클래스]

정말 그런지, 코드를 분석해 보니 위에서 만든 okhttp3.OkHttpClient 하나를 가지고 OkHttpClient를 만들어서

 

[OkHttpClient 클래스]

시스템 별로 Feign Client가 만들어질 때마다 Feign.Builder를 통해 Client를 설정해주고 있었다.

 

[FeignClientFactoryBean 클래스]

그런데, 여기서 궁금한 점이 하나 있었다.

내가 담당하고 있는 서비스는 시스템 별로 readTimeout을 달리 설정해주고 있고, 이것이 정상적으로 잘 동작하는지도 확인을 했는데 이건 어떻게 되는 걸까?

feign:
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 5000
        loggerLevel: BASIC
      other-client:
        connectTimeout: 2000
        readTimeout: 10000 
        loggerLevel: BASIC

 

사실, 이 부분이 코드를 분석하며 가장 신기하다고 생각한 포인트였다.
Feign은 매 요청 scope마다 우리가 yml에서 설정한 connectTimeout 및 readTimeout 값과 okhttp3.OkHttpClient에 설정된 값이 다른지를 판단하며 다른 경우 우리가 설정한 값을 가지고 okhttp3.OkHttpClient를 새로 생성해서(나머지 값은 copy) 호출하는 구조였다.

이로 인해, 시스템 별로 readTimeout 설정이 가능한 것이었다.

 

[OkHttpClient 클래스]