Api Gateway

  • Security
  • Mediation
  • Traffic Management

기능

  1. Routing
    • 모바일과 PC 중 적절히 라우팅
    • Monolithic -> MSA 할 때 많이 사용
      • 마이그레이션 할 때 중요하게 사용
      • 마이그레이션 중 따로 뺀 api도 동작해야하기 때문
  2. Quota (할당량)
  3. Authentication (인증)
  4. Authorization (특정 권한 가진 사람만 접근)
  5. API Cache (반복 요청에 대해 API 게이트웨이의 캐시로부터 바로 반환)
  6. Logging - 로그 파일이 한 곳에 모임
  7. 모니터링
  8. 로드 밸런서와 다른 부분? : Mediation (중재)
    • 백엔드 api가 바뀌었을 때 클라이언트의 요청을 바꿔주는 기능
    • 클라이언트가 원하지 않는 속성을 지워주는 기능
    • 각 단계별(4단계)로 원하는 조건을 수행하도록 함
  9. json to xml, xml to json 가능
  10. gRPC (내부에서는 빠르게, 외부에는 API Gateway를 거쳐서 필요한 형식 json 등으로)
  11. API Gateway는 k8s와 통합이 시작되고 있음
    • 백엔드 서비스가 k8s 형식으로 배포될 때, 입구에서 API Gateway가 하나씩 던져주는 식으로 작동
  12. HTTP API vs REST API
    • HTTP API : 가격이 100만 건당 $0.90 ~ $1.00으로 싸지만, Validation, WAF, API Caching, loging 등을 지원하지 않음
    • REST API : 100만 건당 $1.51 ~ $3.50, HTTP API보다 다양한 기능을 제공
  13. WebSocket API - 요청을 받고 응답하는 REST API와는 다르게 클라이언트와 백엔드 간 양방향 통신 지원
    • 채팅, 알림, 실시간 대시보드에 사용됨
    • 3개의 기본 RouteKey를 가진다.
      1. $connect : 클라이언트가 연결을 요청했을 때
      2. $disconnect : 클라이언트가 연결을 끊었을 때
      3. $default : 클라이언트가 별도의 SelectionExpression을 지정하지 않았을 때

API Gateway vs ALB

  1. 확장성
    • API Gateway : 10000 RPS(requests per second) 가 제한
    • ALB : 제한 없음
  2. 신뢰성 및 가용성
    • API Gateway : 사용자가 관리할 필요 X
    • ALB : 사용자가 region 당 2개 이상의 AZ를 지정할 필요가 있음
  3. 타 서비스와 통합
    • API Gateway : Lambda 함수 이외에 DynamoDB, SQS, S3 등 HTTP 기반 서비스와 모두 통합 가능
    • ALB : Lambda, EC2, ECS, Cognito
  4. Routing
    • API Gateway : 경로 기반 라우팅 (클라이언트 요청 url 기반)
    • ALB : 규칙 기반 라우팅 (url 기반 + 요청자 host name, IP address, HTTP header, Request Type 등)
  5. 비용
    • API Gateway : 수신한 요청에 대해서만 부과
      • HTTP API : 100만 건당 $0.90 ~ $1.00
      • REST API : 100만 건당 $1.51 ~ $3.50
      • WebSockets : 100만 건당 $0.80 ~ $1.00, 연결 분당 0.25
    • ALB : 시간당 + 리소스 사용량당
      • 시간당 $0.0225
      • LCU(로드밸런서 용량 단위) 시간당 $0.008 - 참고

AWS Cloudfront

  • CloudFront는 전 세계적으로 정적, 동적인 웹 컨텐츠, 비디오 스트리밍 및 API를 안전하고 규모에 맞게 제공하는 CDN (Content Dilivery Network) 서비스이다.

  • 에지 로케이션이라고 하는 전세계 데이터 센터 네트워크를 통해 콘텐츠 제공

  • 에지 서버로 콘텐츠를 캐시하고 제공하면 시청자와 가장 가까운 위치에서 콘텐츠 제공

    • 에지 로케이션에서 컨텐츠를 캐싱함으로써 s3 버킷의 부하를 줄이고, 컨테츠 전달 시 사용자에게 빠른 응답
  • CloudFront 기능 : Origin Access Identity (OAI)

    • 해당 컨텐츠에 대한 액세스를 CloudFront 및 해당 작업으로 제한함.
  • 악의적 공격 보호 및 안정장치

    • AWS WAF / AWS Shield 통합

동영상 스트리밍

MediaConvert를 통해 S3 버킷 내에 hls 포맷으로 전환했다면 다음은
CloudFront를 통해 영상을 배포해야 한다.

  1. CloudFront 서비스 접속

  2. [Create Distribution] 클릭

  3. Web 형식과 RTMP 형식 중에서 고르라고 선택지를 주는데, RTMP 형식 사용하는 것이 아니면 Web 선택. (AWS CloudFront는 2021년부터 RTMP를 지원하지 않는다)

  4. 세부 세팅

    • Origin Domain Name : 원하는 S3 버킷 선택 -> Origin ID는 자동으로 입력된다.
    • Viewer Protocol Policy : HTTP and HTTPS
    • Allowed HTTP Method : GET, HEAD
    • Smooth Streaming : MS smooth streaming 사용한다면 Yes
    • Restrict Viewer Access : 접근 제한을 걸 때 사용하므로 No
    • Price Class : 전 세계의 edge를 사용할 지, 특정 리전의 edge를 사용할지.
    • Object Caching 항목의 Default TTl : Origin으로 요청이 전달되기 전에 CloudFront 캐시에 머무르는 시간 (기본값 86400 == 24시간 == 1일)
      • Invalidations 탭에서 Create Invalidation 버튼을 눌러 *로 Invalidate 요청을 생성하게 된다면, 캐시가 만료되기 이전에 새 콘텐츠를 받아올 수 있다.
        • 무효화(Invalidate) : Cloudfront의 엣지 로케이션에 저장된 파일의 캐시를 삭제하는 기능으로, 캐시가 삭제되면 엣지 로케이션이 origin으로부터 새 파일을 받아옴.
  5. http://d3kq9c1qyaz6nw.cloudfront.net/test.m3u8 혹은 내부에 폴더가 존재한다면
    http://d3kq9c1qyaz6nw.cloudfront.net/Test/Default/HLS/test.m3u8 과 같은 형식으로 CDN에 접근할 수 있다.

  6. video.js를 이용하여 hls에 접근할 수 있다.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <link
            href="https://unpkg.com/video.js/dist/video-js.css"
            rel="stylesheet"
        />
    </head>
    <body>
        <video
            id="my_video_2"
            class="video-js vjs-default-skin"
            controls
            preload="auto"
            width="640"
            height="360"
            data-setup="{}"
        >
            <source
                src="http://d2d8kokzpr29em.cloudfront.net/test/Default/HLS/test.m3u8"
                type="application/x-mpegURL"
            />
        </video>

        <script src="https://vjs.zencdn.net/7.2.3/video.js"></script>
        <script
            src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-media-sources/4.7.2/videojs-contrib-media-sources.min.js"
            integrity="sha512-utkFvaMvnpseOQ/4m1+/2zKYNh5r/FHUs5XZAds52wXbfMgeHvHg/3PFnou6DME2U7F2OkcPSM0AWQdYdPKAKg=="
            crossorigin="anonymous"
        ></script>
    </body>
    -->
</html>

How to use MediaConvert & Lambda & S3

  1. 인풋 s3 버킷 생성

  2. 아웃풋 파일을 담을 s3 버킷 생성

  3. s3의 [속성] 탭에 들어가서 정적 웹 사이트 호스팅 활성화 (박스에 index.html 추가)

  4. [권한] 탭에서 모든 퍼블릭 액세스 차단 해제

  5. CORS 구성에 들어가서 다음 내용 추가

    [
        {
            "AllowedHeaders": ["*"],
            "AllowedMethods": ["PUT", "POST", "DELETE"],
            "AllowedOrigins": ["http://www.example1.com"],
            "ExposeHeaders": []
        },
        {
            "AllowedHeaders": ["*"],
            "AllowedMethods": ["PUT", "POST", "DELETE"],
            "AllowedOrigins": ["http://www.example2.com"],
            "ExposeHeaders": []
        },
        {
            "AllowedHeaders": [],
            "AllowedMethods": ["GET"],
            "AllowedOrigins": ["*"],
            "ExposeHeaders": []
        }
    ]
  6. MediaConvert를 경유하기 위한 IAM Role 설정

    • IAM 서비스 접속
    • [역할 생성] 클릭
    • MediaConvert 클릭하고 [다음:검토] 나올 때까지 넘어가기
    • 이름에 MediaConvertRole 입력
    • [역할 생성] 클릭
    • [요약] 들어가서 ARN 값 저장해놓기 (다음 단계에 사용)
  7. Lambda를 위한 IAM Role 설정

  • VODLambdaRole이란 이름으로 IAM 역할 생성 / 역할 타입은 AWS Lambda
  • AWSLambdaBasicExecutionRole 정책을 attach (for CloudWatch logs permission) - [권한] 탭에서 [인라인 정책 추가] - [Json] 탭 클릭
  • 추가한 정책 내 [인라인 정책 추가]에 들어가서 [JSON] 누른 다음 내용 추가
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": "*",
                "Effect": "Allow",
                "Sid": "Logging"
            },
            {
                "Action": ["iam:PassRole"],
                "Resource": ["ARNforMediaConvertRole"],
                "Effect": "Allow",
                "Sid": "PassRole"
            },
            {
                "Action": ["mediaconvert:*"],
                "Resource": ["*"],
                "Effect": "Allow",
                "Sid": "MediaConvertService"
            },
            {
                "Action": ["s3:*"],
                "Resource": ["*"],
                "Effect": "Allow",
                "Sid": "S3Service"
            }
        ]
    }
  • ARNforMediaConvertRole라고 적힌 Resource 부분을 지우고 아까 저장했던 ARN 값으로 대체
  • 이름에 VODLambdaPolicy 입력하고 정책 생성
  1. 비디오 변환을 위한 Lambda 함수 작성

    • [Lambda 함수 생성] 클릭
    • Name에 VODLambdaConvert 입력
    • Python 3.8 입력
    • Role을 [기존 역할 선택] 누른 후 VODLambdaRole 선택
    • job.json convert.py를 다운 받아 zip으로 압축
    • 함수에서 Configuration 탭에 들어가 [zip 파일 업로드] 선택
    • 압축 파일을 업로드하고, handler를 convert.handler 로 수정
    • 환경 변수를 다음과 같이 입력
      • DestinationBucket = <outputput bucket name>
      • MediaConvertRole = arn:aws:iam::ACCOUNT NUMBER:role/MediaConvertRole
      • Application = VOD
  2. Lambda 함수 테스트 - test 이벤트에 다음 json 파일 추가

    {
        "Records": [
            {
                "eventVersion": "2.0",
                "eventTime": "2017-08-08T00:19:56.995Z",
                "requestParameters": { "sourceIPAddress": "54.240.197.233" },
                "s3": {
                    "configurationId": "90bf2f16-1bdf-4de8-bc24-b4bb5cffd5b2",
                    "object": {
                        "eTag": "2fb17542d1a80a7cf3f7643da90cc6f4-18",
                        "key": "vodconsole/TRAILER.mp4",
                        "sequencer": "005989030743D59111",
                        "size": 143005084
                    },
                    "bucket": {
                        "ownerIdentity": { "principalId": "" },
                        "name": "rodeolabz-us-west-2",
                        "arn": "arn:aws:s3:::rodeolabz-us-west-2"
                    },
                    "s3SchemaVersion": "1.0"
                },
                "responseElements": {
                    "x-amz-id-2": "K5eJLBzGn/9NDdPu6u3c9NcwGKNklZyY5ArO9QmGa/t6VH2HfUHHhPuwz2zH1Lz4",
                    "x-amz-request-id": "E68D073BC46031E2"
                },
                "awsRegion": "us-west-2",
                "eventName": "ObjectCreated:CompleteMultipartUpload",
                "userIdentity": { "principalId": "" },
                "eventSource": "aws:s3"
            }
        ]
    }
    • save이후 test를 눌렀을 때 200값이 반환되면 성공적으로 세팅됨
  3. Lambda 함수에 input S3 bucket을 트리거로 설정

    • trigger를 눌러 input S3 bucket을 연동하면 되며
    • 이벤트 같은 경우는 모든 객체 생성 으로 설정
    • prefix에 inputs/ 등을 입력하여 입력 폴더를 지정할 수도 있다.
    • 해당 s3 버킷에 영상을 업로드했을 때 output 버킷에 변환된 영상 디렉토리가 생성되면 성공적으로 MediaConvert가 작동 된 것임. CloudWatchMediaConvert의 Job list에서도 성공적으로 실행된 것을 확인 할 수 있다.

Reference

  • EC2에서는 컴퓨터 한 대를 인스턴스, S3에서는 버킷, Lambda에서는 함수라고 부름
  • Serverless 제품
  • 서버 프로비저닝 및 관리 없이 코드 실행
  • 사용량에 따라 지속적으로 백엔드에서 규모가 자동으로 지정되기 때문에 Scaling을 신경쓸 필요가 없다.
  • 높은 가용성 및 자동 복구
  • 1초에서 최대 15분(900초) 동안 실행하도록 함수를 구성할 수 있게 되어 있다.

사용 방법

  1. 함수 생성
  2. 새로 작성
    • 함수 이름
    • 런타임 : 어떤 언어로 할 것인지
def lambda_handler(event, context):
    return
  • lambda_handler는 약속된 이름의 함수. 람다를 실행했을 때 이 함수가 실행되도록 약속되어 있음.
  • save하고 Deploy 버튼을 눌러야 실행 가능한 상태가 된다.

콘솔에서 테스트

테스트 이벤트 선택(실행될 때 어떠한 값을 입력할 것인지) -> 테스트 이벤트 구성 -> 이름 입력 -> 생성 -> 테스트 -> 함수 실행

입력값

  • 테스트 이벤트 선택 -> 테스트 이벤트 구성 -> json {key: value} 형태로 입력값 입력 -> 생성
  • lambda_handler의 event parameter로 들어간다.

디버깅

  • CloudWatch에서 lambda 함수에 대한 로그를 확인할 수 있다.
  • 코드를 수정하면 새로운 log 스트림 안에 쌓이게 된다.

트리거

  • 다른 AWS 서비스(API 게이트웨이, DynamoDB, S3 등)와 연동되기 때문에 Lambda가 사용되는 것.
  • Trigger를 통해서 다른 서비스에서 변화가 생겼을 때 람다를 실행할 수 있다.
  • 데이터 변화, 직접 또는 endpoint 호출, 리소스 상태 변화, CloudWatch 알람, Cron 주기별

S3와 연동

  1. 트리거에 Bucket 지정 + 모든 객체 이벤트 유형(PUT, COPY 등) + 재귀호출
  2. S3의 속성에 이벤트 알림에 Lambda 함수 추가된 것 확인
  3. S3로 파일을 업로드
  4. CloudWatch에서 S3에서 Lambda로 전달한 event값 확인할 수 있음
  5. 테스트 이벤트 구성에 들어가서 해당 event값 붙여넣기 (json 형식을 지키기 위해서 작은따옴표를 큰따옴표로 변경 - JSON formatter & validator)
  6. 필요한 값 접근

실행 모델

  • 동기식 : Amazon API Gateway
  • 비동기식 : SNS, CloudWatch, S3
  • Stream-based : Kinesis, DynamoDB

성능 및 가격정책

  • 기본 설정에서 메모리 용량 높일 수 있고, 메모리에 비례하여 더 좋은 CPU가 할당된다.
  • 함수 요청 수와 기간에 따라 요금 청구
  • Lambda는 프리티어 무기한으로 제공. 프리티어는 월별 무료 요청 1백만 건 & 월별 400,000GB-초 컴퓨팅 시간
  • 초과가 될 경우 요청 백만 건당 0.20 USD
  • 1GB를 0.1초만큼 썻을 때 0.0000016667 USD
  • 요금 예제
    • 512MB 메모리, 1달에 3,000,000회 실행, 매번 1초간 실행 시 : 18.34 USD
    • 128MB 메모리, 1달에 30,000,000회 실행, 매번 200ms 실행 시 : 11.63 USD

Cold Start vs Warm Start

  • Lambda Function이 일정 기간 이상 실행되지 않을 경우 Stand-by 중인 컨테이너가 하나도 남지 않게 되어 호출 시 소요 시간이 증가됨 (Cold Start)
  • CloudWatch Time-based Event를 통해 주기적으로 Lambda Function을 실행하면, Lambda Function이 실행된 컨테이너가 항상 백엔드에 존재하게 되기 때문에 Cold Start를 방지할 수 있다.

Common issues and troubleshooting

실행이 안될 때 or 함수가 실패

  • CloudWatch log에 에러 확인
  • 이벤트 소스에서 lambda를 실행할 수 있는 function이 있는지 확인

함수 실행이 너무 오래 걸린다면

  • Cold Start - 여러 번 실행해보고 비교
  • 메모리 확장하여 시도 - CloudWatch log로 확인
  • 비효율적 작성 코드 - 로컬 테스트
  • Third Party, Dependency 시간 소요 - X-ray로 어떤 엔드포인트에서 얼마나 시간을 소요했는지 파악 가능

스로틀링

  • 리전별 1000개로 동시 실행 갯수 제한
  • 동기식 호출 스로틀링 : 429 에러
  • 비동기식 호출 스로틀링 : 6시간 동안 호출 재시도
  • 스트림 기반 : 최대 7일간 호출 재시도

Schedule 설정이 제대로 동작하지 않는 경우

  • CRON Expression 확인 (대한민국 표준시가 아니라 UTC 시간으로 되었는지)
  • Second level of precision을 지원하지 않음 (Lambda Function이 매일 23:00 UTC에 실행되도록 설정했다면, 23:00:00부터 23:00:59 사이에 실행된다)
  • 초단위 정밀 작업이 필요하다면 EC2, ECS를 사용하는 것을 추천

Reference

+ Recent posts