Verbindung über Cloud Functions herstellen

Diese Seite enthält Informationen und Beispiele für das Herstellen einer Verbindung zu einer Cloud SQL-Instanz über einen Dienst, der in Cloud Functions ausgeführt wird.

Für eine Schritt-für-Schritt-Anleitung zum Ausführen einer mit Cloud SQL verbundenen Cloud Functions-Beispielwebanwendung finden Sie weitere Informationen unter: Kurzanleitung zum Herstellen einer Verbindung von Cloud Functions.

Cloud SQL ist ein vollständig verwalteter Datenbankdienst, mit dem Sie Ihre relationalen Datenbanken in der Cloud einrichten, warten und verwalten können.

Cloud Functions ist eine einfache Computing-Lösung für Entwickler zum Erstellen zweckgebundener Funktionen, mit denen auf Cloud-Ereignisse reagiert werden kann, ohne einen Server oder eine Laufzeitumgebung verwalten zu müssen.

Cloud SQL-Instanz einrichten

  1. Aktivieren Sie die Cloud SQL Admin API in dem Google Cloud-Projekt, über das Sie eine Verbindung herstellen, falls noch nicht geschehen:

    Aktivieren Sie die API

  2. Cloud SQL for MySQL-Instanz erstellen

    Standardmäßig weist Cloud SQL einer neuen Instanz eine öffentliche IP-Adresse zu. Sie können aber auch eine private IP-Adresse zuweisen. Weitere Informationen zu den Verbindungsoptionen für beide Möglichkeiten finden Sie auf der Seite Verbindungsübersicht.

Cloud Functions konfigurieren

Die Schritte zum Konfigurieren von Cloud Functions hängen vom Typ der IP-Adresse ab, die Sie der Cloud SQL-Instanz zugewiesen haben.

Öffentliche IP-Adresse (Standard)

So konfigurieren Sie Cloud Functions, um Verbindungen zu einer Cloud SQL-Instanz zu ermöglichen:

  • Bestätigen Sie, dass die oben erstellte Instanz eine öffentliche IP-Adresse hat. Sie können dies in der Google Cloud Console auf der Seite Übersicht für die Instanz prüfen. Informationen zum Hinzufügen einer öffentlichen IP-Adresse finden Sie unter Öffentliche IP-Adressen konfigurieren.
  • Rufen Sie den INSTANCE_CONNECTION_NAME der Instanz ab. Dieser Wert ist verfügbar:
    • Auf der Seite Übersicht für die Instanz in der Google Cloud Console oder
    • Indem Sie dazu den folgenden Befehl ausführen: gcloud sql instances describe [INSTANCE_NAME]
  • Konfigurieren Sie das Dienstkonto für Ihre Funktion. Wenn das autorisierende Dienstkonto zu einem anderen Projekt gehört als die Cloud SQL-Instanz, aktivieren Sie die Cloud SQL Admin API und fügen Sie die oben aufgeführten IAM-Berechtigungen für beide Projekte hinzu. Prüfen Sie, ob das Dienstkonto die entsprechenden Cloud SQL-Rollen und -Berechtigungen für die Verbindung mit Cloud SQL hat.
    • Zum Herstellen einer Verbindung zu Cloud SQL benötigt das Dienstkonto eine der folgenden IAM-Rollen:
      • Cloud SQL Client (bevorzugt)
      • Cloud SQL Editor
      • Cloud SQL Admin
      Alternativ können Sie die folgenden IAM-Berechtigungen manuell zuweisen:
      • cloudsql.instances.connect
      • cloudsql.instances.get
  • Wenn Sie Folgendes verwenden: Cloud Functions-(2. Generation) und nicht Cloud Functions (1. Generation) ist Folgendes erforderlich (siehe auch: Cloud Run konfigurieren):
    1. Stellen Sie die Funktion zuerst bereit.
      Zu Beginn der Erstellung einer Cloud Functions-Funktion in der Google Cloud Console ist der zugrunde liegende Cloud Run-Dienst noch nicht erstellt. Sie können eine Cloud SQL-Verbindung erst konfigurieren, wenn der Dienst erstellt wurde (durch Bereitstellung der Cloud Functions-Funktion).
    2. Klicken Sie in der Google Cloud Console rechts oben auf der Seite Funktionsdetails unter Unterstützt durch Cloud Run auf den Link, um auf den zugrunde liegenden Cloud Run-Dienst zuzugreifen.
    3. Wählen Sie auf der Cloud Run-Seite Dienstdetails den Tab Neue Überarbeitung bearbeiten und bereitstellen aus.
    4. Folgen Sie den Standardschritten (wie bei jeder Konfigurationsänderung), um eine neue Konfiguration für eine Cloud SQL-Verbindung festzulegen.
      Dadurch wird eine neue Cloud Run-Überarbeitung erstellt. Nachfolgende Überarbeitungen erhalten diese Cloud SQL-Verbindung automatisch, sofern Sie sie nicht explizit ändern.

Private IP-Adresse

Wenn das autorisierende Dienstkonto zu einem anderen Projekt gehört als zu dem, das die Cloud SQL-Instanz enthält, gehen Sie so vor:

  • Aktivieren Sie in beiden Projekten die Cloud SQL Admin API.
  • Fügen Sie für das Dienstkonto in dem Projekt, das die Cloud SQL-Instanz enthält, die IAM-Berechtigungen hinzu.
Ein Connector für serverlosen VPC-Zugriff verwendet private IP-Adressen, um die Kommunikation mit Ihrem VPC-Netzwerk zu verarbeiten. So stellen Sie eine direkte Verbindung mithilfe privater IP-Adressen her:
  1. Achten Sie darauf, dass die oben erstellte Cloud SQL-Instanz eine private IP-Adresse hat. Eine Anleitung zum Hinzufügen einer IP-Adresse finden Sie unter Private IP-Adresse konfigurieren.
  2. Erstellen Sie einen Connector für serverlosen VPC-Zugriff im selben VPC-Netzwerk wie Ihre Cloud SQL-Instanz. Beachten Sie folgende Bedingungen:
    • Wenn Sie keine freigegebene VPC verwenden, muss sich ein Connector im selben Projekt und in derselben Region wie die Ressource befinden, von der er verwendet wird. Der Connector kann jedoch Traffic an Ressourcen in anderen Regionen senden.
    • Der serverlose VPC-Zugriff unterstützt die Kommunikation mit VPC-Netzwerken, die über Cloud VPN und VPC-Netzwerk-Peering verbunden sind.
    • Der serverlose VPC-Zugriff unterstützt keine Legacy-Netzwerke.
  3. Konfigurieren Sie Cloud Functions für die Verwendung des Connectors.
  4. Stellen Sie eine Verbindung über die private IP-Adresse der Instanz und den Port 3306 her.

Verbindung mit Cloud SQL herstellen

Nachdem Sie Cloud Functions konfiguriert haben, können Sie eine Verbindung zu Ihrer Cloud SQL-Instanz herstellen.

Öffentliche IP-Adresse (Standard)

Für öffentliche IP-Pfade bietet Cloud Functions Verschlüsselung und stellt auf zwei Arten eine Verbindung über den Cloud SQL-Auth-Proxy her:

Private IP-Adresse

Bei privaten IP-Pfaden stellt die Anwendung eine direkte Verbindung zur Instanz über ein VPC-Netzwerk her. Bei dieser Methode wird über TCP eine direkte Verbindung zur Cloud SQL-Instanz hergestellt, ohne den Cloud SQL Auth-Proxy zu verwenden.

Mit TCP verbinden

Stellen Sie eine Verbindung mithilfe der privaten IP-Adresse Ihrer Cloud SQL-Instanz als Host und Port 3306 her.

Python

Wenn Sie dieses Snippet im Kontext einer Webanwendung sehen möchten, rufen Sie die README-Datei auf GitHub auf.

import os

import sqlalchemy

def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
    """Initializes a TCP connection pool for a Cloud SQL instance of MySQL."""
    # Note: Saving credentials in environment variables is convenient, but not
    # secure - consider a more secure solution such as
    # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
    # keep secrets safe.
    db_host = os.environ[
        "INSTANCE_HOST"
    ]  # e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
    db_user = os.environ["DB_USER"]  # e.g. 'my-db-user'
    db_pass = os.environ["DB_PASS"]  # e.g. 'my-db-password'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'
    db_port = os.environ["DB_PORT"]  # e.g. 3306

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # mysql+pymysql://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
        sqlalchemy.engine.url.URL.create(
            drivername="mysql+pymysql",
            username=db_user,
            password=db_pass,
            host=db_host,
            port=db_port,
            database=db_name,
        ),
        # ...
    )
    return pool

Java

Wenn Sie dieses Snippet im Kontext einer Webanwendung sehen möchten, rufen Sie die README-Datei auf GitHub auf.

Hinweis:

  • INSTANCE_CONNECTION_NAME sollte als <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME> dargestellt werden
  • Die Verwendung des Arguments ipTypes=PRIVATE erzwingt, dass die SocketFactory eine Verbindung zur zugeordneten privaten IP-Adresse einer Instanz herstellen kann.
  • Die Anforderungen für die JDBC Socket Factory-Version der pom.xml-Datei finden Sie hier.


import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class TcpConnectionPoolFactory extends ConnectionPoolFactory {

  // Saving credentials in environment variables is convenient, but not secure - consider a more
  // secure solution such as https://cloud.google.com/secret-manager/ to help keep secrets safe.
  private static final String DB_USER = System.getenv("DB_USER");
  private static final String DB_PASS = System.getenv("DB_PASS");
  private static final String DB_NAME = System.getenv("DB_NAME");

  private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
  private static final String DB_PORT = System.getenv("DB_PORT");

  public static DataSource createConnectionPool() {
    // The configuration object specifies behaviors for the connection pool.
    HikariConfig config = new HikariConfig();

    // The following URL is equivalent to setting the config options below:
    // jdbc:mysql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?user=<DB_USER>&password=<DB_PASS>
    // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
    // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

    // Configure which instance and what database user to connect with.
    config.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", "mysql"
    config.setPassword(DB_PASS); // e.g. "my-password"

    // ... Specify additional connection properties here.
    // ...

    // Initialize the connection pool using the configuration object.
    return new HikariDataSource(config);
  }
}

Node.js

Wenn Sie dieses Snippet im Kontext einer Webanwendung sehen möchten, rufen Sie die README-Datei auf GitHub auf.

const mysql = require('promise-mysql');
const fs = require('fs');

// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
const createTcpPool = async config => {
  // Note: Saving credentials in environment variables is convenient, but not
  // secure - consider a more secure solution such as
  // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
  // keep secrets safe.
  const dbConfig = {
    host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
    port: process.env.DB_PORT, // e.g. '3306'
    user: process.env.DB_USER, // e.g. 'my-db-user'
    password: process.env.DB_PASS, // e.g. 'my-db-password'
    database: process.env.DB_NAME, // e.g. 'my-database'
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return mysql.createPool(dbConfig);
};

Einfach loslegen (Go)

Wenn Sie dieses Snippet im Kontext einer Webanwendung sehen möchten, rufen Sie die README-Datei auf GitHub auf.

package cloudsql

import (
	"crypto/tls"
	"crypto/x509"
	"database/sql"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/go-sql-driver/mysql"
)

// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
func connectTCPSocket() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.", k)
		}
		return v
	}
	// Note: Saving credentials in environment variables is convenient, but not
	// secure - consider a more secure solution such as
	// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
	// keep secrets safe.
	var (
		dbUser    = mustGetenv("DB_USER")       // e.g. 'my-db-user'
		dbPwd     = mustGetenv("DB_PASS")       // e.g. 'my-db-password'
		dbName    = mustGetenv("DB_NAME")       // e.g. 'my-database'
		dbPort    = mustGetenv("DB_PORT")       // e.g. '3306'
		dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	)

	dbURI := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true",
		dbUser, dbPwd, dbTCPHost, dbPort, dbName)

	// dbPool is the pool of database connections.
	dbPool, err := sql.Open("mysql", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}

	// ...

	return dbPool, nil
}

PHP

Wenn Sie dieses Snippet im Kontext einer Webanwendung sehen möchten, rufen Sie die README-Datei auf GitHub auf.

namespace Google\Cloud\Samples\CloudSQL\MySQL;

use PDO;
use PDOException;
use RuntimeException;
use TypeError;

class DatabaseTcp
{
    public static function initTcpDatabaseConnection(): PDO
    {
        try {
            // Note: Saving credentials in environment variables is convenient, but not
            // secure - consider a more secure solution such as
            // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
            // keep secrets safe.
            $username = getenv('DB_USER'); // e.g. 'your_db_user'
            $password = getenv('DB_PASS'); // e.g. 'your_db_password'
            $dbName = getenv('DB_NAME'); // e.g. 'your_db_name'
            $instanceHost = getenv('INSTANCE_HOST'); // e.g. '127.0.0.1' ('172.17.0.1' for GAE Flex)

            // Connect using TCP
            $dsn = sprintf('mysql:dbname=%s;host=%s', $dbName, $instanceHost);

            // Connect to the database
            $conn = new PDO(
                $dsn,
                $username,
                $password,
                # ...
            );
        } catch (TypeError $e) {
            throw new RuntimeException(
                sprintf(
                    'Invalid or missing configuration! Make sure you have set ' .
                        '$username, $password, $dbName, and $instanceHost (for TCP mode). ' .
                        'The PHP error was %s',
                    $e->getMessage()
                ),
                $e->getCode(),
                $e
            );
        } catch (PDOException $e) {
            throw new RuntimeException(
                sprintf(
                    'Could not connect to the Cloud SQL Database. Check that ' .
                        'your username and password are correct, that the Cloud SQL ' .
                        'proxy is running, and that the database exists and is ready ' .
                        'for use. For more assistance, refer to %s. The PDO error was %s',
                    'https://cloud.google.com/sql/docs/mysql/connect-external-app',
                    $e->getMessage()
                ),
                $e->getCode(),
                $e
            );
        }

        return $conn;
    }
}

Best Practices und weitere Informationen

Sie können für den lokalen Test Ihrer Anwendung den Cloud SQL Auth-Proxy verwenden. Eine ausführliche Anleitung dazu finden Sie unter Kurzanleitung zur Verwendung des Cloud SQL Auth-Proxys.

Verbindungspools

Verbindungen zu den zugrunde liegenden Datenbanken können entweder vom Datenbankserver selbst oder von der Infrastruktur getrennt werden, die Cloud Functions verwendet. Verwenden Sie eine Clientbibliothek, die Verbindungspools unterstützt. Diese Verbindungspools sollten unterbrochene Clientverbindungen wiederum automatisch wieder verbinden. Außerdem empfehlen wir, einen globalen Verbindungspool zu verwenden. Dies erhöht die Wahrscheinlichkeit, dass Ihre Funktion dieselbe Verbindung für nachfolgende Aufrufe der Funktion verwendet und dass die Verbindung automatisch getrennt wird, wenn die Instanz entfernt wird (automatisches Herunterskalieren). Ausführliche Beispiele zu Verbindungspools finden Sie unter Datenbankverbindungen verwalten.

Verbindungseinschränkungen

In Cloud SQL gibt es ein maximales Limit für gleichzeitige Verbindungen. Dieses Limit kann je nach ausgewähltem Datenbankmodul variieren. Weitere Informationen finden Sie auf der Seite Kontingente und Limits für Cloud SQL. Es empfiehlt sich, eine Verbindung mit Cloud Functions zu verwenden. Allerdings muss die maximale Anzahl der Verbindungen dann unbedingt auf 1 festgelegt werden.

Achten Sie möglichst darauf, einen Verbindungspool nur für Funktionen zu initialisieren, die Zugriff auf die Datenbank benötigen. Bei einigen Verbindungspools werden Verbindungen auf Abruf erstellt, was zusätzliche Ressourcen verbrauchen und auf Ihre Verbindungslimits angerechnet werden kann. Aus diesem Grund wird die Verwendung der verzögerten Initialisierung empfohlen, um das Erstellen eines Verbindungspools zu verzögern, bis es erforderlich ist. Der Verbindungspool wird nur in Funktionen aufgenommen, für die er verwendet wird.

Ausführliche Beispiele zum Begrenzen der Anzahl von Verbindungen finden Sie unter Datenbankverbindungen verwalten.

API-Kontingentlimits

Cloud Functions bietet einen Mechanismus zum Herstellen einer Verbindung über den Cloud SQL Auth-Proxy, der die Cloud SQL Admin API verwendet. Für den Cloud SQL Auth-Proxy gelten deshalb API-Kontingentlimits. Das verwendete Cloud SQL Admin API-Kontingent ist ungefähr das Doppelte der Anzahl der konfigurierten Cloud SQL-Instanzen multipliziert mit der Gesamtzahl der bereitgestellten Funktionen. Sie können die Anzahl der maximalen gleichzeitigen Aufrufe festlegen, um das erwartete verbrauchte API-Kontingent zu ändern. Für Cloud Functions gelten außerdem Ratenbegrenzungen für die Anzahl der API-Aufrufe, die pro 100 Sekunden zulässig sind.

Nächste Schritte