IT/Spring Cloud

Microservice간 통신 - FeignClient 방식

김 정 환 2022. 1. 7. 13:42
반응형

앞으로 구현할  Microservice간 통신의 개요입니다.

 

RestTemplate보다 더 직관적입니다. 호출하려는 HTTP endpoint에 대한 Interface를 생성하면 됩니다.

 

 

요약

Feign Dependency 추가
client 패키지를 만들어서 Feign Client Interface 생성
호출하는 서비스에 Interface 구현
error 패키지를 만들어서 FeignErrorDecoder 클래스 생성

 

소스코드

Dependency를 추가합니다.

        <!-- Feign Client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

 

Feign Client Interface를 생성합니다.

client 패키지를 만들고, OrderServiceClient.java 인터페이스를 만듭니다.

GetMapping에 맵핑할 url은 order service의 endpoint url 입니다.

@FeignClient(name = "order-service") // application name
public interface OrderServiceClient {

    @GetMapping("/order-service/{userId}/orders") // 호출하고 싶은 마이크로서비스의 url 그대로 붙여넣기
    List<ResponseOrder> getOrders(@PathVariable("userId") String userId);
    // 위 데이터 형식이 order-service에서의 ResponseEntity<List<ResponseOrder>> 과 다른 이유?
    // ResponseEntity는 HTTP 응답에 대한 전체 내용을 가짐. status code, header, body
    // ResponseEntity로 감싸지 않는다면, body만 전달.
    // 그래서 body 부분인 List<ResponseOrder> 만 사용


}

 

order service에서 데이터를 가져와야 하는 부분에 Feign Client Interface를 구현합니다.

UserServuceImpl.java

@Service
public class UserServiceImpl implements UserService{

    UserRepository userRepository;
    BCryptPasswordEncoder passwordEncoder;

    // Feign
    OrderServiceClient orderServiceClient;

    @Autowired
    public UserServiceImpl(UserRepository userRepository,
                           BCryptPasswordEncoder passwordEncoder,
                           OrderServiceClient orderServiceClient) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.orderServiceClient = orderServiceClient;
    }

// 중략 //

    @Override
    public UserDto getUserByUserId(String userId) {
        UserEntity userEntity = userRepository.findByUserId(userId);

        // 조회할 유저가 없을 경우
        if(userEntity == null){
            throw new UsernameNotFoundException("User Not Found");
        }

        UserDto userDto = new ModelMapper().map(userEntity, UserDto.class);

        /* Using a Feign Client + ErrorDecoder */
        List<ResponseOrder> ordersList = orderServiceClient.getOrders(userId);

        userDto.setOrders(ordersList);

        return userDto;
    }

}

 

예외 처리를 하겠습니다.

A 서비스에서 B 서비스를 부를 때, B에서 찾고자 하는 엔드포인트가 없을 수도 있습니다.

error 패키지를 만들고, FeignErrorDecoder.java를 만들겠습니다.

@Component // 주입받기 위해서 component 등록
public class FeignErrorDecoder implements ErrorDecoder {

    Environment env;

    @Autowired
    public FeignErrorDecoder(Environment env) {
        this.env = env;
    }

    @Override
    public Exception decode(String s, Response response) {
        switch(response.status()){
            case 400:
                break;
            case 404:
                if(s.contains("getOrders")){
                    return new ResponseStatusException(HttpStatus.valueOf(response.status()),
                            env.getProperty("order_service.exception.order_is_empty"));
                }
                break;
            default:
                return new Exception(response.reason());
        }
        return null;
    }
}

 

 

Postman으로 확인합니다.

1. 회원가입

2. 로그인

3. 주문

4. 주문 확인

 

 

끝.

반응형

'IT > Spring Cloud' 카테고리의 다른 글

Apache Kafka 활용 (1)  (0) 2022.01.23
데이터 동기화 - Kafka 설정  (0) 2022.01.08
Microservice간 통신 - RestTemplate 방식  (0) 2022.01.06
비대칭키 암호화  (0) 2022.01.05
대칭키 암호화  (0) 2022.01.05