BLOG

새로운 서버리스 LAMP 스택을 소개합니다.
작성일: 2020-07-29

오늘은 PHP 개발자 시리즈의 첫 번째 포스팅으로, 본 시리즈를 통해 PHP로 서버리스 기술을 사용하는 방법을 설명드릴 예정입니다. 여기에는 서버리스 응용 프로그램을 구축하는 데 사용할 수 있는 도구, 프레임 워크 및 전략과 왜 이를 지금 시작해야 하는 지에 대한 내용이 포함되어 있습니다.

 

다음 번 포스팅으로는 Laravel 및 Symfony 와 같은 PHP 프레임 워크로 구축된 웹 애플리케이션에 AWS Lambda를 사용하는 방법을 다루어 볼 예정입니다. 여기에선 웹 호스팅 기능을 대신하는 Lambda를 사용하지 않고 분리된 이벤트 중심 방식으로 전환하는 방법을 보여드리고, 최소 범위의 여러 Lambda 기능을 다른 서버리스 서비스와 결합하여 성능이 뛰어난 확장 가능한 마이크로 서비스를 만드는 방법을 안내해 드릴 예정입니다.

 

그럼 먼저 이번 블로그 글에선 맞춤형 런타임 API를 통해 Lambda와 함께 PHP를 사용하는 방법을 알려드리겠습니다. 샘플 코드는 GitHub 리포지토리에서 확인해 주시기 바랍니다.

 

서버리스 LAMP 스택

 

 

기존 PHP 응용 프로그램의 과제

확장성은 전통적인 LAMP 스택의 본질적인 과제입니다. 확장 가능한 응용 프로그램은 매우 다양한 수준의 트래픽을 처리할 수 있는 응용 프로그램입니다. 필요에 따라 더 많은 웹 서버를 추가하여 PHP 응용 프로그램을 수평으로 확장하는 경우가 많습니다. 이는 로드 밸런서를 통해 관리되며, 요청을 다양한 웹 서버로 보냅니다. 각 추가적인 서버는 네트워킹, 관리, 스토리지 용량, 백업 및 복원 시스템, 자산 관리 인벤토리 업데이트로 인한 추가 오버 헤드를 제공합니다. 또한 수평으로 확장된 각 서버는 독립적으로 실행됩니다. 구성 동기화 문제가 발생할 수 있습니다.

 

 

기존 LAMP 스택 애플리케이션을 사용한 수평 스케일링

 

각 서버마다 고유한 디스크와 파일 시스템이 있으므로 개발자가 사용자 세션을 처리하는 메커니즘을 추가해야 하는 새로운 스토리지 문제가 발생합니다. 서버리스 기술을 사용하여 개발자의 확장성을 관리합니다.

 

트래픽이 급증하면 추가 서버를 배포하지 않고도 서비스가 요구를 충족하도록 확장됩니다. 따라서 응용 프로그램을 프로토타입에서 프로덕션으로 빠르게 전환할 수 있습니다.

 

 

서버리스 LAMP 아키텍처

전통적인 웹 응용 프로그램은 두 가지 구성 요소로 나눌 수 있습니다.

  • 정적 자산 (미디어 파일, CSS, JS)
  • 동적 애플리케이션 (PHP, MySQL)

 

이 두 구성 요소를 제공하는 서버리스 접근 방식은 다음과 같습니다.

 

서버리스 LAMP 스택

 

동적 콘텐츠에 대한 모든 요청 (/ assets / *를 제외한 모든 요청)은 Amazon API Gateway로 전달됩니다. 이는 규모에 관계없이 API를 생성, 게시 및 보안을 유지하는 매니지드 서비스입니다. 이는 PHP 애플리케이션의 게이트 역할을 하여 요청을 Lambda 함수로 다운 스트림 라우팅합니다. Lambda 함수에는 비즈니스 논리와 MySQL 데이터베이스와의 상호 작용이 포함되어 있습니다. 요청 헤더, 경로 변수, 쿼리 문자열 매개 변수 및 본문의 조합으로 입력을 Lambda 함수에 전달할 수 있습니다.

 

 

PHP 개발자가 주목할만한 AWS 기능

 

Amazon 오로라 서버리스

re:Invent 2017에서 AWS는 PPU (pay-per-use-cost) 비용 모델을 갖춘 온 디맨드 서버리스 관계형 데이터베이스 Aurora Serverless를 발표했습니다. 이는 개발자를 위한 관계형 데이터베이스 프로비저닝 및 확장의 책임을 관리합니다.

 

람다 레이어  맞춤형 런타임API

re:Invent 2018에서 AWS는 두 가지 새로운 Lambda 기능을 발표했습니다. 이를 통해 개발자는 사용자 정의 런타임을 구축하고 기능 간 공통 코드를 공유 및 관리할 수 ​​있습니다.

 

람다 함수를 위한 VPC 네트워킹

2019년 9월 AWS는 VPC 내부 Lambda 함수에 대한cold star기능 향상을 발표했습니다.  이를 통해 함수 스타트업 성능이 빨라지고 탄력적 네트워크 인터페이스를 보다 효율적으로 사용하여 VPC 콜드 스타트가 줄어듭니다

 

Amazon RDS 프록시

re:Invent 2019에서 새로운 서비스 AWS는 Amazon RDS 프록시의 런칭을 발표했습니다. 매니지드 데이터베이스 프록시는 응용 프로그램과 관계형 데이터베이스 사이에 위치합니다. 데이터베이스 연결을 효율적으로 풀링하고 공유하여 응용 프로그램의 확장성을 향상시킵니다.

 

서버리스 LAMP 스택 타임 라인의 중요한 순간

 

이러한 서비스를 결합하면 PHP 및 관계형 데이터베이스를 사용하여 안전하고 성능이 뛰어난 확장 가능한 서버리스 응용 프로그램을 구축할 수 있습니다.

 

 

커스텀 런타임 API

사용자 정의 런타임 API는 모든 프로그래밍 언어 또는 특정 언어 버전에서 Lambda 함수를 실행할 수 있는 간단한 인터페이스입니다. 사용자 정의 런타임 API에는 부트 스트랩이라는 실행 가능 텍스트 파일이 필요합니다. 부트 스트랩 파일은 코드와 Lambda 환경 간의 통신을 담당합니다.

 

사용자 정의 런타임을 생성하려면 먼저 Lambda 실행 환경과 호환되는 Amazon Linux 환경에서 필요한 PHP 버전을 컴파일해야 합니다. 이를 위해서는 다음 단계별 지침을 따르세요.

 

 

부트 스트랩 파일

아래 파일은 기본 PHP 부트 스트랩 파일의 예입니다. 이 예제는 오류 처리나 추상화가 없기 때문에 설명을 위한 것입니다. 예외를 적절하게 처리하려면 프로덕션 사용자 정의 런타임을 빌드할 때 런타임 API 문서를 참고하세요.

 

#!/opt/bin/php

<?PHP 

 

// This invokes Composer’s autoloader so that we’ll be able to use Guzzle and any other 3rd party libraries we need.

require __DIR__ ./vendor/autoload.php; 

// This is the request processing loop. Barring unrecoverable failure, this loop runs until the environment shuts down.

do {

    // Ask the runtime API for a request to handle.

    $request = getNextRequest();

 

     // Obtain the function name from the _HANDLER environment variable and ensure the function’s code is available.

    $handlerFunction = array_slice(explode(‘.’, $_ENV[‘_HANDLER’]), 1)[0];

    require_once $_ENV[‘LAMBDA_TASK_ROOT’] . ‘/src/’ . $handlerFunction ..php;

 

     // Execute the desired function and obtain the response.

    $response = $handlerFunction($request[‘payload’]);

 

     // Submit the response back to the runtime API.

    sendResponse($request[‘invocationId’], $response);

} while (true);

 

 function getNextRequest()

{

    $client = new \GuzzleHttp\Client();

    $response = $client->get(‘http://’ . $_ENV[‘AWS_LAMBDA_RUNTIME_API’] . ‘/2018-06-01/runtime/invocation/next’);

 

     return [

      ‘invocationId’ => $response->getHeader(‘Lambda-Runtime-Aws-Request-Id’)[0],

      ‘payload’ => json_decode((string) $response->getBody(), true)

    ];

}

 

 function sendResponse($invocationId, $response)

{

    $client = new \GuzzleHttp\Client();

    $client->post(

    ‘http://’ . $_ENV[‘AWS_LAMBDA_RUNTIME_API’] . ‘/2018-06-01/runtime/invocation/’ . $invocationId . ‘/response’,

       [‘body’ => $response]

    );

}

 

이 #!/opt/bin/php선언은 프로그램 로더에게 Amazon Linux용으로 컴파일된 PHP 바이너리를 사용하도록 지시합니다.

 

부트 스트랩 파일은 운영 루프에서 다음 작업을 수행합니다.

  1. 다음 요청 반환
  2. 요청을 처리하기 위해 코드를 실행
  3. 응답 반환

 

부트 스트랩과 컴파일 된 PHP 바이너리를`runtime.zip`으로 패키징 다음 단계를 따르세요.

 

 

라이브러리 종속성

런타임 부트 스트랩은 HTTP 기반 로컬 인터페이스를 사용합니다. 각 Lambda 함수 호출에 대한 이벤트 페이로드를 검색하고 함수에서 응답을 다시 리턴합니다. 이 부트 스트랩 파일은 널리 사용 되는 PHP HTTP 클라이언트인 Guzzle을 사용하여 사용자 정의 런타임 API에 요청합니다. Guzzle 패키지는 Composer 패키지 관리자를 사용하여 설치됩니다. 이러한 방식으로 패키지를 설치하면 응용 프로그램이 발전함에 따라 추가 라이브러리 및 종속성을 통합하기 위한 메커니즘이 생성됩니다.

 

다음 단계에 따라 런타임 종속성을 작성하여`vendors.zip` 바이너리로 패키징하세요.

 

Lambda Layers는 여러 기능에서 공유되는 코드 및 데이터를 중앙에서 관리하는 메커니즘을 제공합니다. Lambda 함수가 계층으로 구성된 경우 계층의 내용은 실행 환경의 / opt 디렉토리에 저장됩니다. 함수의 배포 패키지 또는 계층으로 사용자 지정 런타임을 포함할 수 있습니다. Lambda는 사용 가능한 경우 배포 패키지에서 부트 스트랩 파일을 실행합니다. 그렇지 않은 경우 Lambda는 함수 계층에서 런타임을 찾습니다. 오늘날 몇 가지 오픈 소스 PHP 런타임 계층이 있으며, 가장 주목할만한 것은 다음과 같습니다.

 

 

다음 단계는 앞서 생성된 `runtime.zip` 및`vendor.zip ‘바이너리를 Lambda 레이어에 게시하고 PHP 런타임으로 Lambda 함수를 빌드하는 데 사용하는 방법을 보여줍니다.

  1. AWS Command Line Interface (CLI)를 사용하여 이전에 생성된 바이너리에서 레이어를 게시

aws lambda publish-layer-version \

    –layer-name PHP-example-runtime \

   –zip-file fileb://runtime.zip \

   –region eu-west-1 

 

 

aws lambda publish-layer-version \

    –layer-name PHP-example-vendor \

    –zip-file fileb://vendors.zip \

    –region eu-west-1

 

2. 다음 단계에 필요한 각 명령의 LayerVersionArn 출력 값 (예: arn : aws : lambda : eu-west-1 : XXXXXXXXXXXX : layer : PHP-example-runtime : 1) 기록

PHP Lambda 함수 생성

AWS CLI, AWS Serverless Application Model (SAM)을 또는 AWS Management Console에서 직접 Lambda 함수를 생성할 수 있습니다. 콘솔을 사용하여 이를 수행하려면 다음을 수행하세요.

  1.  AWS Management Console의 Lambda 섹션으로 이동 및 Create function 선택
  2. 기능 이름 필드에 ” PHPHello” 를 입력 하고 런타임 필드 에서 고유 부트 스트랩 제공 선택  Create function 선택
  3. bootstrap.sample 마우스 오른쪽 단추로 클릭 및 삭제
  4. 레이어 아이콘을 선택 및 레이어 추가 선택

5. 레이어 버전 ARN을 제공을 선택 후 1단계에서 복사하고 사용자 지정 런타임 층의 필드에 붙여넣기

6. 공급 업체 ARN에 대해 6 단계와 7 단계를 반복

7. 함수 코드 섹션에서 SRC 폴더를 새로 생성하고 그 안에 index.php

8. 아래 코드를 index.php에 붙여넣기

//index function

function index($data)

{

return “Hello, “. $data[‘name’];

}

 

9. 처리기 입력 필드에 ” index ” 삽입, 이를 통해 Lambda가 호출될 때 인덱스 함수를 실행하도록 지시

10. 페이지 오른쪽 상단에서 저장 선택

11. 페이지 오른쪽 상단에서 테스트를 선택 및 이벤트 이름 필드에 ” PHPTest “를 입력,이벤트 페이로드 필드에 다음을 입력한 후 작성 선택하고 { “name”: “world”}  작성

 

 

12. 테스트 선택 실행 결과 옆에 있는 드롭 다운 선택

 

이벤트 페이로드 ” name “값이 ” hello world ” 를 리턴하는 데 사용됨을 알 수 있습니다. 이는 람다 함수에 제공되는  $data[‘name’]매개 변수에서 가져옵니다. 로그 출력은 실제 기간, 청구 기간 및 코드 실행에 사용된 메모리 양에 대한 세부 정보를 제공합니다.

 

 

결론

이 글은 Lambda Layers와 사용자 맞춤 런타임 API를 사용하여 PHP 런타임으로 Lambda 함수를 생성하는 방법을 설명합니다. 애플리케이션 트래픽에 따라 확장되는 서버리스 LAMP 스택의 아키텍처를 소개합니다.

 

Lambda를 사용하면 런타임이 혼합된 기능이 서로 상호 작용할 수 있습니다. 이제 PHP 개발자는 배송 코드에 중점을 둔 다른 서버리스 개발팀에 합류할 수 있습니다. 서버리스 기술을 사용하면 더 이상 웹 호스트 재시작, 확장 또는 호스팅에 대해 고민할 필요가 없습니다.

 

Lambda에 대한 사용자 정의 런타임 빌드를 시작하세요.

 

원문URL:  https://aws.amazon.com/ko/blogs/compute/introducing-the-new-serverless-lamp-stack/

** 메가존 클라우드 TechBlog는 AWS BLOG 영문 게재 글 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.