간단하게(?) WebSocket API, Lambda, DynamoDB를 사용해 서버리스 채팅 앱을 구축해보자..

https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/websocket-api-chat-app.html

해당 링크에서 cloudformation 템플릿으로 작업 후에 하나씩 살펴보자..


  • CloudFormation 생성

CloudFormation 템플릿

 

  • WebSocket API 생성

라우팅 선택 표현식 값으로 표현된 속성은 클라이언트가 API 호출할 때마다 전송되는 모든 메시지에 포함되어야 한다.

$request.body.action 의 경우, 클라이언트 요청의 body 내에 "action" 키에 mapping 된 값으로 route 한다는 의미!

 

다음으로 넘어가 $connect / $disconnect / $default 다 추가하기.

(요청과 일치하는 다른 경로가 없을 때 $default 경로를 호출)

통합 연결에서 Lambda 선택 후 각 각 맞는 함수를 넣어준다.

 

  • Test the chat API

wscat 유틸을 사용해 테스트 해보자

 

터미널 환경을 위해 cloud9을 열어주자... 2개를 만들 것!(메시지를 던지는 서버 1 / 메시지를 받는 서버 2)

wscat을 사용하기 위해선 npm이 필요!

npm -v
npm install -g wscat

publish 된 API endpoint에 연결

wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE}

api gateway의 대시보드를 보면 websocket url 알 수 있음..

위의 명령어 입력 시 connected 가 뜨면 연결 된 것..

DynamoDB에 connect Id 가 들어간 것을 볼 수 있음

sendMessage 함수 테스트를 위해 아래와 같은 JSON 메시지 전달 (cloud9 -1)

던진 메시지를 보기 위한 것..(cloud9 -2)

두 개의 터미널(cloud9 -1,2)에서 연결을 종료 시킨 뒤 다시 dynamoDB를 확인해보면...

 

이제 하나씩 다시 살펴보자!


일단 Lambda 함수들 먼저 보면

Connect / Disconnect / Default / sendMessage 이렇게 4개의 함수가 생성되어 있다.

(물론 모든 함수들은 트리거로 위에서 생성했던 API Gateway 잡혀있음!!)

  • ConnectHandler
const AWS = require('aws-sdk');
      const ddb = new AWS.DynamoDB.DocumentClient();
      exports.handler = async function (event, context) {
        try {
          await ddb
            .put({
              TableName: process.env.table,
              Item: {
                connectionId: event.requestContext.connectionId,
              },
            })
            .promise();
        } catch (err) {
          return {
            statusCode: 500,
          };
        }
        return {
          statusCode: 200,
        };
      };

DynamoDB 테이블에 connectId 값을 넣는 작업

 

  • DisconnectHandler
const AWS = require('aws-sdk');
      const ddb = new AWS.DynamoDB.DocumentClient();
      
      exports.handler = async function (event, context) {
        await ddb
          .delete({
            TableName: process.env.table,
            Key: {
              connectionId: event.requestContext.connectionId,
            },
          })
          .promise();
        return {
          statusCode: 200,
        };
      };

DynamoDB 테이블에 connectId 값에 해당되는 record 삭제

(따라서 위 두 함수의 역할에는 기본적인 Lambda + DynamoDB 에 접근할 수 있는 권한이 필요!)

 

  • DefaultHandler
const AWS = require('aws-sdk');

      exports.handler = async function (event, context) {
        let connectionInfo;
        let connectionId = event.requestContext.connectionId;
      
        const callbackAPI = new AWS.ApiGatewayManagementApi({
          apiVersion: '2018-11-29',
          endpoint:
            event.requestContext.domainName + '/' + event.requestContext.stage,
        });
      
        try {
          connectionInfo = await callbackAPI
            .getConnection({ ConnectionId: event.requestContext.connectionId })
            .promise();
        } catch (e) {
          console.log(e);
        }
      
        connectionInfo.connectionID = connectionId;
      
        await callbackAPI
          .postToConnection({
            ConnectionId: event.requestContext.connectionId,
            Data:
              'Use the sendmessage route to send a message. Your info:' +
              JSON.stringify(connectionInfo),
          })
          .promise();
      
        return {
          statusCode: 200,
        };
      };

잘못된 경로(?)로 들어오면... 들어오는 방법 설명!

 

  • sendMessageHandler
const AWS = require('aws-sdk');
      const ddb = new AWS.DynamoDB.DocumentClient();
      
      exports.handler = async function (event, context) {
        let connections;
        try {
          connections = await ddb.scan({ TableName: process.env.table }).promise();
        } catch (err) {
          return {
            statusCode: 500,
          };
        }
        const callbackAPI = new AWS.ApiGatewayManagementApi({
          apiVersion: '2018-11-29',
          endpoint:
            event.requestContext.domainName + '/' + event.requestContext.stage,
        });
      
        const message = JSON.parse(event.body).message;
      
        const sendMessages = connections.Items.map(async ({ connectionId }) => {
          if (connectionId !== event.requestContext.connectionId) {
            try {
              await callbackAPI
                .postToConnection({ ConnectionId: connectionId, Data: message })
                .promise();
            } catch (e) {
              console.log(e);
            }
          }
        });
      
        try {
          await Promise.all(sendMessages);
        } catch (e) {
          console.log(e);
          return {
            statusCode: 500,
          };
        }
      
        return { statusCode: 200 };
      };

메시지 주고 받게...

(위 두 함수들은 연결된 클라이언트들 호출을 위한 "execute-api:ManageConnections" 권한이 필요하다.)

 

❗ 근데.. 위는 정말 간단하게 메시지 주고 받는 거고... 실제로 사용할 땐 어떤 식으로 사용하는지 궁금하다... ❗

그리고 웹소켓 연결 후 주고받는 메시지들은 어떻게 관리가 되는지, 유실은 없는지 등의 궁금증이 생기네...?

'Cloud > AWS' 카테고리의 다른 글

[AWS] Serverless Service - Lambda 편 (2)  (0) 2022.11.05
[AWS] Serverless Service - Lambda 편 (1)  (0) 2022.11.05
[AWS] Lambda Warm Start / Cold Start  (0) 2022.10.28
[AWS] Fan-Out 시나리오 -1(easy)  (0) 2022.10.11
[AWS] Event-Driven Architecture  (0) 2022.10.11

제일 중요한(뇌피셜) 개념을 다뤄보려 한다..

사실 내가 이걸 먼저 보려고 했었는데...😂


Warm Start / Cold Start

Lambda 동작 순서

lambda code 작성 & 배포 → Load Code as .zip → Download to container → Bootstrap code(compile, load code to container) → run code

https://velog.io/@milkcoke/Lambda-Cold-start

(Bootstrap: 특정 언어에 대해 컴파일하여 기록하는 것)

 

Warm Start

  • 이미 실행 준비가 완료된 상태

 

Cold Start

  • 배포 패키지의 크기와 코드 실행 시간 및 코드의 초기화 시간에 따라 새 실행 환경으로 호출을 라우팅할 때 지연 시간이 발생
  • 쉽게 얘기하면 잠시 절전 모드의 컴퓨터를 키는 느낌 이랄까...
  • 발생 원인
    • 인스턴스 자체가 떠있지 않은 상황:
      • 컨테이너를 실행시키기 위해선 인스턴스가 활성화되어 있어야하는데 요청과 요청 사이의 간격이 너무 크거나, 최초의 요청이여서 인스턴스가 내려가있을 수 있다.
    • ENI 적용 시간:
      • Lambda도 결국엔 서버이다. 통신을 위해선 ENI가 컨테이너에 붙어야 한다. 특히, VPC를 사용하는 Lambda의 경우 반드시 적용된다.
      • 예를 들면, DB와 연결할 때, DB는 내부 서버에게만 열어야하기 때문에..
      • 이를 해결하려면 VPC + ENI의 성능을 향상시켜야 한다!
    • Dwell Time:
      • lambda 구조에서도 봤듯이 요청이 들어오면 컨테이너로 바로 들어가는게 아니라 큐에 쌓이게 된다.
      • 큐에서 요청을 꺼내 컨테이너로 보내는 시간: Dwell Time
      • 이 시간은 언제 길어질까?
        • 한 계정에 동시에 띄울 수 있는 최대 컨테이너 수(Max Concurrent Executions)는 제한되어 있음
        • 요청이 엄청 들어왔다고 가정했을 때, 컨테이너가 어떻게 증가할까?
          • 아마 컨테이너가 하나씩 선형적으로 증가하는 그림은 아닐듯
        • 한 계정에는 하나의 서비스를 만들기 위해 여러 종류의 Lambda를 사용하게 된다. 각 Lambda에서 생성될 수 있는 컨테이너 수를 제한하는데(Reserved Concurrent Executions) 이 설정보다 많은 요청이 동시에 들어오면 Throttle 발생!

 

Cold Start 해결 방법

  • Lambda 메모리 늘리기:
    • 메모리를 올리면 인스턴스의 사양(cpu)이 올라가 처리 속도 자체가 빨라질 수 있다고 한다.
    • but, 비용 고민: (메모리별 가격) * (요청이 처리되는 시간) * (요청 수)
    • 메모리가 올라가 요청이 처리되는 시간이 줄어들 수도 있고 그냥 메모리만 올라가면 음... 계산기 잘 두드려라
  • lambda 컨테이너 재사용:
    • 한번 호출되고, 다음 호출이 5분 이내인 경우 그 후속 호출에 컨테이너 재사용
    • 자체적인 Warm Start 구성이라고 생각해도 될듯?
    • 여기서 꼼수를 쓰자.. 요청 없어도 5분마다 강제 실행을 시키는 것!
      • CW 활용, Route 53 HealthCheck를 람다 API Gateway Endpoint 설정 등...
      • but, 쓸데 없는 지출이 증가됨
    • 시간이 오래 걸리는 코드는 global로 선언하는 게 좋다
      • 재사용할 때 돌아가지 않도록!
      • 예를들면 db_connection과 같은 작업?
더보기

warm-cold-start-test func

let isWarmStart = false;

exports.handler = async () => {
  let message;
 
  if (isWarmStart) {
    message = "warm start";
  } else {
    message = "cold start";
    isWarmStart = true;
  }
 
  return {
    statusCode: 200,
    body: JSON.stringify({ message }),
  };
};

그냥 아주 단순한 코드.. global로 isWarmStart 변수 선언하고 handler 실행되면 true로 값 바꿈.

처음에 실행한 결과값

그 이후 두번째 실행한 결과값

 

일정 시간 뒤에 다시 실행해보면 cold start를 다시 출력할 것이다..

 

'Cloud > AWS' 카테고리의 다른 글

[AWS] Serverless Service - Lambda 편 (1)  (0) 2022.11.05
[AWS] API Gateway - Websocket API  (0) 2022.11.01
[AWS] Fan-Out 시나리오 -1(easy)  (0) 2022.10.11
[AWS] Event-Driven Architecture  (0) 2022.10.11
[AWS] Lambda Layer  (0) 2022.10.07

1편에서 장치 설치 하고 오기!

https://realyun99.tistory.com/153

이어서 진행해보자..


Kinesis Data Streams

  • 스트림 생성

 

DynamoDB

  • DB 생성

 

Lambda

  • IAM 역할 생성 - Lambda

  • IAM 역할 생성 - IoT

권한의 경우 알아서 추가해줌.. 그대로 진행하면 됨

 

  • Lambda 함수 생성 및 트리거 추가

역할의 경우 위에서 만들었던 IAM Lambda 역할을 지정해주자.

 

다음으로 트리거 추가를 하자. 먼저 Kinesis!

함수에 코드를 추가해주자.. 추가 후에 꼭 Deploy 버튼 누르기!!!!!!

더보기
from __future__ import print_function
import base64
import boto3
from boto3.dynamodb.conditions import Key, Attr
import json
import os
import traceback

#-----Dynamo Info change here------
TABLE_NAME = os.environ.get('TABLE_NAME', "default")
DDB_PRIMARY_KEY = "deviceid"
DDB_SORT_KEY = "timestamp"
DDB_ATTR = "temp"
#-----Dynamo Info change here------

dynamodb = boto3.resource('dynamodb')
table  = dynamodb.Table(TABLE_NAME)

'''
This Kinesis data(Json Image) is below
{
    "DEVICE_NAME": $device_name,
    "TIMESTAMP": $TimeStamp(yyyy-mm-ddThh:MM:SS),
    "HUMIDITY" : int,
    "TEMPERATURE" : int
}
'''
def checkItem(str_data):
    try:
        #String to Json object
        json_data = json.loads(str_data)
        # adjust your data format
        resDict = {
            DDB_PRIMARY_KEY:json_data['DEVICE_NAME'],
            DDB_SORT_KEY:json_data['TIMESTAMP'],
            "HUMIDITY": json_data['HUMIDITY'],
            "TEMPERATURE": json_data['TEMPERATURE']

        }
        print("resDict:{}".format(resDict))
        return resDict

    except Exception as e:
        print(traceback.format_exc())
        return None

def writeItemInfo(datas):
    ItemInfoDictList = []
    try:
        for data in datas:
            itemDict = checkItem(data)
            if None != itemDict:
                ItemInfoDictList.append(itemDict)
            # if data does not have key info, just pass
            else:
                print("Error data found:{}".format(data))
                pass

    except Exception as e:
        print(traceback.format_exc())
        print("Error on writeItemInfo")

    return ItemInfoDictList

def DynamoBulkPut(datas):
    try:
        putItemDictList = writeItemInfo(datas)
        with table.batch_writer() as batch:
            for putItemDict in putItemDictList:
                batch.put_item(Item = putItemDict)
        return

    except Exception as e:
        print("Error on DynamoBulkPut()")
        raise e

def decodeKinesisData(dataList):
    decodedList = []
    try:
        for data in dataList:
            payload =  base64.b64decode(data['kinesis']['data'])
            print("payload={}".format(payload))
            decodedList.append(payload)

        return decodedList

    except Exception as e:
        print("Error on decodeKinesisData()")
        raise e

#------------------------------------------------------------------------
# call by Lambda here.
#------------------------------------------------------------------------
def lambda_handler(event, context):
    print("lambda_handler start")

    try:
        print("---------------json inside----------------")
        print(json.dumps(event))
        encodeKinesisList = event['Records']
        print(encodeKinesisList)
        decodedKinesisList = decodeKinesisData(encodeKinesisList)
        # Dynamo Put
        if 0 < len(decodedKinesisList):
            DynamoBulkPut(decodedKinesisList)
        else:
            print("there is no valid data in Kinesis stream, all data passed")

        return

    except Exception as e:
        print(traceback.format_exc())
        # This is sample source. When error occur this return success and ignore the error.
        raise e

 

환경 변수 지정을 위해 설정을 들어가자 (구성 → 환경변수)

DynamoDB 테이블을 넣어주자

 

IoT Core 확인

  • 메시지 라우팅 규칙 생성

(메시지 라우팅 → 규칙)

from 뒤에는 아까 생성했던 디바이스의 topic을 넣어준다.

 

IoT와 Kinesis를 연결해준다. IoT 디바이스에서 데이터를 받아와 Kinesis로 흐르게

Role도 아까 생성했던 iot 역할로 지정해준다.

 

현재 iot 디바이스 연결도 잘 되어 있는 것을 볼 수 있음.

 

  • Kinesis Stream 모니터링

또, 위에서 연결했던 Kinesis의 모니터링을 보면 데이터가 잘 들어오는 것을 볼 수 있다.

(지표들 중에서 GetRecords - 합계 | PutRecords - 합계 값이 0이 아닌지 확인)

시간이 좀 지나야 해당 그래프를 볼 수 있음...!

  • DynamoDB 모니터링

라이브 항목 수 가져오기 클릭

항목 탐색을 확인해보자.

 

  • Lambda 모니터링

(Invocations 그래프가 끝에 떨어지는 모양은 내가 cloud9 실행을 멈췄기 때문/ 스크립트 계속 돌리면 그래프 유지됨.)

 

API 용 Lambda 구성

  • Lambda 함수 만들기

해당 코드를 넣어준다.(Deploy 클릭)

더보기
from __future__ import print_function
import boto3
from boto3.dynamodb.conditions import Key
import datetime
import json
import traceback
import os

#-----Dynamo Info change here------
TABLE_NAME = os.environ.get('TABLE_NAME', "default")
DDB_PRIMARY_KEY = "deviceid"
DDB_SORT_KEY = "timestamp"
#-----Dynamo Info change here------

dynamodb = boto3.resource('dynamodb')
table  = dynamodb.Table(TABLE_NAME)

#------------------------------------------------------------------------
def dynamoQuery(deviceid, requestTime):
    print("dynamoQuery start")
    valList = []
    res = table.query(
        KeyConditionExpression=
            Key(DDB_PRIMARY_KEY).eq(deviceid) &
            Key(DDB_SORT_KEY).lt(requestTime),
            ScanIndexForward = False,
            Limit = 30
        )

    for row in res['Items']:
        val = row['TEMPERATURE']
        itemDict = {
            "timestamp":row['timestamp'],
            "value":int(val)
        }
        valList.append(itemDict)

    return valList

#------------------------------------------------------------------------
# call by Lambda here.
#  Event structure : API-Gateway Lambda proxy post
#------------------------------------------------------------------------
def lambda_handler(event, context):
    #Lambda Proxy response back template
    HttpRes = {
        "statusCode": 200,
        "headers": {"Access-Control-Allow-Origin" : "*"},
        "body": "",
        "isBase64Encoded": False
    }

    try:
        print("lambda_handler start")
        print(json.dumps(event))

        # get Parameters
        pathParameters = event.get('pathParameters')
        deviceid = pathParameters["deviceid"]
        requestTime = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

        resItemDict = { deviceid : ""}
        resItemDict[deviceid] = dynamoQuery(deviceid, requestTime)
        HttpRes['body'] = json.dumps(resItemDict)

    except Exception as e:
        print(traceback.format_exc())
        HttpRes["statusCode"] = 500
        HttpRes["body"] = "Lambda error. check lambda log"

    print("response:{}".format(json.dumps(HttpRes)))
    return HttpRes

위에서 했던 것과 같이 DynamoDB 환경변수를 넣어준다.

 

API Gateway

  • REST API 생성

(작업 → 리소스 생성)

(/datas 클릭 후 리소스 생성)

리소스 경로 괄호에 주의하라

(/deviceid에서 매서드 생성)

권한 추가는 확인을 클릭해준다.

위와 같은 화면이 구성되면 완료.

(작업 → CORS 활성화)

/{deviceid} 에서 cors 활성화!

(작업 → API 배포)

/{deviceid} 에서 api 배포를 진행하자.

생성된 url을 복사해두자.

 

DrawGraph.zip을 받고

(js/createGraph.js 파일)

첫번째 줄 device_name에 만들었던 디바이스 입력

두번째 줄 hosturl에 api url 입력

 

다운받았던 폴더에서 html 브라우저에서 실행하면

다음과 같은 그래프가 나오면 성공이다.(해당 그래프 나올 때까지의 시간이 걸릴 수 있음!)

위의 값은 DynamoDB에 저장된 디바이스의 Temperature값을 표시한다.

 

 

❗ 다음엔 실시간 시각화 OpenSearch를 사용해보자. ❗

참고: https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-example.html

 

게임데이 준비하면서 해본 간단한 실습!


  • S3 버킷 생성 및 샘플 객체 업로드

그냥 하고 싶은대로 설정 후 원하는 파일 아무거나 업로드하면 된다.

 

  • Lambda 함수 생성

function blueprint를 사용해 생성할 예정..

샘플 코드를 활용한다고 생각하면 된다!

python으로 진행

위에서 생성했던 버킷으로 트리거를 설정한다.

Amazon S3 가 함수를 호출할 수 있도록 함수의 리소스 기반 정책을 수정하자.

역할 문서를 확인해보자. S3 관련한 정책을 허용하는 내용이 잘 들어가있는지 확인한다.

트리거가 잘 잡혔는지 확인해보자..(나는 위처럼만 하면 트리거 추가가 안되서.. 따로 추가 다시 해줌..)

 

  • Lambda Test

아래 JSON 코드에서 S3 버킷 이름(examplie-bucket)과, 객체 키(test%2Fkey)를 테스트 파일 이름(버킷 안 파일)으로 바꿔준다.

해당 이벤트로 설정 후에 테스트를 해보면

다음과 같이 결과를 얻을 수 있다.

 

  • S3 Trigger Test

S3 버킷에 파일을 업로드할 때 함수를 호출한다.

따라서 파일 업로드를 몇 개 하고 Lambda의 모니터링을 확인해보면

Invocations 그래프의 숫자는 S3 버킷에 업로드한 파일의 수와 일치해야한다.

cloudwatch 로그에서도 확인 가능하다.

  • IAM 역할 생성(AWS 서비스 - Lambda에 연결할 예정)

위처럼 해당 정책들을 연결해준 역할을 생성한다. (나중에 Lambda에 연결할 것..)


  • Lambda 함수 생성

위에서 생성했던 역할을 연결해준 후 함수 생성!


  • Lambda에 MySQL 종속성 지원

로컬 상에서 작업하면 된다.(Window의 경우 cmd에서 작업)

나는 로컬 C에 test 폴더를 생성해주고 그 안에서 작업했다.

cd C:\test
# 초기화 설정은 원하는대로 (나는 default로 진행함)
npm init
npm install --save mysql

해당 명령어들을 차례로 입력하면 아래와 같이 생성된다.

파일들을 zip으로 묶어준다.(test.zip)

생성했던 lambda 함수에 zip파일을 올려준다.

위와 같이 올리면 완료!


  • RDS 생성

해당 설정들 중 마스터 사용자 이름, 마스터 암호는 잘 기억을 해두자!

나머지 설정들은 원하는대로 설정한 뒤 생성하면 된다.

(나의 경우: 인스턴스 클래스는 t3.micro / 스토리지 gp2, 자동 조정 비활성화 / 대기 인스턴스 생성 안하게 / 기본 vpc / 데이터베이스 암호 인증 / 자동 백업 비활성화 등..)

아! 지금은 간단하게 테스트 용 DB라 퍼블릭 액세스는 허용으로 진행했다.(뒤에 Workbench랑 쉽게 연결하려고...)

해당 RDS 생성에는 시간이 걸린다. 여유롭게 기다리자! (참고로 RDS 생성 뒤 엔드포인트가 필요하다.. 복사해두자!)


  • Lambda와 RDS Connection Test

먼저 lambda에 index.js 파일을 생성해줄 차례다.

//index.js
const mysql = require('mysql'); 
const connection = mysql.createConnection({ 
//following param coming from aws lambda env variable 

  host: process.env.RDS_LAMBDA_HOSTNAME,  
  user: process.env.RDS_LAMBDA_USERNAME, 
  password: process.env.RDS_LAMBDA_PASSWORD, 
  port: process.env.RDS_LAMBDA_PORT, 
  // calling direct inside code  
  connectionLimit: 10,   
  multipleStatements: true,
 // Prevent nested sql statements 
  connectionLimit: 1000,   
connectTimeout: 60 * 60 * 1000, 
  acquireTimeout: 60 * 60 * 1000, 
  timeout: 60 * 60 * 1000, 
  debug: true 
});

exports.handler = async (event) => { 
  try {    
 const data = await new Promise((resolve, reject) => {
       connection.connect(function (err) {   
      if (err) {      
     reject(err);     
    }        
 connection.query('CREATE DATABASE testdb', function (err, result) {  
         if (err) {  
           console.log("Error->" + err);     
        reject(err);        
   }         
  resolve(result);  
       });     
  })  
   }); 
    return { 
      statusCode: 200,  
     body: JSON.stringify(data)   
  } 
  } catch (err) {    
 return {   
    statusCode: 400,   
    body: err.message 
    } 
  }
 };

해당 환경변수를 알맞게 설정한다.(HOSTNAME은 RDS의 엔드포인트)

해당 코드를 Deploy한 뒤에 Test를 진행한다.

저장 후에 Test 버튼을 누르면 다음과 같은 결과를 얻을 수 있다.(DB 정보에 대한 내용..)

MySQL Workbench에 rds를 연결해 확인해보면 아래와 같이 테이블이 생성되어있음을 볼 수 있다. (위의 코드단에 DB 테이블 생성 관련 코드 있음.)


  • api test (event 생성)

아래의 코드를 Workbench를 통해 DB에 적용시켜라.

use testdb; 

CREATE TABLE `Employee` ( 
  `emp_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  `emp_name` varchar(100) DEFAULT NULL,      PRIMARY KEY (`emp_id`)    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
insert into Employee values(1,'Vaquar khan'); 
insert into Employee values(2,'Zidan khan');

위와 같이 테이블 생성과 데이터 삽입이 잘 이루어진 것을 확인하자.

다음으로 다시 Lambda로 돌아와 index.js에 코드를 변경해주자.

const mysql = require('mysql'); 
const connection = mysql.createConnection({ 
//following param coming from aws lambda env variable 

  host: process.env.RDS_LAMBDA_HOSTNAME,  
  user: process.env.RDS_LAMBDA_USERNAME, 
  password: process.env.RDS_LAMBDA_PASSWORD, 
  port: process.env.RDS_LAMBDA_PORT, 
  // calling direct inside code  
  connectionLimit: 10,   
  multipleStatements: true,
 // Prevent nested sql statements 
  connectionLimit: 1000,   
connectTimeout: 60 * 60 * 1000, 
  acquireTimeout: 60 * 60 * 1000, 
  timeout: 60 * 60 * 1000, 
  debug: true,
  database:'testdb'
});

exports.handler = async (event) => { 
  try {    
 const data = await new Promise((resolve, reject) => {
       connection.connect(function (err) {   
      if (err) {      
     reject(err);     
    }        
 connection.query('use testdb', function (err, result) {  
         if (err) {  
           console.log("Error->" + err);     
        reject(err);        
   }         
  resolve(result);  
       });     
  })  
   }); 
    return { 
      statusCode: 200,  
     body: JSON.stringify(data)   
  } 
  } catch (err) {    
 return {   
    statusCode: 400,   
    body: err.message 
    } 
  }
 }; 

 exports.handler = (event, context, callback) => {  
   console.log('inside lambda...'+event.emp_id) 
  // allows for using callbacks as finish/error-handlers 
  context.callbackWaitsForEmptyEventLoop = false; 
  const sql = "select * from Employee where emp_id = " + event.emp_id;  
  connection.query(sql, function (err, result) {   
  if (err) throw err; 
    callback(null, result)
   }); 
};

새로운 테스트 이벤트를 만들어준다.

{ "emp_id":1, "emp_name":"xyz" }

코드를 테스트 해보면

이와 같은 결과를 얻을 수 있다.

 

밑작업은 끝났고 API Gateway를 생성하자.

나는 REST API를 생성할 것이다.

API 생성 후에 메서드 GET도 생성해준다.

GET을 선택하고 체크 표시를 선택하면 다음과 같은 화면을 볼 수 있다. 아까 생성한 Lambda 함수 이름을 넣고 저장하자.

권한 부여도 한다고 해주자.. 그 뒤에 다시 작업에서 API 배포를 해주자!

함수를 다시 테스트 해보면

이와 같은 트리거가 추가된 것을 볼 수 있다.

 

❗ 확인이 필요...ㅠ ❗

근데, API URL로 확인(Postman)해보면 에러 뜨네...? 왜그럴까?

→ 위의 코드단에서 수정이 필요할 듯.. const sql = " 쿼리문 " 이 부분을 인식을 못하는 것 같다...?

'Cloud > AWS' 카테고리의 다른 글

[AWS] Mobile Backend 구성  (1) 2022.09.08
[AWS] AWS Amplify -1(Amplify Studio)  (0) 2022.09.07
[AWS] CloudFront 사용 이유  (0) 2022.08.29
[AWS] CloudFront와 Route 53 연결  (0) 2022.08.29
[AWS] CloudFront 배포  (0) 2022.08.29

+ Recent posts