Подключение к Google Cloud SQL из функции Google Cloud python3.7 - PullRequest
0 голосов
/ 23 сентября 2019

Я пытаюсь подключиться, используя pymysql, используя код, очень близкий к примеру, приведенному в документации: https://cloud.google.com/functions/docs/sql#functions_sql_mysql-python

База данных имеет публичный ip, без авторизованных сетей (поскольку cf должен использовать сокет), и мой пользователь создал разрешающий доступ из любого места.

Локальный запуск с Cloud Proxy работает нормально, но в Google Cloud я получаю отказ в соединении.

Редактировать: обновленный примерс кодом для локального запуска с env vars

import logging
import os

import pymysql
from pymysql.err import OperationalError


mysql_conn = None


def __get_cursor():
    try:
        return mysql_conn.cursor()
    except OperationalError:
        mysql_conn.ping(reconnect=True)
        return mysql_conn.cursor()


def get_config():
    return {
        'unix_socket': f'/cloudsql/{os.environ["CONNECTION_NAME"]}',
        'user': os.environ['DB_USER'],
        'password': os.environ['DB_PASSWORD'],
        'db': os.environ['DB_NAME'],
        'charset': 'utf8mb4',
        'cursorclass': pymysql.cursors.DictCursor,
        'autocommit': True
    }


def mysql_demo(request):
    global mysql_conn

    if not mysql_conn:
        mysql_config = get_config()
        logging.info('Open db with config: %s', mysql_config)

        try:
            mysql_conn = pymysql.connect(**mysql_config)
        except OperationalError as exception:
            logging.warning('Unable to get db connection: %s', str(exception))
            return

    with __get_cursor() as cursor:
        cursor.execute('SELECT NOW() as now')
        results = cursor.fetchone()
        return str(results['now'])


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    os.environ['CONNECTION_NAME'] = 'my-project:us-central1:cf-test'
    os.environ['DB_USER'] = 'db-user'
    os.environ['DB_PASSWORD'] = 'db-password'
    os.environ['DB_NAME'] = 'db_name'
    logging.info(mysql_demo(None))

Редактировать: дополнительный вывод

При локальном запуске выводится:

INFO:root:2019-09-24 07:11:54

При запуске в качестве облачной функции я получаю вывод: `

2019-09-24 09:14:59.279 CEST test-cloud-sql mesuju89uxuw Open db with config: {'unix_socket': '/cloudsql/boeingfda-jal:us-central1:cf-test', 'user': 'enplore', 'password': 'az2labha', 'db': 'content_enplore_auth', 'charset': 'utf8mb4', 'cursorclass': <class 'pymysql.cursors.DictCursor'>, 'autocommit': True}
2019-09-24 09:14:59.856 CEST test-cloud-sql mesuju89uxuw Unable to get db connection: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")

Ответы [ 2 ]

0 голосов
/ 24 сентября 2019

Похоже, что ваша запись unix_socket не сгенерирована должным образом.Он принимает данные в следующем формате:

'/cloudsql/project-id:region:instance-name'

Пример:

'/cloudsql/my-awesome-project:us-central1:mysqlinst1'

Чтобы получить точное имя соединения, вы можете использовать следующую команду:

gcloud sql instances describe <instance_name> | grep connectionName
0 голосов
/ 23 сентября 2019

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

  • Убедитесь, что API-интерфейс Cloud SQL Admin включен.
  • Убедитесь, что учетная запись службы (по умолчанию service-[YOUR_PROJECT_NUMBER]@gcf-admin-robot.iam.gserviceaccount.com), используемая для запуска экземпляра, имеет правильные разрешения IAM (роль Cloud SQL Client или разрешения cloudsql.instances.connect и cloudsql.instances.get).
  • Наконец, убедитесь, что переменная CONNECTION_NAME не написана с ошибкой.

Наконец, вам следует рассмотреть возможность использования пула соединений (например, SQLAlchemy) и установить максимальное ограничение равным 1. Пул соединений будет обрабатыватьошибки более изящно, и ограничить количество соединений, используемых на экземпляр.

...