AWS

AWS Lambda Java With SnapStart

recent0 2024. 6. 24. 01:20

서론

AWS Lambda는 다양한 개발 언어를 지원하고 있습니다. 그 중 자바는 ColdStart가 다른 언어보다 유독 길어 선호하지 않고 있습니다. 이를 개선하기 위해서 나온 SnapStart 기능에 대해 소개시켜드리고, 그 전에 Lambda 개념에 대해서 정리하고자 합니다.

 

AWS Lambda

AWS Lambda란?

AWS Lambda는 AWS에서 제공하고 있는 서버리스 컴퓨팅 서비스입니다. 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 다는점이 특징입니다.

AWS Lambda의 장점

1. 관리 비용

AWS Lambda는 흔히 알고 있는 서버와 다르게 사용자가 관리하지 않고 AWS에서 서버와 운영체제 관리, 보안 패치 등을 대신 처리해주어 고가용성을 보장할 수 있기에 관리비용이 적습니다.

2. 필요할 때만 사용하기에 요금절감

EC2를 통해 API 서버를 띄워서 사용하는 것과는 다르게, Lambda는 필요할 때만 사용하여 요청 수와 실행시간 단위로 비용이 청구되기 때문에 다음과 같은 경우에 유용합니다.

  • 자주 사용 되지 않거나, 특정 기간 또는 주기로 실행되어야 하는 기능이 있는 경우
  • 서버를 띄우지 않고 간단한 기능들을 사용하고 싶은 경우(ex. 파일 관련 작업)

AWS Lambda의 단점

1. 실행 시간 & 메모리 제한

AWS Lambda 설정을 보면 실행시간, 메모리에 제한이 있는 것을 확인할 수 있습니다. 그렇기에 람다가 무거운 작업을 돌리기엔 적합하지 않습니다.

Lambda 제한

2. ColdStart

먼저 Lambda 실행 환경 수명 주기는 크게 INIT, INVOKE, SHUTDOWN 으로 이루어지는데, ColdStart는 INIT 단계로 인해 발생하게 됩니다.

출처 : https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/lambda-runtime-environment.html#runtimes-lifecycle

 

Lambda는 일정시간동안 요청이 없으면 인스턴스를 종료합니다. 그렇기에 Lambda가 종료된 이후, 다시 Lambda에 요청을 보내면 실행환경을 초기화하게 되는데 초기화하는 시간동안은 요청을 처리할 수 없습니다. 그래서 INIT 단계에 걸리는 시간을 ColdStart라고 합니다.

ColdStart 개선 방법

EventBridge Scheduler

람다는 보통 5~15분정도 사용하지 않으면 꺼지기 때문에, AWS EventBridge Scheduler를 이용해 일정 간격으로 요청을 보내 해결할 수 있습니다. 스케줄러는 다음과 같이 사용할 수 있습니다.

1. EventBridge 메뉴 

  • EvnetBridge 탭에서 Scheduler를 선택하여 일정 생성을 선택합니다.

스케줄러 생성

2. 일정 패턴 설정

  • AWS Lambda는 마지막 요청을 이후로 5~15분이 지나면 종료되므로, 5분 간격으로 이벤트를 발행 시키도록 설정합니다.

이벤트 발행 간격 설정

3. EventBridge 대상 설정

  • 이벤트 대상을 지정하고, 어떤 Lambda에 이벤트를 발행시킬지 선택하여 WarmStart 상태를 유지할 수 있습니다.

이벤트 대상 지정

Lambda Provisioned Concurrency

AWS Lambda는 자동으로 스케일링 되어 실행되는데, 사전에 예약 용량을 설정하면 설정한 용량만큼 인스턴스를 띄워서 ColdStart 문제를 방지할 수 있습니다. Provisioned Concurrency 설정은 다음과 같이 할 수 있습니다.

1. AWS Lambda에 대해 새 버전 발행

새 버전 발행

2. AWS Lambda 별칭 생성

별칭 생성

3. 프로비저닝된 동시성 설정

  • 생성한 별칭 정보에 들어가 구성 탭을 보면, 프로비저닝된 동시성을 편집할 수 있습니다.

별칭으로 생성된 AWS Lambda 구성

  • 편집을 눌러 프로비저닝된 동시성의 개수를 선택할 수 있습니다. 
  • 동시성 개수에는 계정마다 제한이 있고, 이를 해제하기 위해서는 Service Quatos에서 요청을 보내어 한도를 높일 수 있습니다.

프로비저닝된 동시성 설정

SnapStart For Java (자바 한정)

Java에서 ColdStart 시간의 주요 이유는 JIT 컴파일 과정때문입니다. 이를 해결하기 위해 AWS는 INIT 단계에서 발생하는 과정에 대해SnapShot을 생성하고, 이를 캐싱하여 ColdStart 시간을 줄일 수 있는 SnapStart 기능을 만들었습니다.

출처 : https://aws.amazon.com/ko/blogs/compute/starting-up-faster-with-aws-lambda-snapstart/

 

SnapStart를 사용하면 함수 버전을 게시할 때 Lambda가 함수를 초기화합니다. Lambda는 초기화된 실행 환경의 메모리 및 디스크 상태 Firecracker microVM 스냅샷을 생성하고, 스냅샷을 암호화하며 짧은 지연 시간으로 액세스할 수 있도록 스냅샷을 캐싱합니다.

 

SnapShot이 적용된 후 함수를 처음 호출하거나, 스케일 업되는 경우 실행 환경을 처음부터 초기화하는 대신 캐싱된 스냅샷에서 새 실행 환경을 재개하여 ColdStart를 개선할 수 있게 됩니다.

 

AWS Lambda 실행 환경 구성

SnapStart를 사용하기 전 다음과 같이 AWS Lambda를 구성했습니다.

1. FunctionInvoker, Function 함수형 인터페이스를 사용

  • RequestStreamHandler, RequesetHandler와 같은 인터페이스를 기반으로 Controller를 사용해 구현할 수도 있습니다.

 

// Lambda가 실행할 클래스 및 메서드
@Component
public class BeerHandler implements Function<RequestDto , ResponseDto> {

    @Override
    public ResponseDto apply(RequestDto requestEvent) {
        try {
            if (requestEvent.beerCount() < 0) {
                return new ResponseDto("NO BEER.....", -99);
            }
            return new ResponseDto("NICE BEER", requestEvent.beerCount() + 5);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

// LambdaHandler 클래스
import org.springframework.cloud.function.adapter.aws.FunctionInvoker;

public class LambdaHandler extends FunctionInvoker {

}

 

2. 런타임 설정

  • 작성한 BeerHandler를 실행시키기 위해 FunctionInvoker를 구현한 LambdaHandler의 패키지와 클래스명을 입력합니다.

런타임 구성

3. 환경변수 설정

  • 함수 클래스명, 메인 클래스에 대한 정보를 다음과 같이 입력합니다.

4. AWS Lambda API Gateway 연결

AWS Lambda의 함수 주소 그대로를 사용해도 좋지만, API Gateway를 활용했을 때 다음과 같은 장점이 있습니다.

  • REST API로 사용
  • 트래픽 관리
  • 캐싱 기능을 사용하여 불필요한 비용절감 

AWS Lambda는 다음과 같이 트리거를 추가하여 API GateWay를 간편하게 연결할 수 있습니다.

API Gateway 설정

람다 개선하기 with SnapStart

SnapStart 활성화

AWS Lambda 구성을 끝마치면, SnapStart 기능을 AWS Lambda 함수에 일반 구성에서 활성화 시킬 수 있습니다.

AWS Lambda 일반 구성

 

편집 버튼을 누르면 아래와 같이 PublishedVersions를 선택해 SnapStart 기능을 활성화 시킬 수 있습니다.

AWS Lambda SnapStart 활성화

 

기능을 활성화하면 새로운 람다버전을 배포하면 다음과 같이 SnapStart가 활성화 되어 있음을 확인할 수 있습니다.

SnapStart 최적화 상태 ON

SnapStart 성능 비교

SnapStart를 적용하지 않았을 때 시작시간은 3409ms 였고, SnapStart를 적용했을 때는 복원 기간+ 기간을 합쳐 1200ms로 개선된 것을 확인할 수 있습니다. 여기서 조금 더 개선이 필요하다면, 초기화 코드에서 클래스를 미리 로드해 추가적인 개선을 할 수 있습니다.

SnapStart 개선

SnapStart 문제점이나 고려해야할 점?

SnapStart 지원 범위

  • SnapStart는 Java 11, 17, 21을 지원합니다. 다른 관리형 런타임(예: nodejs20.x  python3.12), OS 전용 런타임, 컨테이너 이미지는 지원되지 않습니다.

고유성에 의존하는 상태 저장

  • 초기화 단계에서는 고유성을 보장받지 못하기 때문에, 핸들러 내에서 캐싱하는 것을 AWS에서 권장하고 있습니다.
import java.util.UUID;
  public class Handler implements RequestHandler<String, String> {
    private static UUID uniqueSandboxId = null;
    @Override
    public String handleRequest(String event, Context context) {
      if (uniqueSandboxId == null)
        uniqueSandboxId = UUID.randomUUID();
      System.out.println("Unique Sandbox Id: " + uniqueSandboxId);
      return "Hello, World!";
    }
  }

Lambda SnapStart 만료기간

  • 14일간 별다른 요청이 없는 경우에는 스냅샷을 삭제합니다.
  • 14일이 지난 후에 함수 버전을 호출하면 Lambda는 SnapStartNotReadyException 응답을 반환하고 새 스냅샷을 초기화합니다.

Lambda SnapStart와 프로비저닝된 동시성

  • SnapStart가 활성화된 버전의 Lambda를 사용하고 있으면 Provisioned Concurrency 기능을 사용할 수 없습니다.

SnapStart 기능이 활성화되어 있으면 Provision Concurrency 지원 x

 

 

여기까지 AWS Lambda, SnapStart에 대해서 알아봤습니다.

읽어주셔서 감사합니다.

'AWS' 카테고리의 다른 글

Route 53, DNS 그리고 레코드  (2) 2024.05.30
AWS VPC, CIDR, Bastion Host  (1) 2024.04.22