Как перезапустить стандартную службу Google App Engine - PullRequest
0 голосов
/ 17 марта 2019

Контекст: у меня есть приложение, которое обслуживает интерактивные графики и анализ данных. Чтобы рассчитать графики и сводки данных, он использует набор данных, который загружается при инициализации приложения путем запроса Google BigQuery. Затем данные сохраняются как глобальная переменная (в памяти) и используются во всех вычислениях данных и графиках, которые могут выполняться разными пользователями (каждый пользователь сохраняет в своем сеансе свои собственные фильтры / маску).

Этот набор данных изменяется в BigQuery один раз в день в течение ночи (я знаю точную дату и время обновления). Как только данные обновляются в BigQuery, я хочу, чтобы глобальная переменная набора данных была обновлена.

Я знаю, что правильным решением было бы вызывать базу данных по каждому запросу пользователя, но большая задержка запросов BigQuery не делает это хорошим решением, и я не могу использовать другую базу данных.

Единственное решение, с которым я сталкивался до сих пор, - это перезапустить сервис Google App Engine (все экземпляры) после обновления данных BigQuery. Обратите внимание, что это должно быть запланированное действие, выполняемое программно.

Мои вопросы:

  • Если перезапуск службы является наилучшим возможным решением, как мне перезапустить службу?
  • Если есть другой способ выполнить то, что я хочу, пожалуйста, дайте мне знать

Ответы [ 3 ]

0 голосов
/ 17 марта 2019

Один из возможных подходов состоит в том, чтобы запускать запущенные экземпляры (сами по себе, т.е. совершать самоубийство) после обновления набора данных BQ и оставлять GAE запускать новые / заменяющие экземпляры, что будет загружать обновленный набор данных.

Триггер может быть основан на memcache, хранилище данных или облачном хранилище / GCS (все быстрее, чем BQ - меньше штраф за проверку их в каждом запросе). Вы хотите быть уверены, что триггер также не влияет на только что запущенные экземпляры:

  • сделать триггер, например, отметкой времени последнего обновления набора данных BQ
  • добавить глобальную переменную с отметкой времени загрузки набора данных в память
  • триггер сработает, когда отметка времени memcache / datastore на ~ 24 ч (или просто "много") новее, чем та, которая находится в памяти

Для действия, вызывающего выход, я бы попробовал:

  • обычный sys.exit(0) вызов (не совсем уверен, если / как это работает в GAE)
  • возбуждает исключение (не так приятно, оно оставит неприятные следы в журналах). Если вы используете его, постарайтесь сделать его как можно более четким, чтобы свести к минимуму вероятность того, что его случайно интерпретируют как настоящий провал. Может быть что-то вроде:

    assert False, "Intentional crash to force an instance restart"
    

Другой возможный подход заключается в принудительном перезапуске экземпляра извне - путем повторного развертывания приложения с использованием той же строки версии. Отключение, связанное с перезапусками экземпляров, вызванными повторным развертыванием той же версии, на самом деле, поэтому мне не нравится использование реализаций среды на основе версии службы, см. Непрерывная интеграция / развертывание / доставка в Google App Engine, слишком рискованно?

Но чтобы это работало, вам нужна другая среда (ы) для запуска и выполнения развертывания. Это может быть какая-то другая служба GAE или даже Облачная функция (в этом случае использование триггера событий Storage устранит необходимость явного опроса для обновленного условия набора данных).

0 голосов
/ 18 марта 2019

Наконец-то я нашел способ программно перезапустить все экземпляры, используя клиент обнаружения Python API и учетную запись службы.Сначала он получает список активных экземпляров и удаляет их все.Затем выполняет простой запрос для инициирования одного из них.

import requests
from apiclient.discovery import build
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('credentials.json')
scoped_credentials = credentials.with_scopes(['https://www.googleapis.com/auth/appengine.admin',"https://www.googleapis.com/auth/cloud-platform"])
appengine = build(serviceName="appengine",version="v1",credentials=scoped_credentials)

VERSION_ID = "version_id"
PROJECT_ID = "project_id"
SERVICE_ID = "appengine_service_name"
APP_URL = "http://some_url.com"

active_instances_dict = appengine.apps().services().versions().instances().list(servicesId=SERVICE_ID,appsId=PROJECT_ID,versionsId=VERSION_ID).execute()
list_of_instances = active_instances_dict["instances"]

for instance in list_of_instances:
    appengine.apps().services().versions().instances().delete(servicesId=SERVICE_ID,appsId=PROJECT_ID,
                  versionsId=VERSION_ID,instancesId=instance["id"]).execute()

requests.get(url=APP_URL)
0 голосов
/ 17 марта 2019

Вероятно, хорошей практикой является кэширование вашего набора данных в процессе работы;если вы знаете, что данные не изменились.тогда нет необходимости запрашивать BigQuery для этого.

Однако ваш набор данных меняется, только один раз в день.

Итак, я думаю, что ваш подход должен состоять в том, чтобы пересмотреть ваше приложение, чтобы оно обновлялоськэшированная копия набора данных BigQuery каждый день и stop | блокирует ваших пользователей от запроса набора данных при его изменении.

На самом деле вам нужно изменять набор данных только в том случае, если пользователь его запрашивает (нетнеобходимо обновить набор данных в дни, когда это не нужно никому из пользователей), поэтому, в зависимости от времени, которое требуется для обновления, и ожиданий ваших пользователей в отношении задержки, вы можете запустить обновление по запросу пользователя: изменился ли набор данных?Если это так, заблокируйте этот запрос, обновите данные и затем ответьте пользователю.

Я предполагаю, что вы уже решили проблему, заключающуюся в том, что графики и расчеты данных ваших пользователей будут отличаться для разных наборов данных.

...