Lambda 기반 애플리케이션 설계 원칙
잘 설계된 이벤트 중심 애플리케이션은 AWS 서비스 및 사용자 지정 코드의 조합을 사용하여 요청과 데이터를 처리 및 관리합니다. 이 장에서는 애플리케이션 설계에서 Lambda 관련 주제에 중점을 둡니다. 사용량이 많은 프로덕션 시스템에 대한 애플리케이션을 설계하는 경우 서버리스 아키텍트에게 중요한 고려 사항이 많이 포함되어 있습니다.
소프트웨어 개발 및 분산 시스템에 적용되는 많은 모범 사례가 서버리스 애플리케이션 개발에도 적용됩니다. 전반적인 목표는 다음과 같은 워크로드를 개발하는 것입니다.
-
신뢰성-최종 사용자에게 높은 수준의 가용성을 제공합니다. AWS 서버리스 서비스는 장애와 관련하여 설계되었기 때문에 안정적입니다.
-
내구성-워크로드의 내구성 요구 사항을 충족하는 스토리지 옵션을 제공합니다.
-
보안-모범 사례를 따르고 제공된 도구를 사용하여 워크로드에 대한 액세스를 보호하고 영향을 받는 반경을 제한합니다.
-
성능-컴퓨팅 리소스를 효율적으로 사용하고 최종 사용자의 성능 요구 사항을 충족합니다.
-
비용 효율성-과도한 지출 없이 규모를 조정할 수 있어 불필요한 비용을 방지하고 상당한 오버헤드 없이 해체할 수 있는 아키텍처를 설계합니다.
다음 설계 원칙은 이러한 목표를 충족하는 워크로드를 구축하는 데 도움이 될 수 있습니다. 모든 아키텍처에 모든 원칙이 적용되는 것은 아니지만 일반적인 아키텍처 결정에 도움이 될 수 있습니다.
주제
사용자 지정 코드 대신 서비스 사용
서버리스 애플리케이션은 일반적으로 Lambda 함수에서 실행되는 사용자 지정 코드와 통합된 여러 AWS 서비스로 구성됩니다. Lambda는 대부분의 AWS 서비스와 통합할 수 있지만 서버리스 애플리케이션에서 가장 일반적으로 사용되는 서비스는 다음과 같습니다.
범주 | AWS 서비스 |
---|---|
컴퓨팅 |
AWS Lambda |
데이터 스토리지 |
Amazon S3 Amazon DynamoDB Amazon RDS |
API |
Amazon API Gateway |
애플리케이션 통합 |
Amazon EventBridge Amazon SNS Amazon SQS |
오케스트레이션 |
AWS Step Functions |
스트리밍 데이터 및 분석 |
Amazon Data Firehose |
분산 아키텍처에는 직접 빌드하거나 AWS 서비스를 사용하여 구현할 수 있는 잘 정립된 일반적인 패턴이 많이 있습니다. 대부분의 고객에게는 이러한 패턴을 처음부터 개발하는 데 시간을 투자할 상업적 가치가 거의 없습니다. 애플리케이션에 이러한 패턴 중 하나가 필요한 경우 해당 AWS 서비스를 사용합니다.
패턴 | AWS 서비스 |
---|---|
대기열 |
Amazon SQS |
이벤트 버스 |
Amazon EventBridge |
게시/구독(팬아웃) |
Amazon SNS |
오케스트레이션 |
AWS Step Functions |
API |
Amazon API Gateway |
이벤트 스트림 |
Amazon Kinesis |
이러한 서비스는 Lambda와 통합되도록 설계되었으며 코드형 인프라(IaC)를 사용하여 서비스에서 리소스를 생성 및 취소할 수 있습니다. 애플리케이션을 설치하거나 서버를 구성하지 않고도 AWS SDK
Lambda 추상화 수준 이해
Lambda 서비스는 Lambda 함수를 실행하는 기본 운영 체제, 하이퍼바이저 및 하드웨어에 대한 액세스를 제한합니다. 이 서비스는 인프라를 지속적으로 개선하고 변경하여 기능을 추가하고 비용을 절감하며 서비스의 효율성을 높입니다. 코드에서는 Lambda의 설계 방식에 대한 자식이 없으며 하드웨어 선호도도도 높지 않다고 가정해야 합니다.
마찬가지로 Lambda의 통합은 소수의 구성 옵션만 공개한 상태로 AWS에서 관리합니다. 예를 들어 API Gateway와 Lambda가 상호 작용할 때는 서비스에서 완전히 관리하므로 로드 밸런싱 개념이 없습니다. 또한 언제든지 함수를 간접 호출할 때 서비스가 사용하는 가용 영역
이 추상화를 통해 애플리케이션의 통합 측면, 데이터 흐름, 워크로드가 최종 사용자에게 가치를 제공하는 비즈니스 로직에 집중할 수 있습니다. 서비스에서 기본 메커니즘을 관리하도록 허용하면 유지 관리할 사용자 지정 코드가 적어 애플리케이션을 더 빠르게 개발할 수 있습니다.
함수에서 상태 비저장 구현
Lambda 함수를 빌드할 때 환경이 단일 간접 호출에만 존재한다고 가정해야 합니다. 함수는 처음 시작할 때 필요한 상태를 초기화해야 합니다. 예를 들어 함수에서 DynamoDB 테이블에서 데이터를 가져와야 할 수 있습니다. 나가기 전에 Amazon S3, DynamoDB 또는 Amazon SQS와 같은 지속적인 저장소로 영구적인 데이터 변경을 커밋해야 합니다. 기존 데이터 구조나 임시 파일 또는 여러 간접 호출로 관리되는 내부 상태에 의존해서는 안 됩니다.
데이터베이스 연결 및 라이브러리 또는 로드 상태를 초기화하려면 정적 초기화를 활용할 수 있습니다. 실행 환경은 성능을 개선하기 위해 가능한 경우 재사용되므로 여러 간접 호출을 통해 이러한 리소스를 초기화하는 데 걸리는 시간을 일부 분할할 수 있습니다. 그러나 이 글로벌 범위 내에서 함수에 사용된 변수나 데이터를 저장해서는 안 됩니다.
결합 최소화
대부분의 아키텍처는 수가 더 적고 크기가 더 큰 함수보다 더 짧고 많은 함수를 선호해야 합니다. 각 함수의 목적은 트랜잭션 볼륨또는 전체 워크플로에 대한 지식이나 예상 정보 없이도 함수에 전달된 이벤트를 처리하는 것이어야 합니다. 그러면 함수가 다른 서비스에 대해 최소의 연결을 사용하며 이벤트 소스의 구애를 받지 않습니다.
자주 변경되지 않는 전역 범위 상수는 배포 없이 업데이트할 수 있는 환경 변수로 구현해야 합니다. 모든 보안 암호 또는 민감한 정보는 AWS Systems Manager Parameter Store 또는 AWS Secrets Manager
배치 대신 온디맨드 데이터 빌드
많은 기존 시스템이 주기적으로 실행되고 시간 경과에 따라 빌드된 트랜잭션 배치를 처리하도록 설계되었습니다. 예를 들어 뱅킹 애플리케이션은 중앙 원장으로 ATM 트랜잭션을 처리하기 위해 1시간마다 실행될 수 있습니다. Lambda 기반 애플리케이션에서 서비스가 필요에 따라 동시성을 스케일 업하여 트랜잭션을 거의 실시간으로 처리할 수 있도록 사용자 지정 처리는 모든 이벤트에 의해 트리거되어야 합니다.
Amazon EventBridge에서 규칙에 대해 예약된 표현식을 사용하여 서버리스 애플리케이션에서 cron
예를 들어 Lambda 함수를 트리거하여 새 Amazon S3 객체 목록을 가져오는 배치 프로세스를 사용하는 것은 모범 사례가 아닙니다. 서비스가 15분의 Lambda 함수 내에서 처리할 수 있는 것보다 배치 사이에 더 많은 새 객체를 수신할 수 있기 때문입니다.
대신 새 객체를 버킷에 넣을 때마다 Amazon S3에서 Lambda 함수를 간접적으로 호출해야 합니다. 이 접근 방식은 특히 확장성이 더 뛰어나며 거의 실시간으로 작동합니다.
오케스트레이션 시 AWS Step Functions 고려
분기 로직, 여러 가지 유형의 장애 모델 및 재시도 로직을 포함하는 워크플로는 일반적으로 오케스트레이터를 사용하여 전체 실행 상태를 추적합니다. 이 목적으로 Lambda 함수를 사용하지 마세요. 강한 결합과 복잡한 코드 처리 라우팅이 발생하기 때문입니다.
AWS Step Functions
Lambda 함수의 더 간단한 워크플로는 시간이 지남에 따라 더 복잡해지는 것이 일반적입니다. 프로덕션 서버리스 애플리케이션을 작동할 때는 이 로직을 상태 머신으로 마이그레이션할 수 있도록 이러한 상황이 언제 발생하는지 식별하는 것이 중요합니다.
멱등성 실행
Lambda를 포함하여 AWS 서버리스 서비스는 내결함성이 뛰어나고 장애를 처리하도록 설계되었습니다. 예를 들어 서비스가 Lambda 함수를 간접 호출하고 서비스 중단이 발생하면 Lambda는 다른 가용 영역에서 함수를 간접 호출합니다. 함수에서 오류가 발생하면 Lambda는 간접 호출을 다시 시도합니다.
동일한 이벤트가 두 번 이상 수신될 수 있으므로 함수는 멱등성
DynamoDB 테이블을 사용하여 최근에 처리된 식별자를 추적해 트랜잭션이 이전에 처리되었는지 확인함으로써 Lambda 함수의 멱등성을 구현할 수 있습니다. DynamoDB 테이블은 일반적으로 Time To Live(TTL) 값을 구현하여 사용되는 스토리지 공간을 제한하도록 항목을 만료시킵니다.
할당량 관리를 위해 여러 AWS 계정 사용
AWS의 많은 Service Quotas가 계정 수준에서 설정됩니다. 즉, 더 많은 워크로드를 추가하면 제한을 빠르게 소진할 수 있습니다.
이 문제를 해결하는 효과적인 방법은 여러 AWS 계정을 사용하여 각각의 워크로드를 해당 계정에 전용으로 사용하는 것입니다. 그러면 할당량이 다른 워크로드나 비프로덕션 리소스와 공유되지 않습니다.
또한 AWS Organizations
이때 한 가지 일반적인 접근 방식은 각 개발자에게 AWS 계정을 제공한 다음, 베타 배포 단계 및 프로덕션에 대해 별도의 계정을 사용하는 것입니다.
이 모델에서는 각 개발자는 계정에 대한 자체 제한 세트가 있으므로 해당 개발자의 사용은 프로덕션 환경에 영향을 주지 않습니다. 또한 이 접근 방식을 통해 개발자는 개별 계정의 라이브 클라우드 리소스에 대해 개발 시스템에서 Lambda 함수를 로컬로 테스트할 수 있습니다.