Project3 Day2 회고
카테고리: Project
태그: AWS lambda Serverless Project3
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 이었다.
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
) 생성
- lambda에서 대상 추가로 생성된 주제로 연결하여 SQS 대기열에 메세지를 연결 시킨다.
- cURL을 통해 재고가 없을 때까지 요청을 보냄
- 재고보다 많은 수량을 요청 하면 구매 실패 메시지가 뜨도록 구성.
- CloudWatch를 통해서도 확인 가능하다
Step 3 : 메시지를 Factory API로 전송하는 Lambda 구성 및 DLQ 추가
- 가용성을 높이기 위한 DLQ를 stock_queue에 연결
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를 통해 전송된 메시지 내용 확인이 가능하다.
댓글남기기