외로운 Nova의 작업실

aws - Lambda 본문

Cloud/aws

aws - Lambda

Nova_ 2023. 10. 26. 20:02

- Lambda

람다는 Fass 서비스입니다. 람다는 아래와 같은 동작을 수행합니다.

람다는 이벤트를 감지하여 아마존 리눅스 환경의 Micor VM을 띄우고 함수를 실행합니다. 그리고 결과를 처리합니다. 함수가 실행될때 필요한 환경이 있는데, 이것을 런타임이라고 합니다. 런타임은 어떤 언어로 작성하는지에 따라 다르며, 그 환경에 따라 성능 차이가 있습니다.

람다에는 하나의 큰 단점이 있는데, 이는 람다를 처음 시작하면 EC2인스턴스를 하나 만드는 것과 같이 Micro VM을 올리고 OS를 켜고 함수 실행환경을 구축하고 코드를 다운로드한다음 실행하여 느리다는 점입니다. 이를 Cold Start라고합니다.

 

이후 Micro VM이 유지되는 시간에 함수를 다시 실행하면 함수 실행환경만 구축하고 코드를 다운로드한다음 실행하는데 이는 조금 빠릅니다. 이를 Partial Cold Start라고합니다.

 

이러한 Cold Start를 줄이려면 지속적인 호출을 통해 구동되어 있는 Micro VM을 유지해야합니다.

 

 -Lambda 생성

람다 카테고리에 들어가줍니다.

함수 생성을 눌러줍니다.

파이썬으로 간단히 Hello world를 출력하는 람다를 생성해보겠습니다.

람다를 만들고 아래보게되면 코드가 작성되어 있습니다. 한번 테스트 해보겠습니다. Test 버튼을 눌러줍니다.

위처럼 설정후 저장을 눌러줍니다.

테스트 부분으로가서 테스트를 눌러보면 함수가 실행되며 그 결과값(Json)을 알 수 있습니다.

 

- Lambda에서 Lambda 실행

AWS Lambda_a를 만들고 Lambda_b가 호출하도록 하여 Lambda_a를 실행시켜보겠습니다.

Lambda_a를 생성합니다.

코드를 아래와 같이 변경해줍니다.

import json

def lambda_handler(event, context):
    # TODO implement
    print(event)
    return event

 

이제 Lambda_b를 생성해줍니다.

위와 같이 만들어줍니다. 그리고 코드를 아래와 같이 변경해줍니다.

import json
import boto3

def lambda_handler(event, context):
    # TODO implement
    payload = {}
    payload['Hello'] = 'hi'
    lan = boto3.client(service_name='lambda', region_name='ap-northeast-2')
    lan.invoke(FunctionName="Lambda_a", InvocationType='Event', Payload=json.dumps(payload))
    print(payload)
    return payload

이제 Lambd_b에게 권한을 부여해줍니다.

이후 Lambda_b를 실행시켜줍니다.

이제 Lambda_b의 로그를 확인하기 위해 CloudWatch로 이동해보겠습니다.

정확하게 실행한 로그가 기록되어있습니다.

 

- Lambda로 S3 실행

먼저 S3 버킷 리스트를 가져오는 Lambda를 만들어보겠습니다. 그러기전에 S3를 만들어보겠습니다.

 

버킷 2개를 만들어주겠습니다.

 

이제 Lambda를 만들어줍니다.

s3관련 권한을 역할에 넣어줍니다.

이제 아래와 같이 람다 코드를 작성해줍니다.

import json
import boto3
import botocore

def lambda_handler(event, context):
    # TODO implement
    s3 = boto3.resource('s3')
    bucket_list = []
    for bucket in s3.buckets.all():
        bucket_list.append(bucket.name)
        
    return json.dumps(bucket_list)

이제 테스트해줍니다.

버킷 리스트를 불러올 수 있습니다. 이제 파일을 하나 버킷에 넣어놓고 그 값을 가져와보겠습니다.

이제 이걸 불러오는 코드를 짜줍니다.

import json
import boto3
import botocore

def lambda_handler(event, context):
    # TODO implement
    bucket_name = 'serverless-study-bucket'
    key = 'hello.txt'
    
    s3_client = boto3.client('s3')
    
    data = s3_client.get_object(Bucket=bucket_name, Key=key)
    file_text = data['Body'].read()
    
    return json.dumps(file_text.decode('utf-8'))

이제 테스트해줍니다.

정상적으로 되는 것을 확인할 수 있습니다.

 

- Lambda와 SQS 연결

이번에는 Lambda를 사용해서 SQS에 메시지를 보내고 받아보겠습니다. 먼저 SQS를 만들어주겠습니다.

이제 SQS로 메시지를 보낼 Lambda를 생성해줍니다.

그리고 권한을 추가해줍니다.

이제 코드를 작성해줍니다.

import json
import boto3

def lambda_handler(event, context):
    # TODO implement
    sqs_client = boto3.client(
        service_name='sqs',
        region_name='ap-northeast-2'
        )
        
    response = sqs_client.send_message(
        QueueUrl='https://sqs.ap-northeast-2.amazonaws.com/396540618055/Serverless-SQS',
        MessageBody='from Lambda_sqs_sender'
        )
        
    print(json.dumps(response))
    return json.dumps(response)

이제 테스트해줍니다.

잘 되었음을 알 수 있습니다. SQS큐도 한번 봐보게습니다.

정상적으로 도착햇음을 알 수 있습니다. 이제 SQS 대기열에서 메시지를 받아서 사용해보겠습니다.

 

메시지를 받는 Lambda를 생성해줍니다.

권한을 추가해줍니다.

이제 코드를 작성해줍니다.

import json

def lambda_handler(event, context):
    # TODO implement
    print('event', event)
    print('context', context)
    return print(event)

이제 SQS에 트리거로 람다를 등록해줍니다.

트리거 추가를 눌러줍니다.

이대로 추가해줍니다.

그리고 CloudWatch에서보면 SQS메시지를 받은 것을 확인할 수 있습니다. 또한, 메시지 큐에서도 삭제처리를 자동으로 진행됩니다.

 

- Lambda와 DynamoDB 연동

DynamoDB를 만들어서 음악에 관한 테이블을 만들고 값을 넣고 조회, 수정하는 Lambda를 생성해보겠습니다. 먼저 DynamoDB를 만들어줍니다.

 

위처럼 DynamoDB를 생성해줍니다. 이제 Lambda를 생성해줍니다.

이제 역할 권한을 추가해줍니다.

이제 코드를 작성해줍니다.

import json
import boto3

from botocore.exceptions import ClientError


def put_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").put_item(
            Item={
                "yyyymmdd": yyyymmdd,
                "title": title,
                "info": {
                    "singer": singer,
                    "country": country
                }
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def lambda_handler(event, context):
    song_put_response = put_song(20120715, "gangnam style", "psy", "korea")

    return song_put_response

람다로 강남스타일에 대한 곡 정보를 넣어보겠습니다. 이제 테스트해줍니다.

실제 잘 들어갔는지 봐줍니다.

데이터가 잘 삽입되는 것을 확인할 수 있습니다. 이제 이 데이터를 수정보겠습니다. country의 값을 korea에서 south korea로 변경해보겠습니다. 아래는 코드입니다.

import json
import boto3

from botocore.exceptions import ClientError


def put_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").put_item(
            Item={
                "yyyymmdd": yyyymmdd,
                "title": title,
                "info": {
                    "singer": singer,
                    "country": country
                }
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def update_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").update_item(
            Key={"yyyymmdd": yyyymmdd, "title": title},
            UpdateExpression="SET info= :values",
            ExpressionAttributeValues={
                ":values": {"singer": singer, "country": country}
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def lambda_handler(event, context):
    # song_put_response = put_song(20120715, "gangnam style", "psy", "korea")
    update_response = update_song(20120715, "gangnam style", "psy", "south korea")

    return update_response

테스트해보겠습니다.

데이터가 업데이트 된 것을 확인할 수 있습니다. 이번엔 데이터를 가져오겠습니다.

아래는 코드입니다.

import json
import boto3

from botocore.exceptions import ClientError


def put_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").put_item(
            Item={
                "yyyymmdd": yyyymmdd,
                "title": title,
                "info": {
                    "singer": singer,
                    "country": country
                }
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def update_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").update_item(
            Key={"yyyymmdd": yyyymmdd, "title": title},
            UpdateExpression="SET info= :values",
            ExpressionAttributeValues={
                ":values": {"singer": singer, "country": country}
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def get_song(yyyymmdd, title):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").get_item(Key={"yyyymmdd": yyyymmdd, "title": title})
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def lambda_handler(event, context):
    # song_put_response = put_song(20120715, "gangnam style", "psy", "korea")
    # update_response = update_song(20120715, "gangnam style", "psy", "south korea")
    song_get_response = get_song(20120715, "gangnam style")

    return song_get_response

테스트해보겠습니다.

정상적으로 쿼리가 되는 것을 확인할 수 있습니다. 이제 데이터를 삭제해보겠습니다.

import json
import boto3

from botocore.exceptions import ClientError


def put_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").put_item(
            Item={
                "yyyymmdd": yyyymmdd,
                "title": title,
                "info": {
                    "singer": singer,
                    "country": country
                }
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def update_song(yyyymmdd, title, singer, country):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").update_item(
            Key={"yyyymmdd": yyyymmdd, "title": title},
            UpdateExpression="SET info= :values",
            ExpressionAttributeValues={
                ":values": {"singer": singer, "country": country}
            }
        )
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def get_song(yyyymmdd, title):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").get_item(Key={"yyyymmdd": yyyymmdd, "title": title})
    except ClientError as e:
        print(e.response["Error"]["Message"])
    else:
        return response


def delete_underrated_song(yyyymmdd, title):
    dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-2")

    try:
        response = dynamodb.Table("song").delete_item(
            Key={"yyyymmdd": yyyymmdd, "title": title}
        )
    except ClientError as e:
        if e.response["Error"]["Code"] == "ConditionalCheckFailedException":
            print(e.response["Error"]["Message"])
        else:
            raise
    else:
        return response


def lambda_handler(event, context):
    # song_put_response = put_song(20120715, "gangnam style", "psy", "korea")
    # update_response = update_song(20120715, "gangnam style", "psy", "south korea")
    # song_get_response = get_song(20120715, "gangnam style")
    delete_response = delete_underrated_song(20120715, "gangnam style")

    return delete_response

테스트해보겠습니다.

항목이 삭제된 것을 확인할 수 있습니다.

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

aws - 글로벌 사진 사이트 구축  (0) 2023.10.22
aws - CLI(추가 예정)  (1) 2023.10.21
aws - Elastic Transcoder  (2) 2023.10.21
aws - SQS  (0) 2023.10.21
aws - SNS  (0) 2023.10.20
Comments