[ Spring Docs ] Spring Cloud OpenFeign
[ Blog ] OpenFeign 이란?
[우아한 기술블로그 ] 우아한 Feign 적용기

의존성 추가
ext { springCloudVersion = "2021.0.5" } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' }
- springCloudVersion 참고 링크
사용방법
@FeignClient(value = "${feign.name}", url = "${feign.url}") public interface GameServerApiClient { @PostMapping("/rooms") RoomCreateResponse createRoom(URI baseUrl, @RequestBody RoomCreateRequest request); @GetMapping("/api") String apiCall(); @PostMapping("/create") EC2ClientResponse createEC2Instance(@RequestHeader("x-api-key") String apiKey, @RequestBody EC2ClientRequest request); // 위와 같은 방식으로 RequestHeader 추가 가능 } public class GameServerService { private final GameServerApiClient client; public boolean createRoom(URI baseUrl, String roomName, Integer accountUID) { try { RoomCreateResponse room = client.createRoom(baseUrl, new RoomCreateRequest(roomName, accountUID)); return String.valueOf(room.code()).startsWith("2"); } catch (RetryableException exception) { log.warn("GameServer API Call Failed : {}", exception.getMessage()); return false; } } }
- URI를 가장 첫번째 파라미터로 넣음으로써, URL 자체도 동적으로 설정이 가능함p
Logging 활성화
[Spring Docs ] Feign Logging
@Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
# application.yaml # 클래스 fullpath: DEBUG logging.level.project.user.UserClient: DEBUG
MultiThread에서 사용하기
- feign은 기본적으로 JDK의 native
URLConnection
을 이용하여 HTTP request를 보냅니다.
- 따라서 기본 설정으로는 별도의 Connection pool을 설정할수 없는데, Connection pool을 설정하기위해서는 apache HTTPClient, OKHttp로 feign의 client 바꾸어 사용하여야 합니다.
에러 처리하기
[ Github ] Openfeign Error Handling
static class MyErrorDecoder implements ErrorDecoder { private final ErrorDecoder defaultErrorDecoder = new Default(); @Override public Exception decode(String methodKey, Response response) { // wrapper 401 to RetryableException in order to retry if (response.status() == 401) { return new RetryableException(response.status(), response.reason(), response.request().httpMethod(), null, response.request()); } return defaultErrorDecoder.decode(methodKey, response); } }
- ErrorDecoder를 구현하는 클래스를 선언하여 에러 response가 왔을때 로직 커스터마이징 할 수 있음
- RetryableException은 response 자체를 못받기 때문에 ErrorDecoder로 로직 커스터마이징이 어려움