Lambda Managed Instances용 Rust 지원
Lambda Managed Instances용 Rust 지원
동시성 구성
Lambda가 각 실행 환경으로 보내는 최대 동시 요청 수는 함수 구성의 PerExecutionEnvironmentMaxConcurrency 설정으로 제어돼요. 선택 사항인 이 설정의 Rust 기본값은 vCPU당 8개 동시 요청이며, 직접 값을 구성할 수도 있어요. 이 값은 런타임이 생성하는 Tokio 작업 수를 결정하며 실행 환경 수명 동안 정적이에요. 각 작업자(worker)는 한 번에 정확히 하나의 진행 중 요청을 처리하며, 작업자당 멀티플렉싱은 없어요. Lambda는 각 실행 환경이 그 요청을 흡수할 수 있는 용량을 기준으로 구성된 최대값까지 동시 요청 수를 자동으로 조정해요.
본문
다중 동시성을 위한 함수 구축
Lambda Managed Instances를 사용할 때는 다른 멀티 스레드 환경과 동일한 스레드 안전 관행을 적용해야 해요. 핸들러 객체는 모든 작업자 스레드에 걸쳐 공유되므로, 가변 상태는 스레드 안전해야 해요. 여기에는 컬렉션, 데이터베이스 연결, 요청 처리 중 수정되는 정적 객체가 포함돼요.
동시 요청 처리를 활성화하려면 Cargo.toml 파일에 concurrency-tokio 기능 플래그를 추가하세요.
[dependencies]
lambda_runtime = { version = "1", features = ["concurrency-tokio"] }
lambda_runtime::run_concurrent(…) 진입점은 Tokio 런타임 내에서 호출되어야 하며, 보통 main 함수의 #[tokio::main] 속성이 제공해요. 핸들러 클로저는 Clone + Send를 구현해야 해요. 이렇게 해야 프레임워크가 여러 비동기 작업에 걸쳐 핸들러를 안전하게 공유할 수 있죠. 이 제약 조건을 충족하지 못하면 코드가 컴파일되지 않아요.
호출 간에 공유 상태(데이터베이스 풀, 구성 구조체)가 필요하면 Arc로 감싸고 Arc를 각 호출에 복제하세요.
모든 AWS SDK for Rust 클라이언트는 동시성 안전하며 특별한 처리가 필요 없어요.
예제: AWS SDK 클라이언트
다음 예제는 호출마다 S3 클라이언트를 사용해 객체를 업로드해요. 클라이언트는 Arc 없이 클로저에 직접 복제돼요:
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
let s3_client = aws_sdk_s3::Client::new(&config);
run_concurrent(service_fn(move |event: LambdaEvent<Request>| {
let s3_client = s3_client.clone(); // cheap clone, no Arc needed
async move {
s3_client.put_object()
.bucket(&event.payload.bucket)
.key(&event.payload.key)
.body(event.payload.body.into_bytes().into())
.send()
.await?;
Ok(Response { message: "uploaded".into() })
}
}))
.await
예제: 데이터베이스 연결 풀
핸들러가 클라이언트와 구성 같은 공유 상태에 접근해야 할 때는 Arc로 감싸고 Arc를 각 호출에 복제하세요:
#[derive(Debug)]
struct AppState {
dynamodb_client: DynamoDbClient,
table_name: String,
cache_ttl: Duration,
}
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
let state = Arc::new(AppState {
dynamodb_client: DynamoDbClient::new(&config),
table_name: std::env::var("TABLE_NAME").expect("TABLE_NAME must be set"),
cache_ttl: Duration::from_secs(300),
});
run_concurrent(service_fn(move |event: LambdaEvent<Request>| {
let state = state.clone();
async move { handle(event, state).await }
}))
.await
공유 /tmp 디렉토리
/tmp 디렉토리는 같은 실행 환경의 모든 동시 호출에 걸쳐 공유돼요. 데이터 손상을 피하려면 호출마다 고유한 파일 이름을 사용하거나(예: 요청 ID 포함) 명시적 파일 잠금을 구현하세요.
로깅
로그 인터리빙(서로 다른 요청의 로그 항목이 로그에 섞여 표시되는 것)은 다중 동시 시스템에서 정상이에요. Lambda Managed Instances를 사용하는 함수는 Lambda의 고급 로깅 컨트롤을 통해 구조화된 JSON 로그 형식을 지원해요. 이 형식에는 requestId가 포함되어 로그 항목을 단일 요청에 상관시킬 수 있죠. 자세한 내용은 Tracing 크레이트로 고급 로깅 구현을 참고하세요.
요청 컨텍스트
Context 객체는 각 핸들러 호출에 직접 전달돼요. event.context.request_id를 사용해 현재 요청의 요청 ID에 접근할 수 있어요.
event.context.xray_trace_id를 사용해 X-Ray 추적 ID에 접근하세요. Lambda는 Lambda Managed Instances에서 _X_AMZN_TRACE_ID 환경 변수를 지원하지 않아요. X-Ray 추적 ID는 AWS SDK for Rust를 사용할 때 자동으로 전파돼요.
event.context.deadline을 사용해 타임아웃을 감지하세요 — 호출 마감(deadline)을 밀리초 단위로 담고 있어요.
초기화 및 종료
함수 초기화는 실행 환경당 한 번 발생해요. 초기화 중 생성된 객체는 요청 간에 공유됩니다.
확장(extension)이 있는 Lambda 함수의 경우 실행 환경은 종료 중 SIGTERM 신호를 내보내요. 이 신호는 확장이 버퍼를 플러시하는 것 같은 정리 작업을 트리거하는 데 사용돼요. lambda_runtime은 정상 종료 신호 처리를 구성하는 것을 간소화하는 헬퍼, spawn_graceful_shutdown_handler()를 제공해요. 실행 환경 수명 주기에 대해 더 알아보려면 Lambda 실행 환경 수명 주기 이해를 참고하세요.
의존성 버전
Lambda Managed Instances에는 다음 최소 패키지 버전이 필요해요:
lambda_runtime:concurrency-tokio기능이 활성화된 버전 1.1.1 이상- 지원되는 최소 Rust 버전(MSRV)은 1.84.0이에요.
더 알아보기 (Learn more)
- Managed Instances에서 Rust 함수의 동시성 설정, 스레드 안전 핸들러, Arc 공유 상태, /tmp 공유, 로깅, 요청 컨텍스트와 최소 버전 요구 사항을 익혀 보세요.