본문으로 바로가기

스프링 마이크로서비스 코딩 공작소

category Backend/Spring 2020. 8. 19. 23:48
    반응형

    마이크로서비스 개념

    대형 모놀리식 어플리케이션과 반대되는 개념으로 느슨히 결합된 작은 분산 서비스이다. 애플리케이션 기능을 분해하고 분리해서 완전히 상호 독립적이어야 한다는 것이다.

    • 애플리케이션 로직을 각자 책임이 명확한 작은 컴포넌트들로 분해하고 이들을 조합해서 솔루션을 제공한다.
    • 각 컴포넌트는 작은 책임 영역을 담당하고 완전히 상호 독립적으로 배포된다.
    • 마이크로서비스는 몇 가지 기본 원칙에 기반을 두며 소비자와 서비스 제공자 사이의 데이터 교환을 위해 HTTP와 JSON 같은 경량 통신 프로토콜을 사용한다.

    마이크로서비스는 작기 때문에 클라우드에서 많은 서비스 인스턴스를 쉽게 시작할 수 있으므로 애플리케이션 확장성을 높일 수 있다.

    스프링

    스프링프레임워크의 핵심은 DI를 통한 의존성 주입이다. 기존의 자바 어플리케이션의 경우 하드코딩으로 객체간 강한결합이 발생하는데 이를 해결하기 위해 의존성 주입을 사용했다.

    스프링부트

    스프링부트는 스프링프레임워크를 경량화하여 재구성한 것이다. 스프링의 핵심 기능을 수용하고 많은 인터프라이즈 기능을 제거하였다. 그 대신 자바 기반의 REST 지향 마이크로서비스 프레임워크를 제공한다.

    REST의 핵심 개념은 HTTP 동사(GET, POST, PUT, DELETE)를 수용해 서비스의 핵심 동작을 표현해야하고, 서비스에 데이터를 요청하고 수신하기 위해 JSON처럼 경량의 웹 기반 데이터 직렬화 프로토콜을 사용하는 것이다.

    개발환경

    자바는 메이븐 프로젝트를 기반으로 생성하며 도커를 사용하여 이미지를 생성한다. 깃을 통해서 형상관리를 진행한다. 각 프로그램의 버전은 이 책의 예제코드 환경이니 맞춰서 설치한다.

    1. 아파치 메이븐 3.5.4 (http://maven.apache.org)
      • 알집 파일 다운로드 후 시스템 변수에 등록하여 사용한다.

    maven 실행화면

    1. 도커 1.8x (http://docker.io)

    도커 설치화면

    1. 깃 클라이언트 (http://git-scm.com)

    프로젝트 소스

    https://github.com/klimtever

    1. 프로젝트 빌드

      mvn clean package docker:build

      빌드를 하다보면 DockerFile에서 에러가 발생한다. 로그를 분석하여 구글링 하면 주로 다운로드하는 파일에 URL 변경이면 문제를 해결할 수 있다.

    1. 프로젝트 구조

      • maven 프로젝트는 pom.xml을 기반으로 빌드를 한다.
      • 메이픈 플러그인 스포티파이를 통해서 도커 이미지를 빌드할 수 있다.
      • DockerFile은 도커 명령어를 사용하여 도커 이미지 생성한다.
        • 이미지로부터 어떤 명령들을 실행할지 DockerFile에 정의한다.
        • 도커 생성시 서비스에 필요한 Jar 파일을 도커 이미지에 복사한다.
        • Jar는 주로 스프링부트에서 빌드된 파일이다.
      • 프로저비닝이란 이미지를 도커에 적재하여 실행함을 의미한다.
      • 프로젝트를 이미지로 만들고 도커 컴포즈를 사용해서 그룹으로 묶어 실행한다.
    2. 도커 컴포즈
      도커 컴포즈는 서비스를 그룹으로 정의한 후 하나의 단위로 실행하게 하는 서비스 오케스트레이션 도구다.
      docker-compose.yml에 파일에는 이미지, 포트, 환경변수등을 설정할 수 있다.

        version: '2'
        services:
          eurekaserver:
           image:   johncarnell/tmx-eurekasvr:chapter8 #도커컴포즈는 로컬에서 이미지를 찾아서 로드한다.
           ports:
               - "8761:8761" #포트번호
          configserver:
            image: johncarnell/tmx-confsvr:chapter8
            ports:
               - "8888:8888"
            environment: #환경변수
               EUREKASERVER_URI: "http://eurekaserver:8761/eureka/"
               EUREKASERVER_PORT: "8761"
               ENCRYPT_KEY:       "IMSYMMETRIC"
          zuulserver:
            image: johncarnell/tmx-zuulsvr:chapter8
            ports:
              - "5555:5555"
            environment:
              PROFILE: "default"
              SERVER_PORT: "5555"
              CONFIGSERVER_URI: "http://configserver:8888"
              EUREKASERVER_URI: "http://eurekaserver:8761/eureka/"
              DATABASESERVER_PORT: "5432"
              EUREKASERVER_PORT:   "8761"
              CONFIGSERVER_PORT:   "8888"
          database:
            image: postgres:9.5 #데이터베이스 설치
            ports:
              - "5432:5432"
            environment:
              - POSTGRES_USER=postgres
              - POSTGRES_PASSWORD=p0stgr@s
              - POSTGRES_DB=eagle_eye_local
      
         ...
      
      • 도커 컴포즈로 서비스 시작, 중지

         docker-compose -f docker/common/docker-compose.yml up 
         docker-compose -f docker/common/docker-compose.yml down

        도커 기본 명령어

    #컨테이너 목록
    docker ps 
    #컨테이너 중지
    docker stop [ID 또는 이미지 이름]
    #이미지 목록 출력
    docker images 
    #이미지를 삭제한다
    docker rim [ID 또는 이미지 이름] 
    #실행중인 컨테이너 접속
    docker exec -ti [ID] /bin/sh

    스프링 부트 마이크로서비스의 흐름

    간단하게보면 HTTP의 요청을 받아 비지니스로직에서 처리하고 객체를 JSON로 변환해서 응답을 한다.

    Hello World

    package com.thoughtmechanix.simpleservice;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.PathVariable;
    
    @SpringBootApplication //스프링부트 서비스 진입점
    @RestController // RestController 지정
    @RequestMapping(value="hello") // /hello 로 시작하는 URL
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @RequestMapping(value="/{firstName}/{lastName}",method = RequestMethod.GET) //HTTP 전송 방식 및 URL 변수 지정
        public String hello( @PathVariable("firstName") String firstName, // 변수맵핑
                             @PathVariable("lastName") String lastName) {
    
            return String.format("{\"message\":\"Hello %s %s\"}", firstName, lastName);
        }
    }

    포스맨을 사용하여 HTTP GET방식으로 호출을 해본다.

    마이크로서비스 핵심 키워드

    작고 단순하며 분리된 서비스 = 확장 가능하고 회복적이며 유연한 애플리케이션

    클라우드란?

    IaaS(Infrastructure as a Service)
    PaaS(Platform as a Sevice)
    SaaS(Software as a Service)
    FaaS(Function as a Service)
    CaaS(Container as a Service) -FaaS, CaaS 는 서버리스로 배포된다.

    공급자가 어느 구간까지 제공하느냐에 따라서 위와 같이 분류된다.

    왜 클라우드와 마이크로서비스 인가?

    각 서비스를 독립된 개별 산출물로 패키징하고 배포한다는 것이다. 서비스 인스턴스를 신속하게 시작할 수 있고 서비스 인스턴스는 서로 차이가 없어야 한다.

    클라우드에 기반을 둔 마이크로서비스의 장점은 탄력성 개념을 중심으로 한다. 빠르게 가상 머신과 컨테이너를 가동 시킬 수 있다. 클라우드 공급자를 사용해 마이크로서비스를 배포하면 애플리케이션을 위해 훨씬 더 높은 수준의 수평 확장성을 얻을 수 있다. 서버 탄력성은 애플리케이션이 회복력이 높다는 것을 의미한다.

    마이크로서비스 구성 시 고려해야할 것들

    마이크로 서비스는 비지니스 로직 외에 고려해야할 것들이 많다. 적정크기, 위치 투명성, 회복성, 반복성, 확장성이다. 탄력성 높은 서비스를 제공하기 위해서는 앞에 제시된 것들이 보장되야한다.

    마이크로서비스 라우팅 패턴

    단일 진입점을 통해서 모든 서비스 호출에 대한 일관된 보안과 콘텐츠 정책을 보장할 수 있다.

    1. 서비스 디스커버리
      클라이언트에서 서비스의 물리적 위치를 추상화한다.
      확장하기 위해 새 마이크로서비스 인스턴스가 추가되고 비정상 서비스 인스턴스는 투명하게 서비스에서 제거된다.
    2. 서비스 라우팅
      마이크로서비스 클라이언트에 인가 및 인증, 콘텐츠 검사 등 정책 시행 지점으로 사용되고 연결되는 논리적 단일 URL을 제공한다.

    마이크로서비스 회복성 패턴

    반응형