Project3 Day2 회고

업데이트:     Updated:

카테고리:

태그:

Day 2


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


주어진 레포지토리를 활용 해서 DB와 연결 하는 과정을 진행 하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
service: sales-api
frameworkVersion: '3'

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

functions:
  api:
    handler: handler.handler
    events:
      - httpApi: '*'

yaml 파일로 람다를 생성해 환경 변수를 입력 하여 DB로 직접 연결 하는 과정을 진행 하였다.

1
mysql -h서버 -u아이디 -p비밀번호 데이터베이스명

​ #mysql CLI 연결 방법

DB생성 및 재고등 입력 후 cURL 명령어로 재고 확인 및 구매 요청 진행

1
curl -X GET https://sq2xu55mai.execute-api.ap-northeast-2.amazonaws.com/product/donut

주어진 js의 GET 엔드포인트는 /product/donut 이었다.

포스트맨-GET

CLI창에 지저분하게 나와 보기좋게 post맨을 활용 하였다.


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const serverless = require("serverless-http");
const express = require("express");
const app = express();
app.use(express.json())
const dotenv = require('dotenv');
dotenv.config();

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


const {
  connectDb,
  queries: { getProduct, setStock }
} = require('./database');
const { request } = require("http");

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

  await req.conn.end()
  if (result.length > 0) {
    return res.status(200).json(result[0]);
  } else {
    return res.status(400).json({ message: "상품 없음" });
  }
});

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 && product.stock >= req.body.MessageAttributeProductCnt) {
      await req.conn.query(setStock(product.product_id, product.stock - req.body.MessageAttributeProductCnt))
      return res.status(200).json({ message: `구매 완료! 남은 재고: ${product.stock - req.body.MessageAttributeProductCnt}`});
    } else {
      await req.conn.end()
      const now = new Date().toString()
      const message = `도너츠 재고가 없습니다. 제품을 생산해주세요! \n메시지 작성 시각: ${now}`
      const params = {
        Message: message,
        Subject: '도너츠 재고 부족',
        MessageAttributes: {
          MessageAttributeProductId: {
            StringValue: product.product_id,
            DataType: "String",
          },
          MessageAttributeFactoryId: {
            StringValue: req.body.MessageAttributeFactoryId,
            DataType: "String",
          },
          MessageAttributeProductCnt: {
            StringValue: req.body.MessageAttributeProductCnt,
            DataType: "String",
          },
          MessageAttributeRequester: {
            StringValue: req.body.requester,
            DataType: "String",
          }
        },
        TopicArn: process.env.TOPIC_ARN
      }
      console.log("보낸 메시지 : ", params)
      const result = await sns.publish(params).promise()
      return res.status(200).json({ message: `구매 실패! 남은 재고: ${product.stock}`});
    }
  } else {
    await req.conn.end()
    return res.status(400).json({ message: "상품 없음" });
  }
});


app.use((req, res, next) => {
  return res.status(404).json({
    error: "Not Found",
  });
});

module.exports.handler = serverless(app);
module.exports.app = app;

  • DB에 재고가 없을 경우 재고가 없다는 정보를 알리기 위한 SNS 토픽(stock_empty) 생성
  • stock_empty 토픽을 구독하는 SQS(stock_queue) 생성

project3-lambda-agw-sns연결

  • lambda에서 대상 추가로 생성된 주제로 연결하여 SQS 대기열에 메세지를 연결 시킨다.

SQS 대기열

  • cURL을 통해 재고가 없을 때까지 요청을 보냄

cURL-POST-구매실패메시지

  • 재고보다 많은 수량을 요청 하면 구매 실패 메시지가 뜨도록 구성.
  • CloudWatch를 통해서도 확인 가능하다

Cloudwatch-구매실패


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


  • 가용성을 높이기 위한 DLQ를 stock_queue에 연결

DLQ 설정

  • stock_queue에 들어온 메시지를 소모하기 위한 stock_lambda 구성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
service: stock-lambda
frameworkVersion: '3'

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

functions:
  consumer:
    handler: index.consumer
    events:
      - sqs: arn:aws:sqs:ap-northeast-2:ID:stockQueue

plugins:
  - serverless-lift

SQS 이벤트가 발생하면 트리거 되어 lambda 함수 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const consumer = async (event) => {
    for (const record of event.Records) {
        const json = JSON.parse(record.body).MessageAttributes

        console.log(`필요데이터 : ${JSON.stringify(json)}`);
        console.log(`요청자 : ${json.MessageAttributeRequester.Value}`);
        console.log(`물건아이디 : ${json.MessageAttributeProductId.Value}`);
        console.log(`공장아이디: ${json.MessageAttributeFactoryId.Value}`);
        console.log(`수량: ${json.MessageAttributeProductCnt.Value}`);
};

module.exports = {
    consumer,
};
  • lambda 함수가 실행되면

cloudwatch-sqs

  • Cloudwatch에서 SQS를 통해 전송된 메시지 내용 확인이 가능하다.

Project 카테고리 내 다른 글 보러가기 🤠

댓글남기기