AWS - MSA pjt

Jaeminst·2022년 5월 10일
3
post-thumbnail

MSA pjt

  • Serverless를 이용한 AWS MSA 구축

프로젝트는 "자동 재고 확보 시스템" 을 위한 MSA를 구성하는 것이 목표이다.

시나리오
<도넛-states>는 부산의 명물 부산도너츠를 판매합니다.
웹사이트를 통해서 주문 버튼을 누르는 것으로 구매(Sales API)가 가능합니다.
창고에 재고가 있다면 재고가 감소하고 구매가 완료됩니다.
유튜브스타가 부산도너츠가 맛있다고 영상을 올리자 판매량이 급증합니다.
창고에 재고가 모두 주문되어 구매가 불가능한 경우가 발생합니다.
창고에 부산도너츠 재고가 다 떨어지면 공장에 알려서 창고를 채우는 시스템을 구축해야합니다.
제조 공장인 <팩토리-states>에 주문을 요청(Legacy Factory API) 할 수 있습니다.
주문이 요청되면 일정 시간이 지난 후 창고에 재고가 증가합니다.


상황

비효율적인 레거시 시스템 때문에 작업 시간이 굉장히 많이 소요되고 있습니다.
제품별 재고부족 요청이 빈번하게 발생되고 있지만 전달과정에서 지연과 누락 등 문제 상황이 발생하고 있습니다.
안정적으로 빠르게 요청이 전달 될 수 있도록 시스템을 개선해야합니다.
또한 성능을 확인해서 개선 결과를 확인하고, 비정상적으로 처리된 요청의 경우 운영팀에 상황을 알려야합니다.

재고부족으로 인한 구매 실패 시

  1. Sales API 를 통한 요청을 받은 서버가 데이터베이스에서 재고 상황을 확인합니다.
  2. 재고가 있다면 감소시키고 응답으로 판매완료 내용을 전달합니다.
  3. 재고가 없는 경우 공장에 주문을 진행합니다
  4. 재고가 없다는 내용을 담은 메세지 페이로드와 함께 SNS topic이 생성됩니다.
  5. 메세지가 SQS로 구현된 stock_queue에 수신됩니다.

Legacy 시스템 성능문제 해결(Factory -> Warehouse)

공장의 시스템이 굉장히 느리고 불안정한 것 같습니다.
위에서 설계한 아키텍처를 참고해서 안정적으로 이벤트가 전달될 수 있는 시스템을 구축해야 합니다.
1. stock_queue 의 메세지를 소비하는 stock_lambda에 의해 Factory API가 호출됩니다.
2. 수신된 메세지에 의해 stock_inc_lambda가 트리거 되어 DB에 상품 재고를 증가시킵니다.

광고 중단 요청

재고가 없는 상황에서도 광고가 계속 진행되고 있습니다.
광고 비용 절감과 고객불만을 낮추기 위한 조치가 필요합니다.
재고를 채우기 위한 과정이 진행 될 때 광고 담당자에게 광고 중단 요청 내용을 담은 이메일이 전송되어야합니다.
1. stock_queue처럼 동일하게 stock_empty 토픽을 구독하는 email_queue가 구성되어야합니다.
2. stock_empty 토픽을 구독하는 send_email_queue에 메세지가 수신됩니다.
3. 수신된 메세지에 의해 email_lambda가 트리거 됩니다.
4. SES 통해 광고 담당자에게 광고 일시 중단을 요청하는 이메일이 전송됩니다.


구성요소

  • Sales API (API Gateway)
  • Sales Lambda (Lambda Function)
  • Stock Database (RDS - MySQL)
  • Stock Empty Topic (SNS)
  • Stock Queue / DLQ (SQS)
  • Stock Lambda (Lambda Function)
  • Factory API (EC2 server)
  • Stock Inc. API (API Gateway)
  • Stock Inc. Lambda (Lambda Function)
  • E-mail Queue / DLQ (SQS)
  • Send E-mail Lambda (Lambda Function)
  • SES

SQS

첫 번째로 SQS Visibility Timeout을 알아야 합니다.
SQS의 특징으로 소비자(다른서비스)가 SQS 대기열에서 수신하고 처리할 때 메시지는 대기열에 남아 있습니다.
SQS는 분산 시스템으로 소비자가 실제로 메시지를 수신한다는 보장이 없습니다.
따라서 소비자는 메시지를 수신하고 처리한 후 Queue에서 메시지를 삭제해야 합니다.

다른 소비자가 메시지를 다시 처리하는 중복처리를 방지하기 위해 SQS에서 다른 소비자가 메시지를 수신 및 처리하지 못하도록 하는 시간 visibility timeout을 설정합니다.
메시지의 기본 표시 시간 제한은 30초이며 최소 0초, 최대 12시간 입니다.
콘솔을 사용하여 대기열에 대한 표시 제한 시간을 구성하는 방법에 대한 자세한 내용은 대기열 매개변수 구성(콘솔) 을 참조하십시오 .

표준 대기열의 경우 표시 제한 시간(visibility timeout)이 메시지를 두 번 수신하는 것을 보장하지 않습니다.
자세한 내용은 최소 한 번 배달을 참조하세요.

DLQ

DLQ의 개념을 잘 알고 있어야 한다.
SQS에서 DLQ로 보내기위한 조건을 설정하는데 예로들면 소비자가 메시지를 가져가고 3번 실패를 한다면 DLQ로 보내도록 설정할 수 있다.

소비자가 메시지를 가져가면 표시 시간 제한(visibility timeout) 동안 소비자가 처리 후 메시지를 삭제하게 되는데 네트워크 장애나 소비자의 문제로 처리하지 못 할 경우 표시 시간 제한이 끝나고 다시 다른 소비자에게 메시지를 노출합니다.
메시지를 처리하지 못하는 문제가 반복되면 DLQ로 보내게 됩니다.

왜 sererless Lift 가 기본으로 DLQ를 생성해주는가?
https://github.com/getlift/lift/blob/master/docs/queue.md#retries


Cloud Architecture Diagram


프로젝트 진행

먼저, 프로젝트 진행에 있어서 코드의 고민보다 프레임워크의 활용과 MSA 구성, 아키텍처 설계 등을 목표로 함으로 기본적인 코드를 가지고 진행합니다.


DAY 1

Step1: Serverless 기반 legacy 시스템 배포 및 테스트 학습

  • Serverless의 사용법 학습
  • curl로 간단한 동작 테스트

Step2: SQS 이용하여 Producer-Consumer 구조 개발 학습

  • SQS에 Queue에 메시지를 담는 Lambda와 그것을 소비하는 Lambda 구성

Step3: SNS-SQS 환경에서, SNS 발행서버 구현

  • nodejs 서버를 구현하고 SNS 발행시 구독하는 SQS가 메시지를 저장

Step4: “부산도너츠" 마이크로서비스 시나리오 환경구성

  • RDS를 구성하고 nodejs 서버로 구매요청 시 재고를 확인 후 응답
  • 재고가 없으면 SNS 발행

DAY 2

Step1: 성능 테스트

  • K6를 활용한 성능 테스트
  • 주요 메트릭 학습
    • 단순한 숫자를 더하는 Counter
    • min,amx, last value가 보여지는 Gauge
    • 퍼센트를 표현하는 Rate
    • 추가 값(최소, 최대, 평균 및 백분위수)에 대한 통계를 계산할 수 있는 Trend
  • Using K6 Metrics
  • https://k6.io/docs/
  • https://github.com/k6io/k6

Step2: Dead Letter Queue(DLQ) 연습

  • 람다에서 짝수의 메시지는 처리하지 못하도록 만든다.
  • K6를 활용해 100개의 메시지를 보낸다.
  • DLQ에 50개의 메시지가 쌓인다.

Step3: 다이어그램 작성

Step4: Sales API 배포

Step5: Stock Empty 람다 배포

  • [ 영업 api ] -> sns -> sqs -> (Stock Empty labmda) -> [ 공장 api ]
  • 공장 API로 curl POST요청을 보내는 람다로 curl nodejs 와 같은 검색을 해보았다.
  • https://curlconverter.com 참고하여 코드를 완성하였다.

DAY 3

Step1: 공장 api REST API 문서 배포를 자동화 하기

  • ssh -i ~/aws_key/MyKeyPair.pem $ec2_dns docker build
  • ssh로 ec2에 접속하는데 그 뒤에오는 인자들로 명령만 줄 수 있었다.
  • 참조 키워드: redoc-cli, swagger editor

Step2: 공장서버의 콜백 메시지를 받아 재고를 추가하는 람다를 구현하기

  • serverless로 생성한 api를 공장 api서버에서 콜백을 보내도록 구현하였다.

트러블슈팅

1. params error

aws-sdk로 sns.publish를 작성할 때 표준타입과 FIFO타입을 구분해야한다.
sns.publish(params, callback)params에 FIFO타입일 때 포함하고 표준타입일 때 포함하면 안되는 값이 있다.

  • MessageGroupId
  • MessageDeduplicationId

2. JSON parse

Stock Queue에서 받아온 메시지를 람다에서 console.log를 찍어보면 event 메시지안에 body가 String의 형태로 저장되어 있다.

JSON.parse()를 사용하여 parsing 하면 된다.


프로젝트 진행 추천 자료

소프트웨어

간편한 SQL GUI Tool
https://tableplus.com/

블로그

리눅스 마스터가 되어 파이프라인으로 프로그래밍을 짜고 싶을 정도라면 이 책 리뷰를 참고
https://martinhongsw.medium.com/리눅스의-장점인-파이프라인-bf77f27bf1c4

비동기 방식과 콜백함수

https://jaehoney.tistory.com/19

테라폼으로 api 게이트웨이를 붙였지만 deploy를 하지 않았을때!

https://stackoverflow.com/questions/38910937/terraform-not-deploying-api-gateway-stage

서버리스로 람다를 배포하지 않고 로컬에서 오프라인상태에서 테스트 해보기(50~200초 세이브)

https://www.serverless.com/plugins/serverless-offline

로컬에서 lambda 함수 테스트 하기

https://www.serverless.com/blog/how-test-serverless-applications

EC2에 docker 중지 요청 보내기

docker ps | grep nginx-redoc:latest | awk '{print $1}' | xargs docker stop
docker ps -aq | xargs docker stop

프로젝트가 끝나고 읽어볼거리

profile
DevOps !

1개의 댓글

comment-user-thumbnail
2022년 5월 18일

데봅스 보물창고(❁´◡`❁)

답글 달기