Spring Feign

풀어갈 나의 이야기·2021년 12월 4일
1

Spring Framework

목록 보기
2/4

Feign Client?

Document

개요

  • Feign Client 는 web Service 클라이언트를 보다 쉽게 작성할 수 있도록 도와주는 라이브러리

    • 선언적 방식
    • 인터페이스를 통해 클라이언트 측 프로그램 작성
    • Spring 이 런타임에 구현체를 제공
  • Feign 은 Netflix 에서 개발된 Http Client Binder 이며, 웹 서비스 클라이언트를 보다 쉽게 작성할 수 있는 장점이 있다.

    사실 장점이 와닿지 않아, WebClient 에 대해 조사해보고, RestTemplate 등을 좀 찾아본 결과 Feign 을 왜 써야하는지 알수 있게 되었다.
    Spring WebClient 사용법
    동일한 호출을 RestTemplate 로 예제를 만들어 볼때 코드복잡도가 확연히 줄어듬을 느낄 수 있음

  • Interface 를 작성하고 Annotaion 을 선언하기만 하면 된다.

    • Spring Data JPA 에서 실제 쿼리를 작성하지 않고, Interface 만 지정하여 쿼리 실행 구현체를 자동으로 만들어 주는것과 유사함
  • Interface 를 작성하고, 바로 사용하기 때문에 코드 복잡도가 낮아지고, 서비스간 통신을 원활하게 할 수 있음

How to Feign?

1. Example Architecture

2. Spring Project

  • 기본적인 Spring Boot 로 시작하고, Web , Lombok, OpenFeign 만 추가함
  • 구조는 다음과 같음

3. Dependency

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

4. Application.java

  • Annotaion 선언해서 그냥 사용하면 끝
    • root package 에 있어야 하고, 그렇지 않을 경우 basePackages 또는 basePackageClasses 를 지정해 주어야 한다.
    • @EnableFeignClients 은 지정된 package 를 돌아다니면서 @FeignClient 를 찾아 구현체를 만들어 준다.
package com.viewrain.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients      // Feign Client 를 사용할 거라고 선언만 하면됨 
@SpringBootApplication
public class FeignApplication {
	public static void main(String[] args) {
		SpringApplication.run(FeignApplication.class, args);
	}
}

5. Client

1) 인터페이스로 작성한다.@FeignClient 을 작성하면 인터페이스를 클래스로 구체화 시킬 필요가 없다. annotation이 작성해준다.
2) annotation을 통해 요청할 url을 넣어준다.
3) 메소드 위의 annotation을 통해 요청할 세부 URL을 설정한다.
4) default 설정을 override 하고 싶다면, configuration 에 설정된 값을 넣으면 된다. configuration = {FeignConfiguration.class}

package com.viewrain.demo.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "feign", url = "http://localhost:8080")
public interface TestClient {

	@GetMapping("/testfeign")
	String testFeign();
}

6. Service

  • Feign 클라이언트를 사용하는 Service 를 작성해준다.
package com.viewrain.demo.service;


import com.viewrain.demo.client.TestClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    @Autowired
	TestClient testClient;

    public String testFeign() {
        return testClient.testFeign();
    }
}

7. Controller

1) 메인 페이지로 접근
2) Feign Client가 /testfeign 으로 get 호출
3) 반환값 받고 메인에서 보여줌

package com.viewrain.demo.web;

import com.viewrain.demo.service.TestService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

  	// 1. 작성한 서비스를 가져오고
    private final TestService testService;

    // 2. 서비스를 사용하기 위한 생성자를 만들어줌
    public TestController(TestService testService) {
        this.testService = testService;
    }

    // 1) 메인 페이지로 접근
    // 2) Feign Client가 /testfeign 으로 get 호출
    // 3) 반환값 받고 메인에서 보여줌
    @GetMapping("/")
    public String main() {
        return testService.testFeign();
    }

    // Feign Client 요청에 응답을 주기 위한 컨트롤러
    @GetMapping("/testfeign")
    public String testFeign() {
        return "Root 로 호출하였으나, 바인딩 됩니다. (viewrain)";
    }
}

Use Feign Client

  • 스프링부트 프로젝트를 실행하고 http://localhost:8080/ (application.properties default값이 8080포트) 으로 접근하면 다음과 같이 결과값을 받을 수 있다.

Study

Header 에 값 설정하기

  • Request Header 에 값을 넣는 방식은 몇가지가 있다.
      1. Configuration 을 이용
      • Config 파일 생성후, Interface 에 @FeignClient(value = "step2", url = "https://httpbin.org", configuration = {HeaderConfiguration.class}) 로 설정해서 사용
public class HeaderConfiguration {
@Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> requestTemplate.header("header", "header1", "header2");
    }
}
    1. headers = "{ }" 로 선언
    1. Annotaion 선언
@GetMapping(value = "/status/{status}", headers = "key2=value2")
  void status2(@PathVariable("status") int status);
        
@GetMapping(value = "/status/{status}")
  void status3(@RequestHeader("key3") String headers, @PathVariable("status") int status);
        
  // 이 호출은 Header 에 값이 설정되지 않습니다.
  // @GetMapping 은 SpringMVcContract 를 사용해야하고, @Headers 는 feign Contract 를 사용해야 합니다.
  
@org.springframework.web.bind.annotation.GetMapping(value = "/status/{status}")
@feign.Headers("key3: value3")
  void status4(@PathVariable("status") int status);

Feign Log Level

loggerLevel : NONE, BASIC, HEADER, FULL을 지정할 수 있음

  • logging.level.com.example.demo.PostClient: debug 등의 debug logger 설정이 되어 있어야함
    • NONE : default, 로그를 남기지 않음
    • BASIC : Request Method, URL과 응답 코드, 실행 시간을 남김
    • HEADERS : BASIC의 정보를 포함하여, 요청, 응답의 헤더를 남김
    • FULL : 요청, 응답의 header, body, metadata를 남김

application.yml 설정

  • 기본적으로 yml 로 설정이 가능함
  • @FeignClient(configuration = FooConfiguration.class)와 application.yml이 같이 있을 시에는, yml 설정이 우선. 우선 순위를 변경하고 싶으면 feign.client.default-to-properties: false를 yml에 설정
feign:
  client:
    config: 
      feignName: # @FeignClient에서 name 값, 전역으로 설정하려면 default
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: full
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

@FeignClient

@FeignClient

  • name : 서비스ID 혹은 논리적인 이름, spring-cloud의 eureka, ribbon에 사용
  • url : 실제 호출할 서비스의 URL, eureka, ribbon을 사용하지 않고서도 동작
  • decode404 : 404응답이 올 때 FeignExeption을 발생시킬지, 아니면 응답을 decode할 지 여부
  • configuration : feign configuration class 지정
  • fallback : hystrix fallback class 지정
  • fallbackFactory : hystrix fallbak factory 지정

요청, 응답 압축

  • GZIP 을 통해 요청, 응답을 압축할 수 있음
feign:
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      request.min-request-size: 2048
    response.enabled: true

refference
https://spring.io/projects/spring-cloud-openfeign
https://woowabros.github.io/experience/2019/05/29/feign.html
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#_feign_logging
https://velog.io/@skyepodium/2019-10-06-1410-작성됨

profile
깨끗한 스케치북 일수록 우아한 그림이 그려지법, 읽기 쉽고, 짧은 코드가 더 아름다운 법.. 또한 프로그래머의 개발은 구현할 프로그래밍이 아닌, 풀어갈 이야기로 써내려가는것.

0개의 댓글