[Spring In Action5] 마이크로서비스

강동준·2022년 4월 6일
0

SpringInAction5

목록 보기
4/5

마이크로 서비스 이해하기


일반적인 단일 애플리케이션

기존의 애플리케이션을 개발을 하면 여러개의 모듈로 나누어진다고 하더라도 하나의 JAR나 WAR로 생성되어왔습니다. 하지만 이 방법은 작은 규모의 애플리케이션을 개발을 할 때는 좋은 방법이지만 코드가 추가될수록 주체하기 어렵고 복잡한 애플리케이션이 될 가능성이 높습니다.

마이크로 서비스 아키텍처

마이크로 서비스 아키텍처는 이러한 단일 애플리케이션의 단점을 보완하기 위해서 발전해온 아키텍처로 개별적으로 개발되고 배포되는 소규모의 작은 애플리케이션들로 하나의 애플리케이션을 구성시키는 방법입니다.

  • 각 마이크로 서비스는 다른 마이크로 서비스와 라이브러리를 공유하지 않으므로 호환성 문제가 생기지 않는다.
  • 마이크로 서비스마다 프로그래밍 언어나 프레임워크, 라이브러리를 다르게 선택할 수 있다.
  • 단일 애플리케이션과 비교하여 크기가 작으므로 테스트에 용이하다.
  • 기능에 따른 분리로 각 컴포넌트의 기능에 대해 정의를 하기 쉽다.

절대적으로 마이크로 서비스가 좋은가?

이렇게만 본다면 마이크로 서비스 아키텍처가 절대적으로 좋아보일 수 있습니다. 하지만 마이크로 서비스 아키텍처는 서버 분산 아키텍처로 네트워크 지연과 같은 문제가 발생할 수 있어서 원격 호출이 많아질 수록 애플리케이션의 실행이 더 느려질 수 있다는 점을 고려해야 합니다.



마이크로 서비스 구성


마이크로 서비스를 위해 필요한 부속 프로젝트

스프링 클라우드 넷플릭스 유레카

유레카를 사용하게 되면 정적으로 개발자가 직접 서비스 레지스토리에 각 마이크로서비스의 인스턴스를 등록하는 것이 아니라 서비스 인스턴스가 시작할 때 각 서비스가 자신의 이름을 유레카 서버에 등록을 하게됩니다. 그리고 유레카 서버는 각 마이크로 서비스와 30초 간격으로 핑을 주고 받으며 인스턴스가 가용할 수 있는 상태인지 확인을 하고 세 번의 갱신(혹은 90초)동안 확인을 받지 못하면 등록을 취소하게 됩니다.

이렇게 서비스가 중단 되어진 서비스의 수가 특정한 수에 다다르면 유레카 서버는 네트워크의 문제가 생긴 것으로 간주하고 레지스트리에 등록된 나머지 서비스 데이터를 보존하기 위해 자체 보존 모드로 들어가게 됩니다.

때문에 실제 배포 환경에서는 자체 보존 모드를 true로 설정을 하고 서비스 인스턴스의 상태가 자주 변경될 수 있는 개발 환경에서는 중단된 서비스의 등록이 계속 유지될 수 있으므로 false로 하는 것이 좋습니다.

유레카 서버 생성

유레카 서버 사용을 위한 의존성 추가

<dependency>
	<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka</artifactId>
</dependency>

유레카 서버의 부트 스트랩 클래스에 @EnableEurekaServer 어노테이션 추가

@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication{
	public static void main(String[] args){
    	StringApplication.run(ServiceRegistryApplication.class, args);
    }
}

유레카 서버 속성 구성

eureka:
   instance:
      hostname: service-registry // 유레카 서버 이름
server:
   port: 8776 // 특정 포트 사용

// 유레카 서버의 URL
eureka:
   client:
      service-url:
         defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      fetchRegistry: false	// 다른 유레카 서버와 통신을 할지 결정
      registerWithEureka : false
   server:
      enableSelfPreservation : false // 자체 보존 모드 끄기

서비스 사용하기

유레카 서비스 등록

유레카 클라이언트 스타터 의존성 추가

<dependency>
	<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artfifactId>
</dependency>

유레카 클라이언트 속성 구성

spring:
   application:
      name: ingredient-service

server:
   port: 0	// 0으로 할시 랜덤으로 포트를 선택

// 서비스를 등록할 유레카 서버
eureka:
   client:
      service-url:
         defaultZone: htt://localhost:8776/eureka

유레카 서버에서 찾은 서비스를 선택 및 사용하는 방법


로드 밸런싱된 RestTemplate

// 로드 밸런싱 된 RestTemplate 빈 선언
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
	return new RestTemplate();
}

.
.
.
@Component
public class IngredientServiceClient{
	private RestTemplate rest;
    
    public IngredientService(RestTemplate rest){
    	this.rest = rest;
    }
    
    // 내부적으로 ingredient-service라는 서비스의 이름을 찾아 인스턴스를 선택하도록
    // RestTemplate이 리본에 요청
    public Ingredient getIngredientById(String ingredientId){
    	return rest.getForObject("http://ingredient-service/ingredients/{id}",
        						Ingredient.class, ingredientId);
    }
}

Feign에서 생성된 클라이언트 인터페이스

Feign은 REST 클라이언트 라이브러리이며, 스프링 데이터 JPA를 사용할 때 인터페이스만 지정하여 쿼리 실행 구현체를 자동으로 만들어주는 것과 유사합니다.

간단한 사용방법은 다음과 같습니다.

의존성 추가

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

구성 클래스들 중 하나에 @EnableFeignClient 어노테이션 등록

@Configuration
@EnableFeignClient
public class RestClientConfiguration{
}

리포지터리 인터페이스 정의

// 호출되는 마이크로 서비스의 이름 지정
@FeignClient("ingredient-service")
public interface IngredientClient{

	// 마이크로 서비스에 대한 요청
	@GetMapping("/ingredients/{id}")
	Ingredient getIngredientDetail(@PathVariable("id) String id);
}

컨트롤러단에서 사용

@RestController
@RequestMapping("/ingredients")
public class IngredientController{

	private IngredientClient client;
    
    @Autowired
    public IngredientController(IngredientClient client){
    	this.client = client;
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Ingredient> inredientDatail(@PathVariable("id") String id){
    	
    	Ingredient ingredientDetail = client.getIngredientDetail(id);
        
        return ...
        
    }
}

MSA(마이크로 서비스 아키텍처 관련) 참조 링크
Spring Cloud Eureka 관련 참조 링크

profile
성장을 멈추지 않는 백엔드개발자입니다.

0개의 댓글