시뻘건 개발 도전기

클라우드 네이티브 배치 본문

Framework/spring

클라우드 네이티브 배치

시뻘건볼때기 2022. 9. 21. 09:32
반응형

서킷 브레이커: 배치 내에서 호출하는 rest api에 과부화가 걸렸을 때 사용

서킷 브레이커 패턴을 구현하여 스프링 배치는 [스프링 리트라이]라는 라이브러리에 의존한다
implementation group: 'org.springframework.retry', name: 'spring-retry', version: '1.3.3'
  1. 서킷 브레이커로 래핑할 메서드를 식별
  2. 식별된 매서드에서 발생한 예외 건수가 임계값을 초과하면
    서킷 브레이커가 해당 매서드에 대한 호출을 중지 및 대체 매서드로 트래픽을 라우팅
  3. 대체 매서드는 원래 메서드와 다른 처리방식
    ex. api가 반환하는 값 대신 기본 값을 반환
  4. 특정 알고리즘을 기반으로 다시 원래 메서드로 트래픽을 되돌려 다시 정상인 상태로 되돌아 왔는지 테스트
  5. 서킷 브레이커 재설정 및 트래픽은 원래 메서드가 호출되도록 정상 복원
public class EnrichmentProcessor implements ItemProcessor<Foo, Foo> {
    @Autowired
    private RestTemplate restTemplate;
    
    @Recover  // 재시도 가능한 메서드가 실패하거나 서킷 브레이커가 플립될 때 호출
              // 연관된 서킷 브레이커가 적용된 메서드와 동일한 메서드 시그니처(동일한 인자와 리턴 값?)를 가지고 있어야 한다.
    public Foo fallback(Foo foo) {
        // 서킷 브레이커를 통해 EnrichmentProcessor.process를 래핑하고
        // 대체 매서드 fallback을 통해 아이템의 message 필드를 "error"로 설정
        foo. sethessage(“error”);
        return foo;
    }
    
    @CircuitBreaker(maxAttempts = 1)	// 서킷 브레이커 래핑
    @0verride
    public Foo process(Foo foo) {
        ResponseEntity<String> responseEntity =
        this. restTemplate. exchange(
            "http: //localhost :8080/enrich",
            HttpMethod.GET,
            null,
            String.class);
            
        foo. setMessage(responseEntity.getBody());
        return foo;
    }
}
[그림 1] CircuitBreaker annotation properties
 

구성 외부화

스프링 부트 앱을 구현할 때 application.properties 혹은 application.yml을 사용했을텐데, 이는 구성이 jar 파일의 애플리케이션과 함께 번들로 제공되기 때문이다.

이는 환경이 변화할 때 쉽게 변경할 수 없고, public 저장소에 민감정보가 평문형태로 저장되어 있다면 문제가 될 수 있다.

이를 해결하기 위해 구성을 외부화할 필요가 있다.

1. spring cloud config server 사용

  • 앱 내 spring cloud config client를 사용해 구성을 가져온다.
  • 스프링 환경에 해당 값을 입력하고 모든 일반적인 프로퍼티를 주입
spring cloud config server 라이브러리 의존
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-config', version: '3.1.4'

client 사용 방법

  1. 의존성 추가
  2. application.yml 파일 내 spring cloud config server, client에 필요한 구성으로 변경
    1. 모든 것을 로컬환경에서 실행한다면 아래 두가지 프로퍼티만 구성
      1. spring.application.name : client가 server에 올바른 구성을 요청하기 위해 사용(=cloud-native-batch)
      2. spring.cloud.config.failFast: spring cloud config server에서 구성을 검색할 수 없는경우 client에게 예외 발생시켜 앱이 시작되지 않도록한다.

server 실행 방법

spring:
  profiles:
    active: git
  cloud:
    config:
      server:
        git:
          uri: file://Users/{user name}/.spring-cloud/config

configserver.yml를 사용해~/.spring-cloud/config 디렉토리에 git 저장소를 추가할 수 있다.

이전 application.yml파일을 해당 디렉토리에 복사하고 새로운 git 저장소에 git 명령어를 통해 커밋한다.

spring cloud CLI는 암호화를 적용한다. 보안이 필요한 값의 앞에 {cipher}라고 입력하기만하면 cloud-native-batch.yml이 생성된다.

spring:
  datasource:
    driverClassName: org.mariadb.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud_native_batch
    username: '{cipher}19775a12b552cd22e1530f745a7l0842c90d903e60f8a934b072c21454321de17'
    password: '{cipher}abcdefa44d2db148cd788507068ee770fa7b64c4d1980ef6ab86cdefabc118def'
    schema: schema-mysql.sql
  batch:
    initalizr:
      enabled: false
job:
  resource-path: s3://def-guide-sprirg-batch/inputs/*.csv
cloud:
  aws:
    credentials:
      accesskey: '{cipher}a7201398734bcd468f5efab785c2b6714042d62844e93f4a436bc4fd2e95fa4bcd26e8fab459c99807d2ef08a212018b'
      secretKey: '{cipher}40a1bc039598defa78b3129c87Bafa0d36e1ea55f4849c1c7b92e809416737de05dc45b7eafce3Bc2bc184811f514e2ta9ad5f0a8bb3e503282158b577d27937'
    region:
      static: us-east-1
      auto: false
spring cloun config server 실행: spring cloud configserver

 

2. 유레카 사용

implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka', version: '1.4.7.RELEASE'

rest api의 구성 내용은 application.yml이 아닌 bootstrap.yml파일을 사용한다.

  • application.yml은 applicationContext가 로드될 때 읽어들인다.
    스프링 클라우드는 applicationContext의 상위 컨텍스트인 BootStrapApplicationContext를 생성해 bootstrap.yml를 읽어들인다.
@EnableRetry
@EnableBatchProcessing
@EnableDiscoveryClient(autoRegister = false)  // 자동으로 유레카에 rest api가 등록
@SpringBootApplication
public class CloudNativeBatchApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudNativeBatchApplication.class, args);
    }
}
@Bean
@LoadBalanced // RestTamplate bean 정의
public RestTemplate restTemplate() {
    return new RestTemplate();
}​
public class EnrichmentProcessor implements ItemProcessor<Foo, Foo> {
    @Autowired
    private RestTemplate restTemplate;
    
    @Recover	// 대체 메서드
    public Foo fallback(Foo foo) {
        foo. sethessage(“error”);
        return foo;
    }
    
    @CircuitBreaker(maxAttempts = 1)	// 서킷 브레이커 래핑
    @0verride
    public Foo process(Foo foo) {
        ResponseEntity<String> responseEntity =
        this. restTemplate. exchange(
            "http://rest-service/enrich",
            HttpMethod.GET,
            null,
            String.class);
            
        foo. setMessage(responseEntity.getBody());
        return foo;
    }
}

유레카에서 제공하는 구성을통해 rest api를 사용하기 위해서는 아래와 같은 작업이 필요

  • 의존성 추가
  • @EnableDiscoveryClient을 통한 rest api 등록
    • autoRegister property는 rest api를 유레카에 등록하되 하나의 job으로 등록하는게 아닌 다른 서비스의 구성 상세정보를 얻으려고할 때 false 값으로 정의한다.
  • @LoadBalanced를 통한 RestTamplate bean 정의
    • RestTamplate을 자동구성해 클라이언트 측의 부하 분산 등 구성을 사용할 수 있다.
유레카의 실행 방법
유레카 단일 실행: spring cloud eureka
config server와 동시 실행: spring cloud configserver eureka

스프링 배치에서 오케스트레이션과 관련된 부분은 설계되지 않았으나 스프링 클라우드 데이터 플로우라는 오케스트레이션 도구가 있다.

스프링 클라우드 데이터 플로우는 사용중인 플랫폼에서 배치 잡을 시작하는 서버 애플리케이션이다.

스프링 클라우드 데이터 플로우 서버는 클라우드 파운드리, 쿠버네티스 및 로컬 환경에서 사용할 수 있도록 제공된다.

 
[그림 2] 스프링 클라우드 데이터 플로우 서버

 

스프링 클라우드 데이터 플로우 다운로드

wget https://repo. spring. io/milestone/org/springframework/cloud/spring-cloud-dataflow-
server-local/1.7.4.RELEASE/spring-cloud-dataflow-server-local-1.7.4.RELEASE.jar

wget https://repo.spring.io/milestone/org/springframework/cloud/spring-cloud-dataflow-
shell/1.7.4.RELEASE/spring-cloud-dataflow-shell-1.7.4.RELEASE.jar
반응형

'Framework > spring' 카테고리의 다른 글

part1. 동시성 이슈의 해결 방법 (2+1)가지  (0) 2023.09.05
배치 처리 테스트하기  (0) 2022.09.22
#18 : Lombok  (0) 2020.07.22
#17 : H2 database 연동 준비  (0) 2020.06.13
#16 : query method를 정의하자  (0) 2020.05.24
Comments