Amazon VPC에 연결된 Lambda 함수의 시간 초과를 방지하려면 어떻게 해야 하나요?

3분 분량
0

Amazon Virtual Private Cloud(VPC)에 대한 AWS Lambda 함수 연결이 제한 시간이 초과되는 것을 방지하고 싶습니다.

간략한 설명


응답 없이 로드 밸런서 또는 NAT 게이트웨이 뒤에서 Lambda 함수 API 호출을 호출하는 것은 연결 유휴 시간 초과 문제 때문일 수 있습니다. 로드 밸런서 유휴 시간 제한 값은 TCP 흐름의 경우 350초입니다.

API 호출 응답 지연이 간헐적이거나 350초 미만인 경우 재시도 및 시간 초과 문제로 인해 발생할 수 있습니다. 자세한 내용은 AWS SDK를 사용하여 Lambda 함수를 호출할 때 재시도 및 시간 초과 문제를 해결하려면 어떻게 해야 하나요?를 참조하세요.

해결 방법

연결이 끊기는 것을 방지하려면 350초 미만의 값으로 TCP keepalive를 켜서 유휴 제한 시간을 재설정할 수 있습니다. TCP keepalive는 20초마다 프런트엔드 및 백엔드 연결에 패킷을 전송하여 연결이 유휴 상태가 되는 것을 방지합니다.

다음과 같이 소켓 객체에서 setKeepAlive를 호출할 수 있습니다.

Node.js 14 및 Node.js 16

const http = require('http');

function invokeApi() {

  return new Promise(resolve => {

    var callback = function(response) {
      var str = '';

      response.on('data', function (chunk) {
        str += chunk;
      });

      response.on('end', function () {
        response = '**** ALB response: ' + str;
        resolve(response)
      });
    }

    const url = 'http://<alb-dns>';
    const myTimeout = 1000*60*15; // 15 minutes
    let req = http.get(url, callback);

    req.on('error', (e) => {
      console.error(`Got error: ${e.message}`);
    });

    req.on('socket', function (socket) {
      socket.setKeepAlive(true, 1000); //set SO_KEEPALIVE

      socket.setTimeout(myTimeout);  

      socket.on('timeout', function() {
        console.log('request is about to timeout');
        req.abort();
      });
    });
    req.end();
  })
}

exports.handler = async (event) => {
    let output = await invokeApi();
    const response = {
        statusCode: 200,
        body: output,
    };
    return response;
};

Node.js 18

import * as http from "http"

function invokeApi() {

  return new Promise(resolve => {

    var callback = function(response) {
      var str = '';

      response.on('data', function (chunk) {
        str += chunk;
      });

      response.on('end', function () {
        response = '**** ALB response: ' + str;
        resolve(response);
      });
    }

    const url = 'http://<alb-dns>';
    const myTimeout = 1000*60*15; // 15 minutes
    let req = http.get(url, callback);

    req.on('error', (e) => {
      console.error(`Got error: ${e.message}`);
    });

    req.on('socket', function (socket) {
      socket.setKeepAlive(true, 1000); //set SO_KEEPALIVE

      socket.setTimeout(myTimeout);  

      socket.on('timeout', function() {
        console.log('request is about to timeout');
        req.abort();
      });
    });
    req.end();
  })
}

export const handler = async(event) => {
    let output = await invokeApi();
    const response = {
        statusCode: 200,
        body: output,
    };
    return response;
};

Python 3.x

import json
import socket
import requests
from urllib3.connection import HTTPConnection

HTTPConnection.default_socket_options = HTTPConnection.default_socket_options + [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
def lambda_handler(event, context):
    try:
        r = requests.get("http://<alb-dns>",timeout=(5,900))

        output = r.text
    except requests.RequestException as e:
        print(e)
        raise e
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": output,
        }),
    }

AWS SDK for Java2를 사용하면 다음과 같이 사전 구성된 HTTP 클라이언트를 전달할 수 있습니다.

LambdaClient awsLambda = LambdaClient.builder()
    .region(region
    .httpClient(ApacheHttpClient.builder()
                   .tcpKeepAlive(true)
                   .connectionTimeout(Duration.ofSeconds(5))
                   .connectionMaxIdleTime(Duration.ofMinutes(15))
                   .socketTimeout(Duration.ofMinutes(15)).build())
    .build();

AWS SDK for Python(Boto3)를 사용하면 구성 파일을 사용할 수 있습니다. 다음 내용이 포함된 .config 파일을 생성합니다.

[default]
tcp_keepalive=true

그런 다음 /var/task/config 디렉터리에 .config 파일의 값을 사용하여 Lambda 환경 변수 AWS_CONFIG_FILE을 생성합니다.

자세한 내용은 연결 유휴 시간 제한을 참조하세요.


관련 정보

AWS Lambda 함수를 위한 개선된 VPC 네트워킹 발표

프라이빗 VPC에서 NAT 게이트웨이를 사용할 때 연결 문제를 해결하려면 어떻게 해야 하나요?

AWS 공식
AWS 공식업데이트됨 일 년 전