준비 요청 구성으로 성능 향상

준비 요청을 사용하면 앱 코드가 새로 생성된 인스턴스에 로드되는 동안 요청 및 응답의 지연 시간을 줄일 수 있습니다.

App Engine이 새 인스턴스에 앱 코드를 로드해야 하는 경우가 종종 있습니다. 다음과 같은 상황에서 인스턴스를 로드할 수 있습니다.

  • 특정 버전의 앱을 다시 배포하는 경우
  • 요청의 부하가 현재 실행 중인 인스턴스 집합의 용량을 초과해 새 인스턴스가 생성되는 경우
  • 기본 인프라나 실제 하드웨어를 유지보수 및 수리하는 경우

앱 코드를 새 인스턴스에 로드하면 로드 요청이 발생할 수 있습니다. 로드 요청으로 인해 사용자의 요청 지연 시간이 증가할 수 있으나 준비 요청을 사용하면 이러한 지연 시간을 방지할 수 있습니다. 준비 요청은 실시간 요청이 새 인스턴스에 도달하기 전에 앱 코드를 이 인스턴스에 로드합니다.

애플리케이션에 준비 요청을 사용 설정하면 App Engine이 애플리케이션에 새 인스턴스가 필요한 시점을 감지하고 준비 요청을 시작하여 새 인스턴스를 초기화합니다. 하지만 이러한 감지 시도가 항상 성공하는 것은 아닙니다. 따라서 앱에 준비 요청이 사용 설정되어 있더라도 로드 요청이 발생할 수 있습니다. 예를 들어 앱에서 어떠한 트래픽도 처리하고 있지 않으면 앱에 대한 최초 요청은 항상 준비 요청이 아닌 로드 요청이 됩니다.

준비 요청은 App Engine 애플리케이션에 대한 다른 요청과 마찬가지로 인스턴스 시간을 사용합니다. 준비 요청을 사용 설정한 경우 대부분 애플리케이션은 로드 요청이 아닌 준비 요청에서 초기화되므로 인스턴스 시간이 거의 증가하지 않습니다. 그러나 준비 요청 중에 사전 캐싱과 같은 추가 작업을 수행하면 인스턴스 시간 사용량이 증가할 수 있습니다. min_idle_instances0보다 높게 설정하면 인스턴스가 처음 시작될 때 준비 요청이 발생할 수 있지만 그 후에도 인스턴스를 계속 사용할 수 있습니다.

준비 요청 사용 설정

준비 요청은 사용자가 제공한 구성에 맞게 인스턴스 자동 확장을 제어하는 App Engine 스케줄러에서 사용됩니다. 준비 요청을 사용 설정하면 App Engine이 /_ah/warmupGET 요청을 보냅니다. 이 요청에 필요한 핸들러를 구현하여 애플리케이션 데이터 사전 캐싱과 같은 애플리케이션별 태스크를 수행할 수 있습니다.

스케줄러는 인스턴스가 더 많이 필요하다고 판단하면 인스턴스를 시작합니다. 스케줄러는 준비 요청을 사용하여 인스턴스를 시작하므로, 준비 요청이 중지되더라도 로그에 나타날 수 있습니다.

준비 요청이 항상 호출되는 것은 아닙니다. 예를 들어 첫 번째로 시작되는 인스턴스이거나 트래픽 양이 갑자기 증가하는 등의 일부 경우에는 로드 요청이 대신 전송됩니다. 하지만 준비 요청이 사용 설정된 경우에는 이미 준비된 인스턴스에 요청을 보내는 것이 '최고의 방법'입니다.

준비 요청을 사용 설정하려면 app.yaml 파일의 inbound_services 지시문에 warmup 요소를 추가합니다. 예를 들면 다음과 같습니다.

inbound_services:
- warmup

핸들러 등록

프로젝트의 app.yaml 파일에서 준비 요청을 처리하는 스크립트를 등록할 수 있습니다. 예를 들면 다음과 같습니다.

inbound_services:
- warmup

handlers:
- url: /_ah/warmup
  script: main.py
  login: admin

이 예시는 main.py 파일로 /_ah/warmup 요청 경로에 대한 준비 요청을 리슨하도록 핸들러를 등록합니다.

핸들러 만들기

/_ah/warmup으로 전송된 요청을 처리하는 핸들러를 만듭니다. 핸들러는 앱에 필요한 준비 로직을 수행합니다. 다음 예시는 이전 예시를 바탕으로 빌드한 것입니다.

import webapp2

class MyWarmUpCode(webapp2.RequestHandler):
  """
  This class handles the warmup request. You should add any code that you
  need to execute in the `get` method, such as populating caches, and ensure
  that you return a successful HTTP response.
  """

  def get(self):

      # Your warmup logic goes here.

      # Return a successful response to indicate the logic completed.
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.write('Warmup successful')

  # ...

application = webapp2.WSGIApplication(
    [
        ('/_ah/warmup', MyWarmUpCode),
        # Other handlers
        # ...
    ]
)

다음 단계

Memcache와 같은 메모리 내 Datastore에 값을 저장하면 앱에서 쿼리 없이 더 빠르게 데이터에 액세스할 수 있습니다.

예를 들어 사이트에서 현재 인기 있는 글 목록을 만들어 저장하려는 경우, 먼저 준비 단계에서 해당 목록을 빌드한 후 Memcache에 저장합니다. 이렇게 하면 사용자 요청 수신 시 App Engine에서 Datastore 쿼리를 수행할 필요가 없으므로 애플리케이션에서 사용자 요청을 더 빠르게 처리할 수 있습니다.