이 가이드는 표준 환경에 익숙한 사용자를 대상으로 가변형 환경을 안내합니다. 환경 간의 유사점과 차이점을 설명하고 두 환경을 모두 사용하는 애플리케이션을 위한 일반적인 아키텍처 권장사항도 제공합니다.
표준 환경에서 사용할 수 있는 서비스를 가변형 환경의 유사 항목에 매핑하려면 표준 환경에서 가변형 환경으로 서비스 마이그레이션을 참조하세요.
유사점 및 주요 차이점
두 환경 모두 App Engine의 배포, 제공, 확장 인프라를 제공합니다. 주요 차이점은 환경에서 애플리케이션을 실행하는 방법, 애플리케이션에서 외부 서비스에 액세스하는 방법, 로컬에서 애플리케이션을 실행하는 방법, 애플리케이션이 확장되는 방법에 있습니다. 이러한 차이점에 대한 개괄적인 요약은 환경 선택을 참조하세요.
애플리케이션 실행
표준 환경에서는 애플리케이션이 샌드박스 내의 가벼운 인스턴스에서 실행됩니다. 이 샌드박스는 애플리케이션에서 수행할 수 있는 작업을 제한합니다. 예를 들어 샌드박스에서 앱은 제한된 바이너리 라이브러리 집합만 사용 가능하고 디스크에 쓰기를 수행할 수 없습니다. 또한 표준 환경은 애플리케이션에서 사용할 수 있는 CPU 및 메모리 옵션도 제한됩니다. 이러한 제한으로 인해 App Engine 표준 애플리케이션은 대부분 HTTP 요청에 빠르게 응답하는 스테이트리스(Stateless) 웹 애플리케이션에 해당합니다.
반면 가변형 환경은 제한이 적은 Google Compute Engine 가상 머신(VM)의 Docker 컨테이너에서 애플리케이션을 실행합니다. 예를 들어 원하는 프로그래밍 언어를 자유롭게 사용하고, 디스크에 쓰고, 원하는 라이브러리를 사용하고, 여러 프로세스를 실행할 수도 있습니다. 또한 가변형 환경에서는 인스턴스의 Compute Engine 머신 유형을 원하는 대로 선택하여 애플리케이션에서 더 많은 메모리와 CPU를 이용할 수 있습니다.
외부 서비스 액세스
일반적으로 표준 환경에서 애플리케이션은 기본 제공되는 google.appengine API를 통해 Datastore와 같은 서비스에 액세스합니다. 하지만 가변형 환경에서는 이러한 API를 더 이상 사용할 수 없습니다. 대신 Google Cloud 클라이언트 라이브러리를 사용합니다. 클라이언트 라이브러리는 어디서나 작동하므로 애플리케이션의 이동성이 향상됩니다. 필요한 경우 일반적으로 가변형 환경에서 실행되는 애플리케이션을 크게 수정하지 않고 Google Kubernetes Engine 또는 Compute Engine에서 실행할 수 있습니다.
로컬 개발
표준 환경에서는 일반적으로 App Engine SDK를 사용하여 로컬에서 애플리케이션을 실행합니다. SDK는 애플리케이션 실행을 처리하고 App Engine 서비스를 에뮬레이션합니다. 가변형 환경에서는 SDK를 사용하여 애플리케이션을 실행하지 않습니다. 대신 가변형 환경용 애플리케이션은 어디서나 실행 가능한 표준 웹 애플리케이션처럼 작성되어야 합니다. 앞서 언급했듯이 가변형 환경은 애플리케이션을 Docker 컨테이너에서 실행합니다. 따라서 애플리케이션을 로컬에서 테스트하려면 애플리케이션을 직접 실행하면 됩니다. 예를 들어 Django를 사용하는 Python 애플리케이션을 실행하려면 python manage.py runserver
를 실행하기만 하면 됩니다.
또 다른 중요한 차이점은 로컬에서 실행되는 가변형 환경 애플리케이션에서 Datastore와 같은 실제 Cloud Platform 서비스를 사용한다는 점입니다. 로컬 테스트를 위해 별도의 프로젝트를 사용하고, 가능한 경우 에뮬레이터를 사용합니다.
확장 특성
두 환경 모두 App Engine의 자동 확장 인프라를 사용하지만 확장 방법이 서로 다릅니다. 표준 환경은 인스턴스를 0개에서 수천 개까지 빠르게 확장할 수 있습니다. 반면 가변형 환경에는 각 활성 버전에 실행 중인 인스턴스가 하나 이상 있어야 하며 트래픽에 따라 수평 확장하는 데 더 오랜 시간이 걸릴 수 있습니다.
표준 환경은 커스텀으로 설계된 자동 확장 알고리즘을 사용합니다. 가변형 환경은 Compute Engine 자동 확장 처리를 사용합니다. 가변형 환경은 Compute Engine에서 사용할 수 있는 자동 확장 옵션 중 일부를 지원하지 않습니다. App Engine은 구성과 일치하는 리전에 이미 있는 Compute Engine VM 예약을 따릅니다. VM 예약이 있으면 일시적인 리소스 부족 중에 리소스 할당을 받을 가능성이 높아집니다.
개발자는 다양한 조건에서 애플리케이션 동작을 테스트해야 합니다. 예를 들어, 원격 서비스에 대한 호출로 인해 지연 시간이 늘어난 상태에서 CPU 바인딩 애플리케이션이 I/O 바인딩으로 변하는 경우 자동 확장이 어떻게 대응하는지 확인해야 합니다.
상태 확인
표준 환경에서는 상태 확인을 사용하여 트래픽을 인스턴스로 전송할지 여부를 결정하지 않습니다. 가변형 환경에서는 애플리케이션 개발자가 부하 분산기에서 사용될 고유한 상태 확인 핸들러를 작성하여 인스턴스에 트래픽을 전송할지 여부와 자동 복구 여부를 결정할 수 있습니다. 개발자는 상태 확인에 논리를 추가할 때 주의해야 합니다. 예를 들어, 상태 확인 시 외부 서비스를 호출하고 해당 서비스에 일시적인 장애가 발생하면 모든 인스턴스가 비정상 상태가 되어 계단식 장애가 발생할 수 있습니다.
과부하 발생 시 요청 삭제
애플리케이션은 계단식 장애 발생을 방지하기 위한 전략의 일환으로 과부하 발생 시 요청을 삭제할 수 있습니다. 이 기능은 표준 환경의 트래픽 라우팅 레이어에 기본 제공됩니다. 가변형 환경에서 QPS가 매우 높은 애플리케이션을 개발하는 경우, 동시 요청 수를 제한하여 애플리케이션에 대한 과부하 트래픽을 차단하는 기능을 빌드하는 것이 좋습니다.
최대 인스턴스 수를 제한하는 버전을 만들어 가변형 환경 애플리케이션이 이러한 유형의 장애에 취약하지 않은지 확인할 수 있습니다. 그런 다음 요청이 삭제될 때까지 트래픽을 지속적으로 늘립니다. 과부하 상태에서 애플리케이션이 상태 확인에 실패하지 않도록 해야 합니다.
자바의 경우, Jetty 런타임을 사용하는 자바 앱은 서비스 품질 필터를 구성하여 과부하 차단을 구현할 수 있습니다. 앱에서 처리하는 최대 동시 요청 수와 이 기능을 사용하여 요청이 대기열에 추가되는 기간을 설정할 수 있습니다.
인스턴스 크기
가변형 환경 인스턴스는 표준 환경 인스턴스보다 높은 CPU 및 메모리 제한을 가질 수 있습니다. 따라서 메모리와 CPU를 더 많이 사용하는 애플리케이션을 가변형 인스턴스에서 실행할 수 있습니다. 하지만 단일 인스턴스 내 스레드 수 증가로 인해 동시 실행 버그가 발생할 가능성이 높아질 수 있습니다.
개발자는 가변형 환경 인스턴스에 SSH를 실행하고 스레드 덤프를 가져와 이러한 유형의 문제를 해결할 수 있습니다.
예를 들어 자바 런타임을 사용하는 경우 다음을 실행할 수 있습니다.
$ ps auwwx | grep java $ sudo kill -3$ sudo docker logs gaeapp
최대 요청 제한 시간
표준 환경 요청 제한 시간은 선택된 확장 유형에 따라 다르지만 가변형 환경에는 항상 60분 제한 시간이 적용됩니다. 요청이 온전히 60분 동안 공개되면서 웹 서버의 모든 스레드를 사용하지 않도록 하려면 다음 안내를 따르세요.
외부 서비스를 호출하는 경우 제한 시간을 지정합니다.
서블릿 필터를 구현하여 허용할 수 없을 만큼 시간이 오래 걸리는(예: 60초) 요청을 중지합니다. 필터가 요청을 중지한 후에는 앱이 일관된 상태로 돌아갈 수 있도록 합니다.
스레드 관리
자바 8 이전의 표준 환경 자바 런타임은 App Engine 표준 환경 SDK를 통해 생성된 스레드만 사용할 수 있습니다. 1세대 자바 표준 환경 런타임에서 가변형 환경으로 애플리케이션을 포팅하는 개발자는 기본 스레드 라이브러리를 사용하도록 전환해야 합니다. 스레드 수가 매우 많이 필요한 애플리케이션은 명시적 스레드 생성보다 스레드 풀에서 더 효율적으로 실행될 수 있습니다.
트래픽 마이그레이션
표준 환경은 트래픽을 새 버전으로 점진적으로 이동하여 지연 시간 급증을 최소화하는 트래픽 마이그레이션 기능을 제공합니다. 트래픽을 새 버전으로 전환할 때 지연 시간 급증을 방지할 수 있는 방법에 대해서는 트래픽 마이그레이션 문서를 참조하세요.
단일 영역 오류
표준 환경 애플리케이션은 단일 홈을 가집니다. 즉, 애플리케이션의 모든 인스턴스가 단일 가용 영역에 상주합니다. 해당 영역에서 오류가 발생하면 애플리케이션은 동일한 리전의 다른 영역에서 새로운 인스턴스를 시작하고 부하 분산기가 트래픽을 새 인스턴스로 라우팅합니다. 이에 따라 로드 요청으로 인한 지연 시간 급증과 Memcache 플러시가 발생합니다.
가변형 환경 애플리케이션은 리전 관리형 인스턴스 그룹을 사용합니다. 즉, 인스턴스가 한 리전 내의 여러 가용 영역에 분산됩니다. 단일 영역 오류가 발생하면 부하 분산기는 해당 영역으로의 트래픽 라우팅을 중지합니다. 인스턴스 실행을 극대화하도록 자동 확장을 설정한 경우, 자동 확장으로 인해 더 많은 인스턴스가 생성되기 전에 잠깐 과부하가 발생합니다.
비용 비교
표준 환경과 가변형 환경에서 실행되는 워크로드 간의 비용을 비교할 때는 여러 가지 요소를 고려해야 합니다. 예를 들면 다음과 같습니다.
- MCycle당 지불 가격
- MCycle당 수행 가능한 작업에 영향을 주는 CPU 플랫폼 기능
- 각 플랫폼에서 실행 가능한 인스턴스 수
- 배포 비용은 플랫폼마다 다를 수 있으며 애플리케이션에서 지속적 배포를 사용하는 경우 비용 부담이 상당히 클 수 있음
- 런타임 오버헤드
실험적으로 실행하여 각 플랫폼별 워크로드 비용을 확인해야 합니다. 가변형 환경에서는 실험적 실행 시 애플리케이션의 비용 효율성 지표로 코어당 QPS를 사용하여 변경사항이 비용에 영향을 미치는지 여부를 확인할 수 있습니다. 표준 환경에서는 애플리케이션의 비용 효율성에 대한 실시간 측정항목을 얻을 수 있는 이러한 메커니즘을 제공하지 않습니다. 따라서 변경한 후 일일 결제 주기가 완료될 때까지 기다려야 합니다.
마이크로서비스
표준 환경에서는 X-Appengine-Inbound-Appid
요청 헤더를 사용하여 애플리케이션 간의 보안 인증을 허용합니다. 반면 가변형 환경에는 이러한 기능이 없습니다. 애플리케이션 간 보안 인증을 위해 권장되는 접근 방식은 OAuth를 사용하는 것 입니다.
배포
표준 환경에서의 배포는 일반적으로 가변형 환경에서의 배포보다 빠릅니다. 가변형 환경에 배포 시 새 버전의 네트워크 프로그래밍을 하려면 일반적으로 시간이 많이 소요되므로, 가변형 환경에서는 새 버전을 배포하는 것보다 기존 버전을 확장하는 것이 더 빠릅니다. 가변형 환경에서 빠른 롤백을 수행하는 한 가지 방법은 알려진 정상 버전을 단일 인스턴스로 하여 유지하는 것입니다. 그런 다음 해당 버전을 확장한 후 트래픽 분할을 사용하여 모든 트래픽을 이 버전으로 라우팅하면 됩니다.
가변형 환경을 사용하는 경우
가변형 환경은 표준 환경을 보완하기 위한 용도로 사용됩니다. 표준 환경에서 실행되는 기존 애플리케이션이 있는 경우 일반적으로 애플리케이션 전체를 가변형 환경으로 마이그레이션할 필요는 없습니다. 대신 애플리케이션에서 CPU 또는 RAM이 추가로 필요하거나 특수한 타사 라이브러리 또는 프로그램이 필요하거나 표준 환경에서는 불가능한 작업을 수행해야 하는 부분을 파악하세요. 애플리케이션에서 이러한 부분을 찾은 후 가변형 환경을 사용하여 이 부분만 처리하는 작은 App Engine 서비스를 만듭니다. 표준 환경에서 실행되는 기존 서비스는 HTTP, Cloud Tasks 또는 Cloud Pub/Sub를 사용하여 다른 서비스를 호출할 수 있습니다.
예를 들어 표준 환경에서 실행 중인 기존 웹 애플리케이션이 있고 파일을 PDF로 변환하는 새로운 기능을 추가하려면 PDF로 변환만 취급하는 가변형 환경에서 실행되는 별도의 마이크로서비스를 작성하면 됩니다. 이 마이크로서비스는 요청 핸들러 한 개 또는 두 개로 구성된 간단한 프로그램일 수 있습니다. 마이크로서비스는 변환에 도움이 되는 Linux 프로그램을 설치 및 사용할 수 있습니다(예: unoconv).
기본 애플리케이션이 표준 환경에서 계속 실행되면 HTTP를 통해 이 마이크로서비스를 직접 호출할 수 있습니다. 또한 변환하는 데 시간이 오래 걸릴 것으로 예상되면 애플리케이션에서 Cloud Tasks 또는 Pub/Sub를 사용하여 요청을 큐에 추가할 수 있습니다.
다음 단계
표준 환경에서 앱이 사용하는 서비스를 가변형 환경의 유사 항목에 매핑