Облачная функция работает локально, но дает сбой в GCP (выполнение функции заняло 12681 мс, завершено со статусом: 'cra sh') - PullRequest
0 голосов
/ 30 мая 2020

Вот супер сокращенная версия моего кода (я помещу ссылку на все в комментариях)

import ...

...

def main(data, context):
    log_client = logging.Client()

    log_name = 'cloudfunctions.googleapis.com%2Fcloud-functions'

    res = Resource(type="cloud_function",
                   labels={
                       "function_name": "refresh_classes",
                       "region": os.environ.get("FUNC_REGION")
                   })
    logger = log_client.logger(log_name.format(os.environ.get("PROJECT_ID")))

    db = sqlalchemy.create_engine(
        sqlalchemy.engine.url.URL(
            drivername="mysql+pymysql",
            username=os.environ.get("DB_USER"),
            password=os.environ.get("DB_PASS"),
            host=os.environ.get("DB_HOST"),
            port=3306,
            database=PRIMARY_TABLE_NAME
        ),
        pool_size=5,
        max_overflow=2,
        pool_timeout=30,
        pool_recycle=1800
    )
    start_time = perf_counter()

    check_if_table_exists(db)

    for i in range(START_IDX, END_IDX):
        print(i)
        logger.log_text(f"Checking class with id {i}", resource=res, severity="INFO")

        ...

    logger.log_text(f"Total seconds elapsed: {perf_counter() - start_time}", resource=res, severity="INFO")


if __name__ == '__main__':
    main('data', 'context')

Когда я запускаю вышеупомянутую облачную функцию локально, с моим GOOGLE_APPLICATION_CREDENTIALS настроенным вместе с настроен мой локальный прокси-сервер Cloud MySQL, выполняется подробное облачное ведение журнала, и функция завершается без сбоев, как и ожидалось:

enter image description here

Однако, когда я развертываю все это в GCP и пытаюсь запустить его через консоль (триггер обмена облачными сообщениями), все, что я получаю, это с точки зрения ведения журнала:

enter image description here

фактический текст

{
 insertId: "******"  
 labels: {
  execution_id: "******"   
 }
 logName: "projects/******/logs/cloudfunctions.googleapis.com%2Fcloud-functions"  
 receiveTimestamp: "2020-05-29T22:11:13.435688367Z"  
 resource: {
  labels: {
   function_name: "******"    
   project_id: "******"    
   region: "us-central1"    
  }
  type: "cloud_function"   
 }
 severity: "DEBUG"  
 textPayload: "Function execution started"  
 timestamp: "2020-05-29T22:11:03.069889708Z"  
 trace: "projects/******/traces/******"  
}

{
 insertId: "******"  
 labels: {
  execution_id: "******"   
 }
 logName: "projects/******/logs/cloudfunctions.googleapis.com%2Fcloud-functions"  
 receiveTimestamp: "2020-05-29T22:11:16.331311285Z"  
 resource: {
  labels: {
   function_name: "******"    
   project_id: "******"    
   region: "us-central1"    
  }
  type: "cloud_function"   
 }
 severity: "DEBUG"  
 textPayload: "Function execution took 12362 ms, finished with status: 'crash'"  
 timestamp: "2020-05-29T22:11:15.430033249Z"  
 trace: "projects/******/traces/******"  
}

* я действительно не знаю, какая конфиденциальная информация, а какая нет, поэтому я просто пометил некоторые случайные вещи

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

Функция вылетает раньше регистратор Google даже настроен.

Итак, на этом Дело в том, что я не совсем уверен, что может нарушать мою функцию, и я не знаю, как это выяснить, поскольку ведение журнала в Google Cloud не помогает. Ошибка json имеет свойство trace, которое выглядит очень многообещающим, потому что все, что мне нужно на данный момент, это трассировка стека Python, но я не знаю, есть ли способ это увидеть.

Я должен отметить, что у меня есть переменные среды, настроенные через консоль GCP Cloud Function.

enter image description here

В принципе, есть две вещи, которые могут быть полезны:

  1. как увидеть python трассировку стека сбойной облачной функции
  2. что, конкретно c для моего приложения, могло вызывать это поведение сбоя

1 Ответ

1 голос
/ 30 мая 2020

Итак, я наконец понял, что если вместо запуска вашей облачной функции через Cloud Scheduler вы запустите функцию вручную через Test Function

enter image description here

GCP выдаст вам возбужденное исключение. В моем случае подключение к Cloud MySQL не удалось

Error: function terminated. Recommended action: inspect logs for termination reason. Details:
(pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '**.***.**.***' (timed out)")
(Background on this error at: http://sqlalche.me/e/e3q8)

, поэтому мне просто пришлось ввести переменную среды для переключения между подключением через прокси и unix сокетами , например:

if os.environ.get("ENV") == "local":
    db = sqlalchemy.create_engine(
        sqlalchemy.engine.url.URL(
            drivername="mysql+pymysql",
            username=os.environ.get("DB_USER"),
            password=os.environ.get("DB_PASS"),
            host=os.environ.get("DB_HOST"),
            port=3306,
            database=PRIMARY_TABLE_NAME
        ),
        pool_size=5,
        max_overflow=2,
        pool_timeout=30,
        pool_recycle=1800
    )
else:
    db = sqlalchemy.create_engine(
        sqlalchemy.engine.url.URL(
            drivername="mysql+pymysql",
            username=os.environ.get("DB_USER"),
            password=os.environ.get("DB_PASS"),
            database=PRIMARY_TABLE_NAME,
            query={"unix_socket": "/cloudsql/{}".format(os.environ.get("CLOUD_SQL_CONNECTION_NAME"))}
        ),
        pool_size=5,
        max_overflow=2,
        pool_timeout=30,
        pool_recycle=1800
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...