- 기능적 요구사항(전체)
- 휴양소 관리자는 휴양소를 등록한다.
- 고객이 휴양소를 선택하여 예약한다.
- 고객이 예약한 휴양소를 결제한다.(팀과제에서 제외)
- 예약이 확정되어 휴양소는 예약불가 상태로 바뀐다.
- 바우처가 고객에게 발송된다. (팀과제에서 제외)
- 고객이 확정된 예약을 취소할 수 있다.
- 주문이 취소되면 바우처가 비활성화 된다.(팀과제에서 제외)
- 휴양소는 예약가능 상태로 바뀐다.
- 고객은 휴양소 예약 정보를 확인 할 수 있다.
- 비기능적 요구사항
- 트랜잭션
- 리조트 상태가 예약 가능상태가 아니면 아예 예약이 성립되지 않아야 한다 Sync 호출
- 장애격리
- 결제/바우처/마이페이지 기능이 수행되지 않더라도 주문은 365일 24시간 받을 수 있어야 한다. Async (event-driven), Eventual Consistency
- 예약시스템이 과중되면 사용자를 잠시동안 받지 않고 잠시후에 하도록 유도한다. Circuit breaker, fallback
- 성능
- 고객이 자신의 예약 상태를 확인할 수 있도록 마이페이지가 제공 되어야 한다. CQRS
- MSAEz 로 모델링한 이벤트스토밍 결과: http://www.msaez.io/#/storming/Rk7HwUkaXvX3C7EArWnMpnml68j1/share/4992a1785df30cc101b0e57f3400fa2d
- View Model 추가
- 도메인 서열
- Core : reservation
- Supporting : resort, mypage
- General : payment, voucher
- Chris Richardson, MSA Patterns 참고하여 Inbound adaptor와 Outbound adaptor를 구분함
- 호출관계에서 PubSub 과 Req/Resp 를 구분함
- 서브 도메인과 바운디드 컨텍스트의 분리: 각 팀의 KPI 별로 아래와 같이 관심 구현 스토리를 나눠가짐
분석/설계 단계에서 도출된 헥사고날 아키텍처에 따라, 각 BC별로 대변되는 마이크로 서비스들을 스프링부트로 구현하였다. 구현한 각 서비스를 로컬에서 실행하는 방법은 아래와 같다 (각자의 포트넘버는 8081 ~ 808n 이다)
- 휴양소 관리자는 휴양소를 등록한다.
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/resorts resortName="Jeju" resortType="Hotel" resortPrice=100000 resortStatus="Available" resortPeriod="7/23~25"
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/resorts resortName="Seoul" resortType="Hotel" resortPrice=100000 resortStatus="Available" resortPeriod="7/23~25"
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/resorts
- 고객이 휴양소를 선택하여 예약한다.
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/reservations resortId=2 memberName="sim sang joon"
- 예약이 확정되어 휴양소는 예약불가 상태로 바뀐다.
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/resorts/2
- 고객이 확정된 예약을 취소할 수 있다.
http PATCH aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/reservations/1 resortStatus="Cancelled"
- 휴양소는 예약 가능상태로 바뀐다.
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/resorts/2
- 고객은 휴양소 예약 정보를 확인 할 수 있다.
http aa9c6a809425d45b69b139edc5237d53-1942883713.ap-northeast-2.elb.amazonaws.com:8080/myPages
- 위 이벤트 스토밍을 통해 식별된 Micro Service 전체 5개 중 3개를 구현하였으며 그 중 mypage는 CQRS를 위한 서비스이다.
MSA | 기능 | port | URL |
---|---|---|---|
reservation | 예약정보 관리 | 8081 | http://localhost:8081/reservations |
resort | 리조트 관리 | 8082 | http://localhost:8082/resorts |
mypage | 예약내역 조회 | 8083 | http://localhost:8083/mypages |
gateway | gateway | 8088 | http://localhost:8088 |
- API GateWay를 통하여 마이크로 서비스들의 진입점을 통일할 수 있다. 다음과 같이 GateWay를 적용하였다.
- gateway 서비스의 application.yml
server:
port: 8088
---
spring:
profiles: default
cloud:
gateway:
routes:
- id: reservation
uri: http://localhost:8081
predicates:
- Path=/reservations/**
- id: resort
uri: http://localhost:8082
predicates:
- Path=/resorts/**
- id: mypage
uri: http://localhost:8083
predicates:
- Path= /myPages/**
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins:
- "*"
allowedMethods:
- "*"
allowedHeaders:
- "*"
allowCredentials: true
---
spring:
profiles: docker
cloud:
gateway:
routes:
- id: reservation
uri: http://reservation:8080
predicates:
- Path=/reservations/**
- id: resort
uri: http://resort:8080
predicates:
- Path=/resorts/**
- id: mypage
uri: http://mypage:8080
predicates:
- Path= /myPages/**
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins:
- "*"
allowedMethods:
- "*"
allowedHeaders:
- "*"
allowCredentials: true
server:
port: 8080
- CQRS 를 위한 mypage 서비스만 DB를 구분하여 적용함. 인메모리 DB인 hsqldb 사용.
- maypage 서비스의 pom.xml
<!--
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
-->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.0</version>
<scope>runtime</scope>
</dependency>
- 타 마이크로서비스의 데이터 원본에 접근없이 내 서비스의 화면 구성과 잦은 조회가 가능하게 mypage에 CQRS 구현하였다.
- 모든 정보는 비동기 방식으로 발행된 이벤트(예약, 예약취소, 가능상태변경)를 수신하여 처리된다.
예약 실행
{"eventType":"ReservationRegistered","timestamp":"20210712022656","id":1,"resortId":2,"resortName":"Seoul","resortStatus":"Confirmed","resortType":"Hotel","resortPeriod":"7/23~25","resortPrice":100000.0,"memberName":"sim sang joon"}
{"eventType":"ResortStatusChanged","timestamp":"20210712022656","id":2,"resortName":"Seoul","resortStatus":"Not Available","resortType":"Hotel","resortPeriod":"7/23~25","resortPrice":100000.0}
{"eventType":"ReservationCanceled","timestamp":"20210712022719","id":1,"resortId":2,"resortName":"Seoul","resortStatus":"Cancelled","resortType":"Hotel","resortPeriod":"7/23~25","resortPrice":100000.0,"memberName":"sim sang joon"}
{"eventType":"ResortStatusChanged","timestamp":"20210712022719","id":2,"resortName":"Seoul","resortStatus":"Available","resortType":"Hotel","resortPeriod":"7/23~25","resortPrice":100000.0}
예약/예약취소 후 mypage 화면
-
분석단계에서의 조건 중 하나로 예약(reservation)->리조트상태확인(resort) 간의 호출은 동기식 일관성을 유지하는 트랜잭션으로 처리하기로 하였다. 호출 프로토콜은 이미 앞서 Rest Repository 에 의해 노출되어있는 REST 서비스를 FeignClient를 이용하여 호출하였다
-
리조트서비스를 호출하기 위하여 Stub과 (FeignClient) 를 이용하여 Service 대행 인터페이스 (Proxy) 를 구현
# (reservation) ResortService.java
package resortreservation.external;
@FeignClient(name="resort", url="${feign.resort.url}")
public interface ResortService {
@RequestMapping(method= RequestMethod.GET, value="/resorts/{id}", consumes = "application/json")
public Resort getResortStatus(@PathVariable("id") Long id);
}
- 예약을 처리 하기 직전(@PrePersist)에 ResortSevice를 호출하여 서비스 상태와 Resort 세부정보도 가져온다.
# Reservation.java (Entity)
@PrePersist
public void onPrePersist() throws Exception {
resortreservation.external.Resort resort = new resortreservation.external.Resort();
//Resort 서비스에서 Resort의 상태를 가져옴
resort = ReservationApplication.applicationContext.getBean(resortreservation.external.ResortService.class)
.getResortStatus(resortId);
// 예약 가능상태 여부에 따라 처리
if ("Available".equals(resort.getResortStatus())){
this.setResortName(resort.getResortName());
this.setResortPeriod(resort.getResortPeriod());
this.setResortPrice(resort.getResortPrice());
this.setResortType(resort.getResortType());
this.setResortStatus("Confirmed");
} else {
throw new Exception("The resort is not in a usable status.");
}
}
- 동기식 호출에서는 호출 시간에 따른 타임 커플링이 발생하며, 시스템이 장애로 예약을 못받는다는 것을 확인
- 또한 과도한 요청시에 서비스 장애가 도미노 처럼 벌어질 수 있다. (서킷브레이커, 폴백 처리는 운영단계에서 설명한다.)
- 예약이 이루어진 후에 결제시스템에 결제요청과 마이페이지시스템에 이력을 보내는 행위는 동기식이 아니라 비 동기식으로 처리하여 예약이 블로킹 되지 않아도록 처리한다.
- 이를 위하여 예약기록을 남긴 후에 곧바로 예약완료가 되었다는 도메인 이벤트를 카프카로 송출한다(Publish)
@Entity
@Table(name="Reservation_table")
public class Reservation {
...
@PostPersist
public void onPostPersist() throws Exception {
...
ReservationRegistered reservationRegistered = new ReservationRegistered();
BeanUtils.copyProperties(this, reservationRegistered);
reservationRegistered.publishAfterCommit();
}
}
- 결제시스템과 마이페이지시스템에서는 예약완료 이벤트에 대해서 이를 수신하여 자신의 정책을 처리하도록 PolicyHandler 를 구현한다
결제시스템(팀과제에서는 미구현)
@Service
public class PolicyHandler{
@Autowired PaymentRepository paymentRepository;
@StreamListener(KafkaProcessor.INPUT)
public void wheneverReservationRegistered_PaymentRequestPolicy(@Payload ReservationRegistered reservationRegistered){
if(!reservationRegistered.validate()) return;
System.out.println("\n\n##### listener PaymentRequestPolicy : " + reservationRegistered.toJson() + "\n\n");
// Logic 구성 //
}
}
마이페이지시스템
@Service
public class MyPageViewHandler {
@Autowired
private MyPageRepository myPageRepository;
@StreamListener(KafkaProcessor.INPUT)
public void whenReservationRegistered_then_CREATE_1 (@Payload ReservationRegistered reservationRegistered) {
try {
if (!reservationRegistered.validate()) return;
// view 객체 생성
MyPage myPage = new MyPage();
// view 객체에 이벤트의 Value 를 set 함
myPage.setId(reservationRegistered.getId());
myPage.setMemberName(reservationRegistered.getMemberName());
myPage.setResortId(reservationRegistered.getResortId());
myPage.setResortName(reservationRegistered.getResortName());
myPage.setResortStatus(reservationRegistered.getResortStatus());
myPage.setResortType(reservationRegistered.getResortType());
myPage.setResortPeriod(reservationRegistered.getResortPeriod());
myPage.setResortPrice(reservationRegistered.getResortPrice());
// view 레파지 토리에 save
myPageRepository.save(myPage);
}catch (Exception e){
e.printStackTrace();
}
}
}
- 예약 시스템은 결제시스템/마이페이지 시스템과 완전히 분리되어있으며, 이벤트 수신에 따라 처리되기 때문에, 결제시스템/마이시스템이 유지보수로 인해 잠시 내려간 상태라도 예약을 받는데 문제가 없다
# 마이페이지 서비스는 잠시 셧다운 시키고 결제시스템은 현재 미구현
1.리조트입력
http localhost:8082/resorts resortName="Jeju" resortType="Hotel" resortPrice=100000 resortStatus="Available" resortPeriod="7/23~25"
http localhost:8082/resorts resortName="Seoul" resortType="Hotel" resortPrice=100000 resortStatus="Available" resortPeriod="7/23~25"
2.예약입력
http localhost:8081/reservations resortId=2 memberName="sim sang joon"
http localhost:8081/reservations #예약 정상 처리 확인
3.마이페이지서비스 기동
4.마이페이지확인
http localhost:8083/myPages #정상적으로 마이페이지에서 예약 이력이 확인 됨
각 구현체들은 각자의 source repository 에 구성되었고, 각 서비스별로 Docker로 빌드를 하여, Docker Hub에 등록 후 deployment.yaml, service.yml을 통해 EKS에 배포함.
- git에서 소스 가져오기
git clone https://github.com/simair77/resort_reservation.git
- 각서비스별 packege, build, github push 실행
cd resort #서비스별 폴더로 이동
mvn package -B -Dmaven.test.skip=true #패키지
docker build -t simair/resort:latest . #docker build
docker push simair/resort:latest #docker push
kubectl apply -f resort/kubernetes/deployment.yml #AWS deploy 수행
kubectl apply -f resort/kubernetes/service.yaml. #AWS service 등록
- Docker Hub Image
- 최종 Deploy완료
- 서킷 브레이크 프레임워크 : Spring FeignClient + Hystrix 옵션을 사용
- 시나리오 : 예약(reservation) -> 휴양소(resort) 예약 시 RESTful Request/Response 로 구현이 하였고, 예약 요청이 과도할 경우 circuit breaker 를 통하여 장애격리. Hystrix 설정: 요청처리 쓰레드에서 처리시간이 610 밀리초가 넘어서기 시작하여 어느정도 유지되면 circuit breaker 수행됨
# application.yml
feign:
hystrix:
enabled: true
hystrix:
command:
# 전역설정
default:
execution.isolation.thread.timeoutInMilliseconds: 610
피호출 서비스(휴양소:resort) 의 임의 부하 처리 - 400 밀리초 ~ 620밀리초의 지연시간 부여
# (resort) ResortController.java
@RequestMapping(method= RequestMethod.GET, value="/resorts/{id}")
public Resort getResortStatus(@PathVariable("id") Long id){
//hystix test code
try {
Thread.currentThread().sleep((long) (400 + Math.random() * 220));
} catch (InterruptedException e) { }
return repository.findById(id).get();
}
부하테스터 siege 툴을 통한 서킷 브레이커 동작 확인 : 동시사용자 100명, 10초 동안 실시
$ siege -v -c100 -t10S -r10 --content-type "application/json" 'http://localhost:8081/reservations POST {"resortId":1, "memberName":"MK"}'
** SIEGE 4.0.5
** Preparing 100 concurrent users for battle.
The server is now under siege...
HTTP/1.1 201 3.64 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 3.64 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 3.70 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 3.94 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 3.98 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.00 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.05 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.05 secs: 343 bytes ==> POST http://localhost:8081/reservations
* 요청이 과도하여 CB를 동작함 요청을 차단
HTTP/1.1 500 4.07 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.07 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.07 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.07 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.07 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.08 secs: 183 bytes ==> POST http://localhost:8081/reservations
* 요청을 어느정도 돌려보내고나니, 기존에 밀린 일들이 처리되었고, 회로를 닫아 요청을 다시 받기 시작
HTTP/1.1 201 4.12 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.18 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.25 secs: 343 bytes ==> POST http://localhost:8081/reservations
* 다시 요청이 쌓이기 시작하여 건당 처리시간이 610 밀리를 살짝 넘기기 시작 => 회로 열기 => 요청 실패처리
HTTP/1.1 500 4.32 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.32 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.32 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.32 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.32 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.33 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.33 secs: 183 bytes ==> POST http://localhost:8081/reservations
* 다시 요청 처리 - (건당 (쓰레드당) 처리시간이 610 밀리 미만으로 회복) => 요청 수락
HTTP/1.1 201 4.45 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.48 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.53 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.54 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.58 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.66 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.70 secs: 343 bytes ==> POST http://localhost:8081/reservations
* 이후 이러한 패턴이 계속 반복되면서 시스템은 도미노 현상이나 자원 소모의 폭주 없이 잘 운영됨
HTTP/1.1 201 4.39 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.50 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.64 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.65 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.66 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.67 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.38 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.83 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.46 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.08 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 3.92 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 3.91 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.46 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.47 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.57 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.58 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.65 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.68 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.68 secs: 343 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.66 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.69 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.40 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.40 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.34 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.50 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.42 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.54 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.52 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.21 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.52 secs: 345 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 500 4.36 secs: 183 bytes ==> POST http://localhost:8081/reservations
HTTP/1.1 201 4.35 secs: 345 bytes ==> POST http://localhost:8081/reservations
Lifting the server siege...
Transactions: 152 hits
Availability: 80.85 %
Elapsed time: 9.66 secs
Data transferred: 0.06 MB
Response time: 4.92 secs
Transaction rate: 15.73 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 77.34
Successful transactions: 152
Failed transactions: 36
Longest transaction: 5.63
Shortest transaction: 1.33
- siege 수행 결과
- 앞서 CB 는 시스템을 안정되게 운영할 수 있게 해줬지만 사용자의 요청을 100% 받아들여주지 못했기 때문에 이에 대한 보완책으로 자동화된 확장 기능을 적용하고자 한다.
- 리조트서비스에 대한 replica 를 동적으로 늘려주도록 HPA 를 설정한다. 설정은 CPU 사용량이 20프로를 넘어서면 replica 를 10개까지 늘려준다:
kubectl autoscale deployment resort --cpu-percent=20 --min=1 --max=10
- CB 에서 했던 방식대로 워크로드를 100초 동안 걸어준다.
siege -c20 -t100S -v http://resort:8080/resorts
- 오토스케일이 어떻게 되고 있는지 모니터링을 해보면 어느정도 시간이 흐른 후 스케일 아웃이 벌어지는 것을 확인할 수 있다:
- 먼저 무정지 재배포가 100% 되는 것인지 확인하기 위해서 Autoscaler 이나 CB 설정을 제거하고 테스트함
- seige로 배포중에 부하를 발생과 재배포 실행
root@siege:/# siege -c1 -t30S -v http://resort:8080/resorts
kubectl apply -f kubernetes/deployment.yml
- seige 의 화면으로 넘어가서 Availability 가 100% 미만으로 떨어졌는지 확인
- 이를 막기위해 Readiness Probe 를 설정함: deployment.yaml 의 readiness probe 추가
readinessProbe:
httpGet:
path: '/actuator/health'
port: 8080
initialDelaySeconds: 10
timeoutSeconds: 2
periodSeconds: 5
failureThreshold: 10
- 동일한 시나리오로 재배포 한 후 Availability 확인
- Pod는 정상적으로 작동하지만 내부의 어플리케이션이 반응이 없다면, 컨테이너는 의미가 없다.
- 위와 같은 경우는 어플리케이션의 Liveness probe는 Pod의 상태를 체크하다가, Pod의 상태가 비정상인 경우 kubelet을 통해서 재시작한다.
- 임의대로 Liveness probe에서 path를 잘못된 값으로 변경 후, retry 시도 확인
livenessProbe:
httpGet:
path: '/actuator/fakehealth' <-- path를 잘못된 값으로 변경
port: 8080
initialDelaySeconds: 120
timeoutSeconds: 2
periodSeconds: 5
failureThreshold: 5
- resort Pod가 여러차례 재시작 한것을 확인할 수 있다.
- 시스템별로 또는 운영중에 동적으로 변경 가능성이 있는 설정들을 ConfigMap을 사용하여 관리합니다. Application에서 특정 도메일 URL을 ConfigMap 으로 설정하여 운영/개발등 목적에 맞게 변경가능합니다. configMap 생성
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: resort-cm
data:
api.resort.url: resort:8080
EOF
configmap 생성 후 조회 deployment.yml 변경
containers:
...
env:
- name: feign.resort.url
valueFrom:
configMapKeyRef:
name: resort-cm
key: api.resort.url
ResortService.java내용
@FeignClient(name="resort", url="${feign.resort.url}")
public interface ResortService {
@RequestMapping(method= RequestMethod.GET, value="/resorts/{id}", consumes = "application/json")
public Resort getResortStatus(@PathVariable("id") Long id);
}