Lambda SnapStart 성능 극대화 - AWS Lambda

Lambda SnapStart 성능 극대화

성능 튜닝

참고

SnapStart는 대규모 함수 호출에서 사용할 때 가장 효과적입니다. 자주 호출되지 않는 함수에서는 동일한 성능 향상이 이루어지지 않을 수 있습니다.

SnapStart의 이점을 극대화하려면 함수 핸들러가 아니라 초기화 코드에서 시작 지연 시간에 영향을 미치는 클래스를 미리 로드하는 것이 좋습니다. 이렇게 하면 과도한 클래스 로딩과 관련한 지연 시간이 호출 경로 외부로 오프로드되어 SnapStart를 사용한 시작 성능이 최적화됩니다.

초기화 중에 클래스를 미리 로드할 수 없는 경우 더미 호출을 통해 클래스를 미리 로드하는 것이 좋습니다. 이렇게 하려면 AWS Labs GitHub 리포지토리의 Pet Store 함수에서 가져온 다음 예제와 같이 함수 핸들러 코드를 업데이트합니다.

private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler; static { try { handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class); // Use the onStartup method of the handler to register the custom filter handler.onStartup(servletContext -> { FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class); registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); }); // Send a fake Amazon API Gateway request to the handler to load classes ahead of time ApiGatewayRequestIdentity identity = new ApiGatewayRequestIdentity(); identity.setApiKey("foo"); identity.setAccountId("foo"); identity.setAccessKey("foo"); AwsProxyRequestContext reqCtx = new AwsProxyRequestContext(); reqCtx.setPath("/pets"); reqCtx.setStage("default"); reqCtx.setAuthorizer(null); reqCtx.setIdentity(identity); AwsProxyRequest req = new AwsProxyRequest(); req.setHttpMethod("GET"); req.setPath("/pets"); req.setBody(""); req.setRequestContext(reqCtx); Context ctx = new TestContext(); handler.proxy(req, ctx); } catch (ContainerInitializationException e) { // if we fail here. We re-throw the exception to force another cold start e.printStackTrace(); throw new RuntimeException("Could not initialize Spring framework", e); } }

네트워킹 모범 사례

Lambda가 스냅샷에서 함수를 재개할 때, 초기화 단계에서 함수가 설정한 연결 상태는 보장되지 않습니다. 대부분의 경우 AWS SDK가 설정한 네트워크 연결이 자동으로 재개됩니다. 다른 연결의 경우 다음 모범 사례를 따르는 것이 좋습니다.

네트워크 연결 재설정

스냅샷에서 함수를 재개할 때는 항상 네트워크 연결을 재설정합니다. 함수 핸들러에서 네트워크 연결을 재설정하는 것이 좋습니다. 또는 afterRestore 런타임 후크를 사용할 수도 있습니다.

호스트 이름을 고유한 실행 환경 식별자로 사용하지 않음

실행 환경을 애플리케이션의 고유한 노드 또는 컨테이너로 식별하는 데 hostname을 사용하지 않는 것이 좋습니다. SnapStart를 사용하면 단일 스냅샷이 여러 실행 환경의 초기 상태로 사용되며 모든 실행 환경은 InetAddress.getLocalHost()에 대해 동일한 hostname 값을 반환합니다. 고유한 실행 환경 ID 또는 hostname 값이 필요한 애플리케이션의 경우 함수 핸들러에서 고유한 ID를 생성하는 것이 좋습니다. 또는afterRestore 런타임 후크를 사용하여 고유 ID를 생성한 다음 고유 ID를 실행 환경의 식별자로 사용할 수도 있습니다.

고정 소스 포트에 연결을 바인딩하지 않음

네트워크 연결을 고정 소스 포트에 바인딩하지 않는 것이 좋습니다. 스냅샷에서 함수가 재개되면 연결이 재설정되고 고정 소스 포트에 바인딩된 네트워크 연결이 실패할 수 있습니다.

Java DNS 캐시를 사용하지 않음

Lambda 함수는 이미 DNS 응답을 캐싱하고 있습니다. SnapStart에 다른 DNS 캐시를 사용하는 경우 스냅샷에서 함수를 재개할 때 연결 시간 초과가 발생할 수 있습니다.

java.util.logging.Logger 클래스는 JVM DNS 캐시를 간접적으로 활성화할 수 있습니다. 기본 설정을 재정의하려면 logger 초기화 전에 networkaddress.cache.ttl을 0으로 설정하십시오. 예시

public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }

Java 11 런타임에서 UnknownHostException 오류를 방지하려면 networkaddress.cache.negative.ttl을 0으로 설정하는 것이 좋습니다. Java 17 이상 런타임에서는 이 단계가 필요하지 않습니다. AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0 환경 변수를 사용하여 Lambda 함수에 대해 이 속성을 설정할 수 있습니다.

JVM DNS 캐시를 비활성화해도 Lambda의 관리형 DNS 캐싱은 비활성화되지 않습니다.