IT STUDY LOG

[SECTION3] <마이크로서비스> DAY 2 LOG 본문

devops bootcamp 4/project log

[SECTION3] <마이크로서비스> DAY 2 LOG

roheerumi 2023. 5. 25. 17:03

# Achivement Goals

  • 메시지 큐의 Pub/Sub 패턴과 Producer/Consumer 패턴의 차이를 이해한다
  • DB와 서버와의 통신이 가능하도록 연결한다
  • 특정 상황에서 SNS, SQS로 메시지가 전달되도록 시스템을 구성한다
  • SQS에 들어온 메시지를 레거시 시스템(Factory API)으로 전달하는 시스템을 구성한다
  • 레거시 시스템(Factory API)의 콜백 대상이 되는 리소스를 생성해 데이터베이스에 접근할 수 있게 한다

 

# PROJECT LOG

Project - Step 1

Step 1:Lambda 서버(Sales API) - DB 연결

1. sales-api 디렉토리에서 Sales API 확인

2. 데이터베이스 연결

  • 로컬 : .env 파일 이용
  • AWS : Lambda 구성 -> 환경변수 이용
    • HOSTNAME=projectdb.secret.region.rds.amazonaws.com
    • USERNAME=username
    • PASSWORD=password
    • DATABASE=database

3. 연결 후 레포지토리의 sales-api/init.sql을 참고하여 자신의 데이터베이스에 테이블을 생성하고 재고를 추가

$ mysql -u user -h projectdb.ap-northeast-2.rds.amazonaws.com -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 101
Server version: 8.0.32 Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

4. CURL 요청을 통해 데이터베이스의 재고 정보에 따라 다른 응답을 보내는 것을 확인

# endpoint는 sls deploy 후 확인 가능
# url + 요청 메소드 엔도프인트
$ CURL -X GET https://xxxxxxx.execute-api.ap-northeast-2.amazonaws.com/product/donut
{
"product_id":"e7b5da50-fa94-11ed-8923-0aebfd403c0e",
"name":"부산도너츠",
"price":19900,
"stock":3,
"BIN_TO_UUID(factory_id)":"c5544aea-fa94-11ed-8923-0aebfd403c0e",
"BIN_TO_UUID(ad_id)":"c68f5c70-fa94-11ed-8923-0aebfd403c0e"
}

 

Project - Step 2

Step 2: “재고 없음” 메시지 전달 시스템 구성

1. DB에 재고가 없을 경우 재고가 없다는 정보를 알리기 위한 SNS 토픽(stock_empty) 생성

1-1. AWS Console에서 SNS 주제 생성

1-2. (Optional) IaC(Terraform)을 사용해 구성

2. stock_empty 토픽을 구독하는 SQS(stock_queue) 생성

2-1. AWS Console에서 SQS 생성

2-2. AWS Console에서 SNS 구독 생성

2-3. (Optional) IaC(Terraform)을 사용해 구성

3. code snippet을 활용하여 재고 부족 메시지를 SNS에 발행

3-1. handler.js 파일 수정

// ../project3-msa/sales-api/handler.js

// .. 상략 ..

// [!] 추가
const {
  alertSNS
} = require('./aws')

// .. 중략 ..

app.post("/checkout", connectDb, async (req, res, next) => {
  const [ result ] = await req.conn.query(
    getProduct('CP-502101')
  )
  if (result.length > 0) {
    const product = result[0]

    if (product.stock > 0) {
      await req.conn.query(setStock(product.product_id, product.stock - 1))
      return res.status(200).json({ message: `구매 완료! 남은 재고: ${product.stock - 1}`});
    }
    else {
      // [!] 추가
      await alertSNS(product.product_id, product.factory_id)
      await req.conn.end()
      return res.status(200).json({ message: `구매 실패! 남은 재고: ${product.stock}`});
    }
  } else {
    await req.conn.end()
    return res.status(400).json({ message: "상품 없음" });
  }
});

// .. 하략 ..

3-2. aws 리소스 관련 메서드 모듈인 aws.js 파일 생성

// ../project3-msa/sales-api/aws.js

// aws-sdk v2 사용
const AWS = require("aws-sdk") // STEP 2
const sns = new AWS.SNS({ region: "ap-northeast-2" }) // STEP 2

const alertSNS = async (product_id, factory_id) => {
  const now = new Date().toString()
  const message = `도너츠 재고가 없습니다. 제품을 생산해주세요! \n메시지 작성 시각: ${now}`
  const params = {
  Message: message,
  Subject: '도너츠 재고 부족',
  MessageAttributes: {
    MessageAttributeProductId: {
      StringValue: product_id,
      DataType: "String",
    },
    MessageAttributeFactoryId: {
      StringValue: factory_id,
      DataType: "String",
    },
  },
  TopicArn: process.env.TOPIC_ARN
  }
const result = await sns.publish(params).promise()
}

module.exports = {
  alertSNS
}

3-3.  CURL을 통해 재고가 없을 때까지 요청을 보내보고 재고가 없는 경우 stock_queue에 메시지가 들어온 것을 확인

$ CURL -X POST https://xxxxxxxxxx.execute-api.ap-northeast-2.amazonaws.com/checkout
cloud watch의 sales-api 람다 로그에서 메시지가 stock_empty(SNS)에 send되었는지 확인
stock_empty(SNS)를 구독중인 stock_queue(SQS)에 정상적으로 메시지가 전달되었는지 확인
stock_queue(SQS)에 전달된 메시지 확인

 

Project - Step 3

Step 3-1: About DLQ

Step 3 -2: 메시지를 Factory API로 전송하는 Lambda 구성 및 DLQ 추가

1. 가용성을 높이기 위해 dead_letter_queue(DLQ)를 생성하고 stock_queue에 연결

2. stock_queue에 들어온 메시지를 소모하기 위한 stock_lambda 구성

2-1. serverless를 사용해 람다 함수 구성

$ serverless 
# template : AWS - Node.js - Starter
# project name : stock-lambda
# deploy now : N

2-2. serverless.yml을 수정해 SQS에 도착한 메시지를 소비하는 람다 함수 구성

# serverless.yml

service: stock-lambda
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs14.x
  region: ap-northeast-2

functions:
  api:
    handler: handler.handler
    events:
      - sqs:
          arn:
            Fn::Join:
              - ':'
              - - arn
                - aws
                - sqs
                - Ref: AWS::Region
                - Ref: AWS::AccountId
                - stock_queue # SQS명

2-3. handler.js에서 SQS 메시지 이벤트 발생 시 이벤트를 핸들링하는 메서드 작성

const AWS = require('aws-sdk');
const sqs = new AWS.SQS({ region: "ap-northeast-2" }) 

exports.handler = async function(event, context) {
    console.log(`[event] : ${JSON.stringify(event)}`)
    console.log(`[context] : ${JSON.stringify(event)}`)

    // TODO factory API 처리

}

3. sales-api에 요청을 보낸 뒤 stock_queue에서 메시지가 사라지는 것과 stock_lambda에서 생성된 로그 확인

$ CURL -X POST https://xxxxxxxxxx.execute-api.ap-northeast-2.amazonaws.com/checkout
stock_queue에 사용가능한 메시지가 1에서 0으로 감소 (lambda 함수에서 소비)
cloud watch의 stock-lambda 로그에서 stock_queue(SQS) 메시지가 전달되어 소비되었음을 확인

 

# REFERENCES

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-envvars.html

 

AWS Lambda 환경 변수 사용 - AWS Lambda

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

https://repost.aws/knowledge-center/sns-topic-lambda

 

Publish a message to an Amazon SNS topic using a Lambda

I want to publish a message to an Amazon Simple Notification Service (Amazon SNS) topic from an AWS Lambda function.

repost.aws

https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/aws-jsdk-reference.html

 

JavaScript API 참조 - AWS SDK for JavaScript

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

https://github.com/getlift/lift/blob/master/docs/queue.md

Comments