본문 바로가기
개발서적

스프링 인 액션 - (5)

by 공부 안하고 싶은 사람 2022. 8. 12.
반응형

Part 4. 클라우드 네이티브 스프링

chapter 13 서비스 탐구하기

마이크로서비스 장점

  1. 이해하기 쉽다

테스트 쉽다

  1. 의존성 충돌이 없다
  2. scale out 유리
  3. 각기 다른 환경을 선택할 수 있다
  4. 배포가 편하다

유레카 : 마이크로서비스(서비스 레지스트리)가 서로를 찾을 때 사용, 도메인이 아닌 인스턴스자체를 찾음, 회복성

리본 : 클라이언트 측의 로드 밸런서

클라이언트 수에 비례하여 로드 밸런서의 크기가 조정

  • 각 클라이언트에 가장 적합한 로드 밸런싱 알고리즘 사용

 

 

유레카 서버

의존성

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

<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>
</dependencyManagement>

실행

@SpringBootApplication
@EnableEurekaServer // 애노테이션 추가
public class ServiceRegistryApplication {
  public static void main(String[] args) {
    SpringApplication.run(ServiceRegistryApplication.class, args);
  }
}

기본적으로 다른 유레카 서버로부터 서비스 레지스트리를 가져오거나 다른 유레카 서버의 서비스로 자신을 등록한다. (하나만 쓰려면 아래 참고)

server:
    port: 8761
eureka:
    instance:
        hostname: localhost
    client:
        fetchRegistry: false # default true
        registerWithEureka: false # default true
        serviceUrl:
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

두개의 유레카서버 연결

server:
    port: 8761
eureka:
    instance.hostname: test1.com
other.eureka:
    host: test2.com
    port: 8761
server:
    port: 8762
eureka:
    instance.hostname: test2.com
other.eureka:
    host: test1.com
    port: 8762

자체 보존 : 30초 마다 등록된 레지스트리이 등록을 갱신해야한다. 3번 동안 갱신하지 않으면, 해당 레지스트리 등록을 취소한다.
이 때 취소된 서비스 수가 임계값을 초과하면 자체 보존을 위해 등록 취소가 일어나지 않게 된다.

(인스턴스들의 상태가 자주 변경되거나, 등록된 레지스트리가 없을 때 사용 가능)

eureka:
    server:
        enableSelfPreservation: false # default true

 

 

유레카 클라이언트

의존성

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

유레카 서버에 연결

spring.application.name: service-name # 서버에 등록될 이름 설정
eureka:
    client:
        serviceUrl:
            defaultZone: http://test1.com:8761/eureka/,
                                     http://test2.com:8762/eureka/ # 실패시 순서대로 서버에 등록 시도

리본 사용하여 서비스 인스턴스 찾기

  • 로드 밸선싱된 RestTemplate, Webclient
@Bean
@LoadBalanced // RestTemplate이 리본을 통해서만 서비스를 찾는다고 알려주기
public RestTemplate restTemplate() {
return new RestTemplate();
}

@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return new WebClient.Builder();
}
restTemplate.getForObject( // host와 port를 사용하지 않고 서비스 이름으로 호출할 수 있다.
    "http://service-name/ingredients/{id}", Ingredient.class, ingredientId
);

webClientBuilder.build().get()
.uri("http://service-name/ingredients/{id}", ingredient).retrieve()
.bodyToMoNo(Ingredient.class);
  • Feign에서 생성된 클라이언트 인터페이스
생략

 

 

 

실행

  1. 빌드 jar
  2. java -jar로 실행

 


chapter 14 클라우드 구성 관리

구성(설정 ) 공유하기

  • 재실행 없이 설정 값을 변경 할 수 있다

한번 변경으로 여러 마이크로서비스 구성 변경

  • 보안에 민감한 구성은 별도로 암호화 가능

구성 서버

의존성

<dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
  </dependency>
</dependencies>

<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>
</dependencyManagement>

실행

@SpringBootApplication
@EnableConfigServer // 애노테이션 추가
public class ConfigServerApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServerApplication.class, args);
  }
}

구성 속성들이 있는 곳 설정

spring.cloud.config.server.git:
    url: https://github.com/habuma/tacocloud-config
  search-path: config1, config2 # 해당 경로의 모든 구성 가져온다. default는 루트경로
  default-label: dev # branch생략시 가져올 브랜치 설정
  username: test # 인증
  password: 1q2w3e4r

호스트:포트/application-name/profile/git-branch(생략가능) 를 통해 구성 응답값을 확인해볼 수 있다.

(http://localhost:8888/application/default/master)

 

 

구성 클라이언트

의존성

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

구성서버 연결

spring.cloud.config.uri: http://localhost:8888
spring.application.name: application-name

가져오는 속성

  • application.yml
  • application-{profile}.yml
  • {application-name}.yml
  • {application-name}-{profile}.yml

공통 속성과 애플리케이션 구성 파일이 중복될 때는 애플리케이션 구성이 우선한다.

 

 

구성 값 암호화

사용시엔 자동으로 복호화되어 별도의 복호화코드필요 없이 사용할 수 있다.

bootstrap.yml 설정

encrypt.key: s3cr3t # 대칭키 암호화
encrypt.key-store: # keytool을 통헤 생성한 비대칭키 암호화
    alias: key
    location: classpath:/keystore.jks
    password: l3tm31n
    secret: s3cr3t

암호화 하기

curl localhost:8888/encrypt -d "q1w2e3r4"

spring.data.mongodb.password: '{cipher}(curl로 암호화된 값)'

 

Vault 보안 (생략)

 

 

 

구성 리프레시

수동

acutator 의존 후, localhost:8888/actuator/refresh Post 요청시 구성을 다시 읽어온다

자동

  1. push -> git 웹훅이 git 변경을 구성서버에 알려준다
  2. 메시지큐에 변경 메시지를 넣는다
  3. 각 /actuator/refresh Post요청으로 구성을 다시 읽어온다

 


chapter 15 실패와 지연 처리하기

서킷브레이커 : 다른 마이크로서비스의 연쇄적인 실패 확산 방지 (Netflix의 Hystrix 사용) ->Resilience4j 추천

 

성공시 닫힘 상태가 유지되어 해당 메서드 실행

임계치(시간/횟수)를 넘는 실패시 서킷이 열림상태가 되며 폴백메서드가 실행

지정된시간에 맞춰 반열림 상태가 되면 해당 메서드를 시도 -> 성공시 닫힘 / 실패시 열림

사용 후보

  • REST 호출하는 메서드
  • 쿼리를 수행하는 메서드
  • 지연이 생길 수 있는 메서드

 

의존성

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

<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>
</dependencyManagement>

실행

@SpringBootApplication
@EnableHystrix // 애노테이션 추가
public class ConfigServerApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServerApplication.class, args);
  }
}

서킷 브레이커 (연쇄적으로 설정 가능. 단, end-point에선 실패하지 않는 메서드)

@HystrixCommand(fallbackMethod="getDefaultIngredient") // 서킷브레이커 선언
public Iterable<Ingredient> getIngredient() {...} 

public Iterable<Ingredient> getDefaultIngredient() {...} // fallback 선언 (같은 클래스. 단, 접근제어자는 상관없다)

지연 시간 줄이기

@HystrixCommand(fallbackMethod="getDefaultIngredient",
               commandProperties={
                 @HystrixProperty(
                     name="execution.isolation.timeoutInMilliseconds",
                  value="500") // 0.5초로 설정 default는 1초
               })
public Iterable<Ingredient> getIngredient() {...} 

한계값 설정

@HystrixCommand(fallbackMethod="getDefaultIngredient",
               commandProperties={
                 @HystrixProperty(
                     name="execution.timeout.enabled",
                  value="false"), // 타임아웃 미설정
                 @HystrixProperty(
                     name="circuitBreaker.requestVolumeThreshold",
                  value="30"), // 메서드가 30번 이상 호출되야 함
                 @HystrixProperty(
                     name="circuitBreaker.errorThresholdPercentage",
                  value="25"), // 25% 이상 실패할 경우 열림
                 @HystrixProperty(
                     name="metrics.rollingStatus.timeInMilliseconds",
                  value="20000"), // 기준 시간 20초
                 @HystrixProperty(
                     name="circuitBreaker.sleepWindowInMilliseconds",
                  value="60000"), // 반열림 상태까지 60초 동안 열려있는다.
               })
public Iterable<Ingredient> getIngredient() {...} // 20초 이내에 30번 이상 호출되며 25% 이상 실패할 경우 

 

모니터링

  • 메서드 호출 수
  • 메서드 성공 수
  • 폴백 메서드 호출 수
  • 메서드 타임아웃 수

의존성

<dependency>
    <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

모니터링 활성화

management.endpoints.web.exposure.include: hystrix.stream # /actuator/hystrix.stream 활성화

실행

@SpringBootApplication
@EnableHystrixDashboard // 애노테이션 추가
public class HystrixDashboardApplication {
  public static void main(String[] args) {
    SpringApplication.run(HystrixDashboardApplication.class, args);
  }
}

대시보드 웹

  1. http://localhost:8080/hystrix 접속
  2. http://localhost:8080/actuator/hystrix.stream 입력

Hystrix의 독자적인 스레드 풀관리

호출자(서킷브레이커 설정된)와 지연메소드가 같은 스레드에서 실행 -> 블록상태로 계속 유지 -> 모든 스레드 포화

호출자는 Hystrix의 스레드 풀의 스레드에서 실행되며, 지연이 생길 경우 스레드에서 벗어 날 수 있으므로 포화 상태 방지

 

 

다중 모니터링

Turbine : 모든 Hystrix 스트림 모니터링 가능

의존성 추가

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

실행

@SpringBootApplication
@EnableTurbine // 애노테이션 추가
public class TurbineHystrixDashboardApplication {
  public static void main(String[] args) {
    SpringApplication.run(TurbineHystrixDashboardApplication.class, args);
  }
}

다른 Hystrix 추가 (유레카 사용)

turbine:
    app-config: test-service, test2-service, ...
    cluster-name-expression: "'default'"
728x90
반응형

'개발서적' 카테고리의 다른 글

스프링 인 액션 - (6)  (0) 2022.08.17
스프링 인 액션 - (4)  (0) 2022.08.11
스프링 인 액션 - (3)  (0) 2022.08.10
스프링 인 액션 - (2)  (0) 2022.08.10
스프링 인 액션 - (1)  (0) 2022.08.09

댓글