Spring Cloud - Config Server

우선 Spring Cloud의 주요 컴포넌트를을 살펴보기 전에 12요소 어플리케이션에서 대해서 간단히 짚고 넘어가보자.


12 요소 어플리케이션 (Twelve-Factor App)

  • 클라우드 플랫폼이 어플리케이션 개발환경의 대세로 자리잡으면서 클라우드 플랫폼의 특징들을 잘 활용하도록 설계된 SaaS어플리케이션을 잘 만들기 위한 방법론을 의미한다.

  • 핵심사상

    • 선언적 형식을로 설정을 자동화해서 프로젝트에 새로 참여하는 동료가 적응하는데 필요한 시간과 비용을 최소화한다.

    • 운영체제에 구애받지 않는 투명한 계약을 통해 다양한 실행 환경에서 작동할 수 있도록 이식성을 극대화 한다.

    • 현대적인 클라우드 플랫폼 기반 개발을 통해 서버와 시스템 관리에 대한 부담을 줄인다.

    • 개발과 운영의 간극을 최소화해서 지속적 배포를 가능하게 하고 애자일성을 최대화 한다.

    • 도구, 아키텍처, 개발 관행을 크게 바꾸지 않도 서비스 규모의 수직적 확장이 가능하다.


Spring Cloud ?

Spring Cloud 는 위의 12요소 어플리케이션의 사상에 부합하는 Java 어플리케이션을 개발할 수 있도록 도와주는 광범위한 영역의 라이브러리들의 집합체이다.

그 중 Spring Cloud Netflix 를 구성하는 주요 컴포넌틀이다.

  1. 환경설정 외부화 담당 - 컨피그 서버

  2. 서비스 등록 및 탐색(discovery) - 유레카 서버

  3. 프록시 및 게이트웨이 역할 - 주울

  4. 마이크로서비스 자동등록 및 서비스 탐색의 구현

  5. 비동기 리액티브 마이크로 서비스 구성에 필요한 Spring Cloud Messaging


환경정보의 외부화, 컨피그 서버 - Config Server

일반적으로 Spring기반의 전통적인 웹어플리케이션을 개발할때 개발환경에 필요한 환경정보는 모두 프로젝트 소스내에 존재하는 application.properties 나 application.yml 파일로 관리한다.

소스와 정적 환경정보들의 분리차원에서 당연한 구조이겠으나, 현대의 어플리케이션들이 점덤 더 작은 단위의 어플리케이션으로 쪼개지면서 각 어플리케이션들의 환경설정을 담당하는 파일들도 서비스별로 분리되어 관리하기 더 어려워지게 되었다.


또한 예전보다 훨씬 더 어플리케이 환경의 변화주기가 빨라지는 상황에서 환경정보를 변경할 때마다 어플리케이션을 새로 빌드하고 배포해야 하는 구조는 분명 요즘의 클라우드 플랫폼기반의 개발환경에서는 한계가 존재한다.

스프링 클라우드의 컨피그 서버는 어플리케이션의 환경설정정보-특히 서비스,비즈니스 로직과 연관성이 있는 정보들-을 어플리케이션과 분리해 외부의 컨피그 서버를 통해 관리하도록 해준다.


  • 각 어플리케이션의 환경설정 정보는 git 또는 SVN에 저장된다.

  • 컨피그 서버는 git 서버에 접근해서 환경설정 정보를 읽어온다.

  • 각 컨피그 클라이언트 (마이크로 서비스)는 컨피그 서버에 접근해서 환경설정 정보를 읽어온다.

  • 컨피그 서버의 환경설정을 읽어오기 위한 정보는 bootstrap.properties가 담당한다.


컨피그 서버의 구성

컨피그 서버를 구성하기 위한 필수 의존성 라이브러리

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-config-server</artifactId>
</dependency>

스프링 엑추에이터는 필수 라이브러리는 아니지만 컨피그 서버 설정 후 Endpoing를 통한 컨피그 서버의 구성정보나 상태를 확인하기 위해서는 필요한 라이브러리이니 같이 추가하는게 좋다. 특히, 컨피그 서버를 바라보는 서비들은 환경설정의 변경상태를 재기동없이 읽어오기 위해서는 엑추에이터가 제공하는 Refresh Endpoint(/actuator/refresh)를 사용해야 하기 때문에 가급적 같이 추가하해서 사용하도록 하자.


스프링 클라우드 라이브러리는 기존 pom.xml에서 추가하는 경우라면, 스프링 클라우드 버전관리를 위한 아래의 설정정보도 같이 추가해야 한다.

<dependencyManagement>
  <dependencies>
     <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
     </dependency>
  </dependencies>

컨피그 서버도 상위개념인 Git서버를 참조해서 구동되어야 하기 때문에 bootstrap.properties파일이 필요하다.


컨피그 서버의 bootstrap.properties에 필수 설정값

server.port=8888
spring.cloud.config.server.git.uri=git서버위치

management.endpoint.env.enabled=true
management.endpoints.web.exposure.include=*

포트는 지정하지 않아도 디폴트로 8888로 지정된다. 스프링 액추에이터에서 제공하는 Endpoint를 모두 노출시켜 사용하길 원한다면 management.endpoints.web.exposure.include값을 *로 지정한다.


로컬에 Git을 구성할 경우, 아래의 의존성 라이브러리가 추가로 필요하다. 보통은 상용환경에서는 Github를 사용할 꺼라서 테스트에서만 사용하면 되는 라이브러리이다.

<dependency>
  <groupId>org.eclipse.jgit</groupId>
  <artifactId>org.eclipse.jgit</artifactId>
  <version>4.8.0.201706111038-r</version>
</dependency>

의존성 관리를 추가한 후, 정상확인하고 다시 제거하고 에러를 재현하려고 하였는데… 에러가 발생하지 않는다...


정확한 원인은 모르겠으나, 로컬에 구성한 Git 레파지토리에 스프링부트(컨피그 서버)가 최소에 접속할 때 필요한 라이브러리가 없어서 에러가 난게 아닐까 추측이 되고, 의존성 추가 후 정상 접속이 되고 어플리케이션도 정상 구동됨을 확인했다.


어플리케이션 환경설정 파일의 등록

컨피그 서버가 참조할 Git 레파지토리를 로컬에 구성하고, 테스트 목적으로 사용할 application.properties를 추가한다.

Git에 등록될 프로퍼티 파일은 디폴트 파일은 application.properties외에. 각 클라이언트 어플리케이션이 사용할 프로퍼티를 추가해서 사용하게 된다.

각 클라이언트 어플리케이션의 bootsrap.properties 프로퍼티 파일에서 지정한 spring.applicaton.name=서비스명의 서비스명으로 프로퍼티 파일을 만들게 된다.


아래와 같이 클라이언트 어플리케이션의 설정정보를 구성하였다면, Git 레파지토리에 등록할 해당 어플리케이션의 프로퍼티 파일명은 supplier-service.properties가 된다.

spring.application.name=supplier-service
spring.cloud.config.uril=http://localhost:8888


컨피그 서버의 구동

컨피그 서버, 즉 스프링 부트 어플리케이션을 구동하고 엑추에이터 Endpoint를 통해 컨피그 서버의 상태를 확인해 보자.

현재 컨피그 서버에 등록된 어플리케이션 환경설정 파일은 2개이다.

  • application.properties

  • supplier-service.properties


각 프로퍼티 정보에 접근하기 위한 URL 규칙이 있다.

http://localhost:8888/{서비스명}/{프로파일명}/{깃브랜치}


프로파일이 default이고 깃 브랜치가 master일 경우 둘 중 하나는 생략가능하다.

http://localhost:8888/supplier-service/default/master
http://localhost:8888/supplier-service/default
http://localhost:8888/supplier-service/master


즉, 이 세 개의 경로는 모두 동일하다.

접속하면 아래와 같이 프로퍼티의 설정정보를 json형태로 확인할 수 있다.

{
 "name": "supplier-service",
 "profiles": [
   "default"
],
 "label": null,
 "version": "a92fa477117546fae78d51e15ae0c3428b723fd1",
 "state": null,
 "propertySources": [
  {
     "name": "file:///Users/ykjang/Dev/Project/config-repo/supplier-service.properties",
     "source": {
       "supplier.name": "supplier2"
    }
  },
  {
     "name": "file:///Users/ykjang/Dev/Project/config-repo/application.properties",
     "source": {
       "message": "helloworld"
    }
  }
]
}

프로파일은 별로로 지정하지 않았기 때문에 default로 설정된다. 프로퍼티 파일을 위치와 이름, 소스내용들을 보여준다.


컨피그 클라이언트 구성

컨피그 클라이언트가 될 어플리케이션, 여기에서는 supplier-service 어플리케이션의 설정은 특별한 것 없다.

필요한 의존성 라이브러리 추가와 bootstrap.application파일의 설정이다.

필요 라이브러리

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>


application.properties 을 bootstrap.properties파일로 변경하고, 필요한 설정정보들을 컨피그 서버의 Git 레파지토리에 있는 supplier-service.properties파일로 옮긴다.

컨피그 서버 깃 레파지토리에 있는 supplier-service.properties파일내용

supplier.name=supplier


어플리케이션 (컨피그 클라이언트)의 bootstrap.properties파일내용

# 서비스명
spring.application.name=supplier-service
# 참조할 컨피그 서버 URL
spring.cloud.config.uri=http://localhost:8888

# 어플리케이션 구동 PORT
server.port=8090

management.endpoint.env.enabled=true
management.endpoints.web.exposure.include=*


컨피그 서버에 있는 supplier-service.properties파일을 잘 읽어 오는지 테스트를 하기 위해, 컨트롤러 클래스와 간단한 API 메서드를 생성한다.

@RefreshScope
@RestController
public class TestController {

   @Value ( "${supplier.name}" )
   private String SUPPLIER_NAME;

   @GetMapping("/supplier/name")
   public String getSupplyName() {
       return this.SUPPLIER_NAME;
  }
}

컨피그 서버의 깃 레파지토리에 있는 프로퍼티 파일의 속성값을 참조하도록 선언하고 메서드에서 해당값을 Return하도록 간단하게 구성하고 테스트를 해보자.

http://localhost:8090/supplier/name을 호출했을때, supplier라고 브라우저에 표시되면 정상적으로 컨피그 서버의 프로퍼티를 읽어온 것이다.

@RefrshScope 어노테이션에 대한 설명은 따로 포스팅을 하도록 하겠다.

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기