Study/ETC

์ง‘๋…์˜ feign.httpclient ๊ด€๋ จ ์‚ฝ์งˆ๐Ÿ˜ฅ ๊ธฐ๋ก๊ธฐ

YURI๐Ÿ•๐Ÿ“๐Ÿถ 2024. 2. 11. 23:39
๋ฐ˜์‘ํ˜•

feign

  • Feign์€ ์˜คํ”ˆ์†Œ์Šค ์›น ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. (like RestTemlate..)
    • HTTP ํ†ต์‹ ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๋‹ค๋ฅธ Feign์˜ ์žฅ์ ์€ api ํ˜ธ์ถœ ์„ค์ •์„ ๊ฐ„์†Œํ™”ํ•˜์—ฌ interface ์„ ์–ธ๋งŒ์œผ๋กœ API ํ˜ธ์ถœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์„ ์–ธ์  ์›น ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ)
  • Feign์€ Netflix๊ฐ€ ์ฒ˜์Œ ๋งŒ๋“ค์—ˆ์ง€๋งŒ, ์ดํ›„ Netflix๊ฐ€ feign์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ฒŒ ๋˜๋ฉด์„œ ํ˜„์žฌ๋Š” OpenFeign์œผ๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ฌธ์ œ์˜ ์‹œ์ž‘

  • ํ™˜๊ฒฝ : spring-cloud-openfeign 2.2.9
  • Spring Boot ํ™˜๊ฒฝ์—์„œ application.yml ํŒŒ์ผ์— feign ๊ด€๋ จ ์„ค์ •์„ ์ž‘์„ฑํ•ด feign์˜ ์„ค์ •๊ฐ’๋“ค์„ ์„ธํŒ…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๋„ ์žˆ์Œ)
  • ํ˜„์žฌ ์žฌ์ง์ค‘์ธ ํšŒ์‚ฌ ๊ฐ€์ด๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ feign ๊ด€๋ จ ์„ค์ •์„ ํ•˜๋˜์ค‘, ๊ถ๊ธˆ์ฆ์ด ์ƒ๊ฒจ๋‚ฌ์Šต๋‹ˆ๋‹ค.
  • feign: client: config: default: connectTimeout: 5000 readTimeout: 15000 loggerLevel: FULL httpclient: connection-timeout: 5000 # feign.client.config.default.connectTimeout๊ณผ feign.httpclient.connection-timeout์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ...
  • feign.client.config.default.connectTimeout๊ณผ feign.httpclient.connection-timeout์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ...
  • ๊ตฌ๊ธ€๋ง์„ ํ•ด๋ณด์•˜์ง€๋งŒ ๋ช…ํ™•ํžˆ ๋‹ค๋ฅธ ์ ์„ ์„ค๋ช…ํ•œ ๊ธ€์€ ์ฐพ์•„๋ณผ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค ใ… 

 

feign.httpclient

https://docs.spring.io/spring-cloud-openfeign/docs/2.2.9.RELEASE/reference/html/#spring-cloud-feign-overriding-defaults

The OkHttpClient and ApacheHttpClient and ApacheHC5 feign clients can be used by setting 
`feign.okhttp.enabled` 
or `feign.httpclient.enabled`
or `feign.httpclient.hc5.enabled` to `true`, 
respectively, and having them on the classpath.

OkHttpClient ๋ฐ ApacheHttpClient ๋ฐ ApacheHC5 feign ํด๋ผ์ด์–ธํŠธ๋Š” ๊ฐ๊ฐ feign.okhttp.enabled ๋˜๋Š” feign.httpclient.enabled ๋˜๋Š” feign.httpclient.hc5.enabled๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ณ  ํด๋ž˜์Šค ํŒจ์Šค์— ์žˆ์œผ๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • spring-cloud-openfeign ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด, httpclient → ApacheHttpClient ๊ด€๋ จ ์†์„ฑ์ด๋ผ๊ณ  ์ถ”์ธกํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

https://techblog.woowahan.com/2657/

  • ๊ทธ๋ฆฌ๊ณ  apache http client๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด feign.httpclient.enabled ์ฒ˜๋ฆฌ๋ž‘ ์˜์กด์„ฑ ์ถ”๊ฐ€๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ๋„ ๊ฐ™์ด ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
    • ์ฐธ๊ณ  : feign๊ฐ€ ์ง€์›ํ•˜๋Š” http client๋Š” default, apache http client, ok http client ๋“ฑ์ด ์žˆ์Œ.

 

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ!

feign:
client:
  config:
    default:
      connectTimeout: 5000
      readTimeout: 15000
      loggerLevel: FULL
httpclient:
  connection-timeout: 5000 # feign.client.config.default.connectTimeout๊ณผ feign.httpclient.connection-timeout์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ...
  • ์•„๊นŒ ์ฐธ๊ณ ํ–ˆ๋‹ค๋˜, ํšŒ์‚ฌ ๊ฐ€์ด๋“œ์—๋Š” enabled ์„ค์ •์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ์™€ ์˜์กด์„ฑ ์ถ”๊ฐ€์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋„ ์ฐพ์•„ ๋ณผ ์ˆ˜ ์—†์—ˆ๋Š”๋ฐ์š”! ๊ทธ๋ž˜์„œ ์ €๋Š” ๋‹ค์‹œ ํ˜ผ๋ž€์— ๋น ์ง€๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค...
  • ๊ณผ์—ฐ.. ์–ด๋–ค ๊ธ€์ด ๋งž๋Š”๊ฒƒ์ธ๊ฐ€...
  • ๊ทธ๋ž˜์„œ ์ง์ ‘ ์†Œ์Šค๋ฅผ ๊นŒ๋ณด๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค!
    • ์ด์œ  : ํ˜„์žฌ ์ œ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” feign ๋ฒ„์ „์ด ๋‚ฎ์€ ๋ฒ„์ „์ด๋ผ.. ์ตœ์‹  ๋ฒ„์ „๊ณผ์˜ ์„ค์ • ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๊ตฌ๊ธ€๋งํ•œ ํŽ˜์ด์ง€๋“ค์„ ๋ฏฟ์ง€ ๋ชปํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค ใ… ใ…  (feign์ด ๋ฒ„์ „์—…์ด ๋˜๋ฉด์„œ ๋ฐ”๋€ ๋ถ€๋ถ„์ด ์€๊ทผ ๋งŽ๋”๋ผ๊ตฌ์š” ๐Ÿคฃ)

 

FeignAutoConfiguration.java

  • ์ˆ˜๋งŽ์€ ๋””๋ฒ„๊น…๊ณผ ๊ตฌ๊ธ€๋ง์„ ํ†ตํ•ด feign์ด client ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ๋ฐ”๋กœ ๊ทธ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค!
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({ApacheHttpClient.class})
    @ConditionalOnMissingClass({"com.netflix.loadbalancer.ILoadBalancer"})
    @ConditionalOnMissingBean({org.apache.http.impl.client.CloseableHttpClient.class})
    @ConditionalOnProperty(
        value = {"feign.httpclient.enabled"},
        matchIfMissing = true
    )
    @Conditional({HttpClient5DisabledConditions.class})
    protected static class HttpClientFeignConfiguration {

        protected HttpClientFeignConfiguration() {
        }

        // ์ƒ๋žต

        @Bean
        @ConditionalOnMissingBean({Client.class})
        public Client feignClient(HttpClient httpClient) {
            return new ApacheHttpClient(httpClient); // ApacheHttpClient๋กœ Client ๊ฐ์ฒด ์ƒ์„ฑ!
         }

    }
  • @ConditionalOnClass({ApacheHttpClient.class}): ApacheHttpClient ํด๋ž˜์Šค ํŒŒ์ผ์ด ์žˆ์„๋•Œ๋งŒ ์„ค์ • ํŒŒ์ผ ์ž‘๋™
  • @ConditionalOnProperty( value = {"feign.httpclient.enabled"}, matchIfMissing = true ) : ๊ฐ’์ด false๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์ œ์™ธํ•˜๊ณ  ๋ชจ๋“  ๊ฒฝ์šฐ์— @Configuration ์„ค์ •ํŒŒ์ผ ์ ์šฉ๋จ (feign.httpclient.enabled ์„ค์ • ๊ฐ’ ์—†์–ด๋„ ๋จ)
  • @ConditionalOnMissingBean({Client.class}) : Client ํƒ€์ž…์˜ ๋นˆ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋นˆ ์ƒ์„ฑ
  • ๋น ๋ฅธ ๊ฒฐ๋ก  : ์ ์šฉํ•˜๋ ค๋ฉด, ApacheHttpClient ์˜์กด์„ฑ ์ถ”๊ฐ€๋งŒ ํ•˜๋ฉด ๋จ

 

์‹คํ—˜

๊ทธ๋ž˜๋„ ํ˜น์‹œ ๋ชฐ๋ผ์„œ ์‹คํ—˜์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜‚

1. ์˜์กด์„ฑ ์ถ”๊ฐ€
// pom.xml
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-httpclient</artifactId>
</dependency>

// application.yml
# ์•„๋ฌด์„ค์ •๋„ ํ•˜์ง€ ์•Š์Œ 
  • ๊ฒฐ๊ณผ : ApacheHttpClient๋กœ Client ์ƒ์„ฑ ๋จ
2. ์˜์กด์„ฑ ์ถ”๊ฐ€ && feign.httpclient.enabled=false
// pom.xml
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-httpclient</artifactId>
</dependency>

// application.yml
feign:
  httpclient:
    enabled: false
3. ์˜์กด์„ฑ ์ถ”๊ฐ€ && feign.httpclient.enabled=์•„๋ฌด๊ฐ’์ด๋‚˜
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-httpclient</artifactId>
</dependency>

// application.yml

feign:
  httpclient:
    enabled: true

--

<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-httpclient</artifactId>
</dependency>

// application.yml

feign:
  httpclient:
    enabled: 'hi'
  • ๊ฒฐ๊ณผ : ApacheHttpClient๋กœ Client ์ƒ์„ฑ ๋จ
4. ์˜์กด์„ฑ ์ถ”๊ฐ€ && feign.httpclient.enabled=off
// pom.xml
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-httpclient</artifactId>
</dependency>

// application.yml
feign:
  httpclient:
    enabled: off

 

๊ฒฐ๋ก 

    • feign์—์„œ http client๋กœ apache http client๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, ์˜์กด์„ฑ ์ถ”๊ฐ€๋งŒ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
      • feign.httpclient.enable=true ์ฒ˜๋ฆฌ๋Š” ์ƒ๋žตํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค
        • @ConditionalOnProperty( value = {"feign.httpclient.enabled"}, matchIfMissing = true )
        • feign.httpclient.enabled ๊ฐ’์„ false์œผ๋กœ ๋ช…์‹œํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ชจ๋“  ๊ฒฝ์šฐ์— client ๊ฐ์ฒด๊ฐ€ apache http client๋กœ ์ƒ์„ฑ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    • ๊ฐœ์ธ์ ์ธ ํšŒ๊ณ 
      • ์ด์ฒ˜๋Ÿผ ๊ธ€๋งˆ๋‹ค ์„ค๋ช…์ด ๋‹ค๋ฅด๋‹ค๋ฉด.. ํ˜ผ๋ž€์— ๋น ์ ธ ์ฐœ์ฐœํ•œ ๋งˆ์Œ๊ณผ ํ•จ๊ป˜ ์ฝ”๋“œ๋ฅผ ๋‹ค ๊นŒ๋ณด๊ฒŒ ๋˜๋Š”๋ฐ์š”..
      • ๊ธ€์—๋Š” ์ž‘์„ฑํ•˜์ง„ ์•Š์•˜์ง€๋งŒ.. ์ด๋ฒˆ ๊ฒฝ์šฐ์—๋Š” openfeign์˜ ์ฝ”๋“œ๊ฐ€ ๋ฏฟ๊ธฐ์ง€ ์•Š์•„, ๋” ํ˜ผ๋ž€ํ•œ ๋งˆ์Œ์œผ๋กœ openfeign์˜ ์ฝ”๋“œ๋ฅผ ๋กœ์ปฌ์— ๋ฐ›์•„ ์ง์ ‘ ๊นŒ๋ณด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. 
        • @ConditionalOnProperty( value = {"feign.httpclient.enabled"}, matchIfMissing = true )
          • ์ด ๋ถ€๋ถ„์—์„œ havingValue๊ฐ€ true๋กœ ์ ํ˜€์ ธ ์žˆ์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด ์™œ ์ด๋ ‡๊ฒŒ ๊ฐœ๋ฐœํ•˜๊ฒŒ ๋œ๊ฑด์ง€ ์ดํ•ด๊ฐ€ ์•ˆ๋์Šต๋‹ˆ๋‹ค.
        • ํ˜น์‹œ ์ œ๊ฐ€ ์ฐพ์•„๋ณด์ง€ ๋ชปํ•œ ์˜์—ญ์—์„œ feign.httpclient.enabled ๊ฐ’์„ ๋˜ ํ™•์ธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์˜์—ญ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์–ด open feign ๊ฐœ๋ฐœ ๋‹น์‹œ ์ปค๋ฐ‹ ๋‚ด์—ญ์„ ํ™•์ธํ•ด๋ณด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €์ฒ˜๋Ÿผ ๊ถ๊ธˆ์ฆํ•˜์‹  ๋ถ„๋“ค์ด ์žˆ์œผ์‹ค๊นŒ๋ด ์ฒจ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.
      • ์ด์ฒ˜๋Ÿผ ๊ณ„์† ์ฐœ์ฐœํ•œ ๋ถ€๋ถ„์ด ์žˆ์–ด, ์ •๋ง ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฐพ์•„๋ณด์•˜๋Š”๋ฐ์š”.. ๋‹ค๋ฅธ ๋ถ„๋“ค์€ ์ด๋Ÿฐ ํ˜ผ๋ž€์— ๋น ์ง€์ง€ ์•Š๊ธธ ๋ฐ”๋ผ๋ฉฐ ๊ธ€์„ ๋งˆ์นฉ๋‹ˆ๋‹ค!
๋ฐ˜์‘ํ˜•