Verbindung von der flexiblen App Engine-Umgebung zu Cloud SQL herstellen

Diese Seite enthält Informationen und Beispiele für das Herstellen einer Verbindung von einem Dienst, der in der flexiblen App Engine-Umgebung ausgeführt wird, zu einer Cloud SQL-Instanz.

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

App Engine ist eine vollständig verwaltete, serverlose Plattform für die Entwicklung und das Hosting von Webanwendungen in großem Umfang. Sie können für die Entwicklung Ihrer Anwendungen aus mehreren gängigen Sprachen, Bibliotheken und Frameworks auswählen. App Engine übernimmt dann die Bereitstellung von Servern und die bedarfsgerechte Skalierung Ihrer Anwendungsinstanzen.

Cloud SQL-Instanz einrichten

  1. Aktivieren Sie die Cloud SQL 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.

Flexible App Engine-Umgebung konfigurieren

Die Schritte zum Konfigurieren der flexiblen App Engine-Umgebung hängen vom Typ der IP-Adresse ab, die Sie der Cloud SQL-Instanz zugewiesen haben.

Öffentliche IP-Adresse (Standard)

So konfigurieren Sie die flexible App Engine-Umgebung, um Verbindungen zu einer Cloud SQL-Instanz zu ermöglichen:

  1. 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 IP-Adresse finden Sie auf der Seite Öffentliche IP-Verbindungen konfigurieren.
  2. 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].
  3. Das Dienstkonto, mit dem Ihre Anwendung Aufrufe an Cloud SQL authentifiziert, braucht die entsprechenden Cloud SQL-Rollen und -Berechtigungen.
    • Das Dienstkonto für Ihren Dienst benötigt eine der folgenden IAM-Rollen:
      • Cloud SQL Client (bevorzugt)
      • Cloud SQL Editor
      • Cloud SQL Admin
      Sie können stattdessen auch manuell die beiden folgenden IAM-Berechtigungen zuweisen:
      • cloudsql.instances.connect
      • cloudsql.instances.get
      Eine ausführliche Anleitung zum Hinzufügen von IAM-Rollen zu einem Dienstkonto finden Sie unter Dienstkonten Rollen zuweisen.

    Standardmäßig autorisiert Ihre Anwendung Ihre Verbindungen mit dem Dienstkonto der flexiblen App Engine-Umgebung. Dieses Dienstkonto hat das Format PROJECT_ID@appspot.gserviceaccount.com.

    Wenn das autorisierende Dienstkonto zu einem anderen Projekt gehört als die Cloud SQL-Instanz, müssen die Cloud SQL Admin API und die IAM-Berechtigungen für beide Projekte hinzugefügt werden.

  4. Aktualisieren Sie die Datei app.yaml Ihres Projekts mit der Option, die am besten funktioniert. Sie können eine durch Kommas getrennte Liste von Instanzen verwenden, um mehrere Optionen gleichzeitig anzugeben.

    Unix Domain Socket aktivieren

    Zur Aktivierung eines Unix Domain Sockets fügen Sie der Datei app.yaml Ihres Projekts eine der folgenden Einstellungen hinzu, je nachdem, ob Sie eine Verbindung zu einer oder mehreren Instanzen herstellen möchten:

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME
    

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME,INSTANCE_CONNECTION_NAME_2,...
    

    TCP-Port aktivieren

    Zur Aktivierung eines lokalen TCP-Ports fügen Sie der Datei app.yaml Ihres Projekts eine der folgenden Einstellungen hinzu, je nachdem, ob Sie eine Verbindung zu einer oder mehreren Instanzen herstellen möchten:

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME=tcp:PORT
    

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME_1=tcp:PORT_1,INSTANCE_CONNECTION_NAME_2=tcp:PORT_2,...
    

Private IP-Adresse

Wenn Sie eine Verbindung zu Ihrer Cloud SQL-Instanz über eine private IP-Adresse herstellen möchten, muss sich die Bereitstellung der flexiblen App Engine-Umgebung im selben VPC-Netzwerk wie Ihre Cloud SQL-Instanz befinden. Eine Anleitung zum Angeben eines VPC-Netzwerks für Ihre Bereitstellung finden Sie in der Konfigurationsdokumentation zu Netzwerkeinstellungen.

Nach der Bereitstellung kann sich Ihre Anwendung direkt über die private IP-Adresse und den Port 5432 Ihrer Instanz verbinden.

Verbindung zu Cloud SQL herstellen

Nachdem Sie die flexible App Engine-Umgebung konfiguriert haben, können Sie eine Verbindung zu Ihrer Cloud SQL-Instanz herstellen.

Öffentliche IP-Adresse (Standard)

Für öffentliche IP-Pfade bietet die flexible App Engine-Umgebung Verschlüsselung und Verbindungen über den Cloud SQL-Auth-Proxy über Unix-Sockets.

Private IP-Adresse

Mit TCP verbinden

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:
    # postgresql+pg8000://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
    sqlalchemy.engine.url.URL.create(
        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.

Hinweis:

  • CLOUD_SQL_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.

// Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
// which is preferred to using the Cloud SQL Proxy with Unix sockets.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.

// 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"

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 = async 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_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

C#

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

            // Equivalent connection string:
            // "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<DB_HOST>;Database=<DB_NAME>;"
            var connectionString = new NpgsqlConnectionStringBuilder()
            {
                // The Cloud SQL proxy provides encryption between the proxy and instance.
                SslMode = SslMode.Disable,

                // Remember - storing secrets in plain text is potentially unsafe. Consider using
                // something like https://cloud.google.com/secret-manager/docs/overview to help keep
                // secrets secret.
                Host = Environment.GetEnvironmentVariable("DB_HOST"),     // e.g. '127.0.0.1'
                // Set Host to 'cloudsql' when deploying to App Engine Flexible environment
                Username = Environment.GetEnvironmentVariable("DB_USER"), // e.g. 'my-db-user'
                Password = Environment.GetEnvironmentVariable("DB_PASS"), // e.g. 'my-db-password'
                Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'
            };
            connectionString.Pooling = true;
            // Specify additional properties here.
            return connectionString;

Ruby

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

development:
  adapter: postgresql
  # Configure additional properties here.
  username: <%= ENV["DB_USER"] %>  # e.g. "my-database-user"
  password: <%= ENV["DB_PASS"] %> # e.g. "my-database-password"
  database: <%= ENV.fetch("DB_NAME") { "vote_development" } %>
  host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT")  { 5432 }%>

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';
// $dbName = 'your_db_name';
// $dbHost = "127.0.0.1";

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

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

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 zugrunde liegenden Datenbanken können unterbrochen werden, entweder vom Datenbankserver selbst oder von der zugrunde liegenden Infrastruktur. Um dies zu vermeiden, empfehlen wir Ihnen die Verwendung einer Clientbibliothek, die Verbindungspools und das automatische Herstellen einer neuen Verbindung unterstützt.

Verbindungseinschränkungen

Eine App Engine-Instanz, die in einer Standardumgebung ausgeführt wird, kann maximal 100 Verbindungen gleichzeitig zu einer Instanz aufbauen. Bei Anwendungen, die in PHP 5.5 geschrieben sind, ist die Anzahl der gleichzeitigen Verbindungen auf 60 beschränkt. Dieses Limit gilt pro Anwendungsinstanz. Das bedeutet, dass jede Instanz der App Engine-Anwendung so viele Verbindungen zur Datenbank herstellen und bei der Skalierung die Gesamtzahl der Verbindungen pro Bereitstellung erhöhen kann. Weitere Informationen finden Sie unter Elemente skalieren.

Sie können die maximale Anzahl der pro Instanz verwendeten Verbindungen mithilfe eines Verbindungspools begrenzen. Ausführlichere Beispiele zum Begrenzen der Anzahl an Verbindungen finden Sie auf der Seite Datenbankverbindungen verwalten.

App Engine-Anwendungen unterliegen je nach Nutzung und Umgebung bestimmten Zeitlimits für Anfragen. Weitere Informationen finden Sie in den Erläuterungen dazu, wie Instanzen in der App Engine-Standardumgebung bzw. der flexiblen App Engine-Umgebung verwaltet werden.

API-Kontingentlimits

App Engine bietet einen Mechanismus zum Herstellen einer Verbindung über den Cloud SQL Auth-Proxy, der die Cloud SQL API verwendet. Für den Cloud SQL Auth-Proxy gelten deshalb API-Kontingentlimits. Das verwendete Cloud SQL Admin API-Kontingent umfasst ungefähr das Doppelte der Anzahl der Cloud SQL-Instanzen, die durch die Anzahl der App Engine-Instanzen eines bestimmten Dienstes konfiguriert werden, der jeweils einmal bereitgestellt wird. App Engine-Anwendungen unterliegen außerdem weiteren Kontingenten und Limits von App Engine. Diese finden Sie auf der Seite mit den Kontingenten für App Engine.