Notice
Recent Posts
Recent Comments
Link
«   2026/04   »
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
Archives
관리 메뉴

공돌이의 DevOps 도전기

마이크로서비스 본문

DevOps/TIL

마이크로서비스

Dozziny 2023. 5. 30. 11:14

 

 


1. Serverless framework를 이용하여 Lambda, SQS, SNS, IAM 생성
service: sales-api  # .yml file
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs14.x
  region: ap-northeast-2
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - sns:Publish
            - sns:ListSubscriptionsByTopic
            - sns:Unsubscribe
            - sns:Subscribe
          Resource: !Ref StockEmptyTopic

        - Effect: Allow
          Action:
            - sqs:SendMessage
            - sqs:ListQueueTags
            - sqs:Unsubscribe
            - sqs:Subscribe
            - sqs:ReceiveMessage
          Resource: !GetAtt StockQueue.Arn

        - Effect: Allow
          Action:
            - sqs:SendMessage
            - sqs:ListQueueTags
            - sqs:Unsubscribe
            - sqs:Subscribe
            - sqs:ReceiveMessage
          Resource: !GetAtt DeadLQ.Arn

resources:
  Resources:
    StockEmptyTopic:
      Type: AWS::SNS::Topic
      Properties:
        DisplayName: stock_empty

    StockQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: stock_queue
        RedrivePolicy:
          deadLetterTargetArn: !GetAtt DeadLQ.Arn
          maxReceiveCount: 3

    StockSnsSubscription:
      Type: AWS::SNS::Subscription
      Properties:
        Endpoint:
          Fn::GetAtt:
            - StockQueue
            - Arn
        Protocol: sqs
        TopicArn:
          Ref: StockEmptyTopic
   
    DeadLQ:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: DLQ

  Outputs:
    StockEmptyTopicArn:
      Value:
        Ref: StockEmptyTopic
      Export:
        Name: StockEmptyTopicArn
    StockQueueArn:
      Value:
        Ref: StockQueue
      Export:
        Name: StockQueueArn
    DeadLQArn:
      Value:
        Ref: DeadLQ
      Export:
        Name: DeadLQArn

functions:
  3rd-project:
    handler: handler.handler
    events:
      - httpApi: '*'
    environment:
      TOPIC_ARN:
        Ref: StockEmptyTopic
      STOCK_QUEUE_ARN:
        Fn::GetAtt:
          - StockQueue
          - Arn
  DLQ-lambda:
    handler: DLQ.handler
    events:
      - sqs:
          arn: !GetAtt DeadLQ.Arn

  stock-lambda:
    handler: stock-lambda.consumer
    events:
      - sqs:
          arn: !GetAtt StockQueue.Arn
Trouble shooting
  1. Serverless framework로 생성한 SQS를 Lambda에 연결할 경우 제대로 동작하지 않는 문제가 발생 함 (SQS의 SNS 구독 Arn, SNS의 Target SQS Arn 이 제대로 지정되어도 동작 안함)
    • 해결 : 각 서비스의 구독을 삭제한 후 메뉴얼로 다시 지정하니 제대로 동작 함 (Serverless Framework 자체 문제로 추측하였지만, 왜 framework로 생성했을 때 구동 안하는지는 해결하지 못함)
  2. SNS와 SQS의 권한 문제 
    • 해결 : IAM 설정(framework) 에서 문제 발생하는 권한을 하나씩 추가하여 해결 하였음
  3. DLQ 자체로는 Console Log를 확인 할 수 없기에 DLQ를 트리거하는 Lambda를 추가하여 DLQ로 제대로 메시지가 이동하는지 확인 하였음 (DLQ-lambda), 여기서도 1번 문제와 마찬가지로 SQS가 Serverless framework로 생성되었을 시 제대로 동작을 안하여 Triger와 Target을 메뉴얼로 지웠다가 다시 생성하였음

 

2. 데이터베이스의 재고를 증가시키는 Lambda 함수 생성
service: stock-increase-lambda   # .yml file
frameworkVersion: '3'

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

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

 

const serverless = require("serverless-http");    # handler.js
const express = require("express");
const app = express();
app.use(express.json())

const {
  connectDb,
  queries: { getProduct, increaseStock }
} = require('./database')

app.post("/product/donut", connectDb, async (req, res, next) => {
  const [ result ] = await req.conn.query(
    getProduct('CP-502101')
  )
  if (result.length > 0) {
    const product = result[0]
    console.log(req.body);
    const incremental = req.body.MessageAttributeProductCnt || 0 # stock
    console.log(incremental);

    await req.conn.query(increaseStock(product.product_id, incremental))
    return res.status(200).json({ message: `입고 완료! 남은 재고: ${product.stock + incremental}`});
  } else {
    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;
Trouble shooting
  1. 요청은 제대로 보냈지만 재고가 오르지 않는 문제
    • 해결 : 응답되는 body값을 console.log로 찍어보니,
더보기
    const incremental = req.body.stock || 0
    console.log(incremental);

body.stock  이 아니라 body.stockMessageAttributeProductCnt  로 날아옴,

const incremental = req.body.stock을 const incremental = req.body.MessageAttributeProductCnt로 변경하니 DB의 재고가 제대로 올라감


요구사항에 맞게 작성한 다이어그램

완성 다이어그램

 

 

 

회고

이번 프로젝트는 Code source가 충분히 제공 되어 Logic 구현보다 마이크로서비스 구현에 더 집중 할 수 있었다. (DB 등등) 프로젝트를 진행하면서 느낀것 중 하나가 생성하는 서비스의 이름을 최대한 간단명료하고 통일성 있게 지어야 해야할 필요성을 느꼈다. 어차피 프레임워크에서 만들어서 배포할건데 무슨 상관인가 했지만, 결국엔 AWS 콘솔로 들어가서 문제를 해결해야하는 상황이 오는데, 이 때 만들어놓은 이름들이 너무 중구난방이라 찾기 힘들었다... (최대한 간단하고 알아보기 쉽게!!)

아직 해결 못한 문제도 있고, 완벽히 이해하지 못한것도 있지만, 그래도 무수한 삽질과 재시도를 반복하다보니 이제는 간단한 아키텍쳐는 구현 할 수 있을것 같다 (역시 삽질과 반복을 해야 눈에 들어오고 손에 익는다...) 

 

'DevOps > TIL' 카테고리의 다른 글

AWS ECS 배포 자동화  (0) 2023.05.02
YAML 작성  (0) 2023.04.11
Nginx 를 이용한 Reverse Proxy 서버 작성  (0) 2023.04.10
WAS 실습  (0) 2023.04.05
Postman (Get, Post 요청)  (0) 2023.03.17
Comments