Part 4. 클라우드 네이티브 스프링
chapter 13 서비스 탐구하기
마이크로서비스 장점
- 이해하기 쉽다
테스트 쉽다
- 의존성 충돌이 없다
- scale out 유리
- 각기 다른 환경을 선택할 수 있다
- 배포가 편하다
유레카 : 마이크로서비스(서비스 레지스트리)가 서로를 찾을 때 사용, 도메인이 아닌 인스턴스자체를 찾음, 회복성
리본 : 클라이언트 측의 로드 밸런서
클라이언트 수에 비례하여 로드 밸런서의 크기가 조정
- 각 클라이언트에 가장 적합한 로드 밸런싱 알고리즘 사용
유레카 서버
의존성
<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에서 생성된 클라이언트 인터페이스
생략
실행
- 빌드 jar
- 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(생략가능) 를 통해 구성 응답값을 확인해볼 수 있다.
구성 클라이언트
의존성
<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 요청시 구성을 다시 읽어온다
자동
- push -> git 웹훅이 git 변경을 구성서버에 알려준다
- 메시지큐에 변경 메시지를 넣는다
- 각 /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);
}
}
대시보드 웹
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'"
'개발서적' 카테고리의 다른 글
스프링 인 액션 - (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 |
댓글