Verbindung von Cloud Functions zu Cloud SQL 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.

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 eigenständiger und 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 Projekt, über das Sie eine Verbindung herstellen, falls noch nicht geschehen:

    Aktivieren Sie die API

  2. Erstellen Sie eine Cloud SQL for PostgreSQL-Instanz.

    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:

  • Achten Sie darauf, 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 Ihre Instanz nachprüfen. Eine Anleitung zum Hinzufügen einer öffentlichen IP-Adresse finden Sie auf der Seite Öffentliche IP-Verbindungen konfigurieren.
  • Rufen Sie den INSTANCE_CONNECTION_NAME für Ihre Instanz ab. Sie finden ihn in der Google Cloud Console auf der Seite Übersicht für Ihre Instanz oder über folgenden Befehl: gcloud sql instances describe [INSTANCE_NAME].
  • Konfigurieren Sie das Dienstkonto für Ihre Funktion. Achten Sie darauf, dass 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 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.

Private IP-Adresse

Ein Connector für serverlosen VPC-Zugriff übernimmt die Kommunikation mit Ihrem VPC-Netzwerk. So stellen Sie eine direkte Verbindung mithilfe einer privaten IP-Adresse 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 auf der Seite Private IP-Adresse konfigurieren.
  2. Erstellen Sie einen Connector für serverlosen VPC-Zugriff im selben VPC-Netzwerk wie Ihre Cloud SQL-Instanz.
  3. 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.

  4. Konfigurieren Sie Cloud Functions für die Verwendung des Connectors.
  5. Stellen Sie eine Verbindung über die private IP-Adresse der Instanz und den Port 5432 her.

Verbindung zu Cloud SQL herstellen

Nachdem Sie Cloud Functions konfiguriert haben, können Sie eine Verbindung zu Ihrer Cloud SQL-Instanz herstellen. Cloud Functions bietet einen Mechanismus, der Verbindungen über den Cloud SQL-Proxy herstellt.

Öffentliche IP-Adresse (Standard)

Verbindung mit Unix Domain Sockets herstellen

Wenn alles richtig konfiguriert ist, können Sie den Dienst mit dem Unix Domain Socket der Cloud SQL-Instanz verbinden, auf den im Dateisystem der Umgebung unter folgendem Pfad zugegriffen wird: /cloudsql/INSTANCE_CONNECTION_NAME.

Solche Verbindungen werden ohne zusätzliche Konfiguration automatisch verschlüsselt. Die unten gezeigten Codebeispiele sind Auszüge aus umfassenderen Beispielen auf der GitHub-Website. Klicken Sie auf View on GitHub, um mehr Code zu sehen.

Python

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

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_socket_dir = os.environ.get("DB_SOCKET_DIR", "/cloudsql")
cloud_sql_connection_name = os.environ["CLOUD_SQL_CONNECTION_NAME"]

pool = sqlalchemy.create_engine(

    # Equivalent URL:
    # postgres+pg8000://<db_user>:<db_pass>@/<db_name>
    #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
    sqlalchemy.engine.url.URL(
        drivername="postgresql+pg8000",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        database=db_name,  # e.g. "my-database-name"
        query={
            "unix_sock": "{}/{}/.s.PGSQL.5432".format(
                db_socket_dir,  # e.g. "/cloudsql"
                cloud_sql_connection_name)  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
        }
    ),
    **db_config
)

Java

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

// 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:postgresql:///<DB_NAME>?cloudSqlInstance=<CLOUD_SQL_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.postgres.SocketFactory&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:postgresql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);

// The ipTypes argument can be used to specify a comma delimited list of preferred IP types
// for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
// SocketFactory to connect with an instance's associated private IP.
config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

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

// Initialize the connection pool using the configuration object.
DataSource pool = 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 createUnixSocketPool = config => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';

  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
    },
    // ... Specify additional properties here.
    ...config,
  });
};

Go

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

var (
	dbUser                 = mustGetenv("DB_USER")                  // e.g. 'my-db-user'
	dbPwd                  = mustGetenv("DB_PASS")                  // e.g. 'my-db-password'
	instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
	dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
)

socketDir, isSet := os.LookupEnv("DB_SOCKET_DIR")
if !isSet {
	socketDir = "/cloudsql"
}

var dbURI string
dbURI = fmt.Sprintf("user=%s password=%s database=%s host=%s/%s", dbUser, dbPwd, dbName, socketDir, instanceConnectionName)

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

// ...

return dbPool, nil

PHP

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

// $username = 'your_db_user';
// $password = 'yoursupersecretpassword';
// $db_name = 'your_db_name';
// $cloud_sql_connection_name = getenv("CLOUD_SQL_CONNECTION_NAME");
// $socket_dir = getenv('DB_SOCKET_DIR') ?: '/cloudsql';

// Connect using UNIX sockets
$dsn = sprintf(
    'pgsql:dbname=%s;host=%s/%s',
    $db_name,
    $socket_dir,
    $cloud_sql_connection_name
);

// Connect to the database.
$conn = new PDO($dsn, $username, $password, $conn_config);

Private IP-Adresse

Verbindung mit TCP herstellen

Stellen Sie eine direkte Verbindung über die private IP-Adresse und den Port 5432 für Ihre Instanz her.

Python

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

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_host = os.environ["DB_HOST"]

# Extract host and port from db_host
host_args = db_host.split(":")
db_hostname, db_port = host_args[0], int(host_args[1])

pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # postgres+pg8000://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
    sqlalchemy.engine.url.URL(
        drivername="postgresql+pg8000",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        host=db_hostname,  # e.g. "127.0.0.1"
        port=db_port,  # e.g. 5432
        database=db_name  # e.g. "my-database-name"
    ),
    **db_config
)

Java

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

// 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:postgresql:///<DB_NAME>?cloudSqlInstance=<CLOUD_SQL_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.postgres.SocketFactory&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:postgresql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);

// The ipTypes argument can be used to specify a comma delimited list of preferred IP types
// for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
// SocketFactory to connect with an instance's associated private IP.
config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

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

// Initialize the connection pool using the configuration object.
DataSource pool = 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 createTcpPool = config => {
  // Extract host and port from socket address
  const dbSocketAddr = process.env.DB_HOST.split(':'); // e.g. '127.0.0.1:5432'

  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
      host: dbSocketAddr[0], // e.g. '127.0.0.1'
      port: dbSocketAddr[1], // e.g. '5432'
    },
    // ... Specify additional properties here.
    ...config,
  });
};

Go

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

var (
	dbUser    = mustGetenv("DB_USER")     // e.g. 'my-db-user'
	dbPwd     = mustGetenv("DB_PASS")     // e.g. 'my-db-password'
	dbTcpHost = mustGetenv("DB_TCP_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	dbPort    = mustGetenv("DB_PORT")     // e.g. '5432'
	dbName    = mustGetenv("DB_NAME")     // e.g. 'my-database'
)

var dbURI string
dbURI = fmt.Sprintf("host=%s user=%s password=%s port=%s database=%s", dbTcpHost, dbUser, dbPwd, dbPort, dbName)

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

// ...

return dbPool, nil

PHP

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

// $username = 'your_db_user';
// $password = 'yoursupersecretpassword';
// $db_name = 'your_db_name';
// $host = "127.0.0.1";

// Connect using TCP
$dsn = sprintf('pgsql:dbname=%s;host=%s', $db_name, $host);

// Connect to the database
$conn = new PDO($dsn, $username, $password, $conn_config);

Best Practices und weitere Informationen

Sie können für einen lokalen Test Ihrer Anwendung den Cloud SQL-Proxy verwenden. Eine detaillierte Anleitung dazu finden Sie im Schnellstart zur Verwendung des Proxys für lokale Tests.

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-Proxy, der die Cloud SQL Admin API verwendet. Für den Cloud SQL-Proxy gelten deshalb API-Kontingentlimits.