Verbindung über Cloud Run 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 Run ausgeführt wird.

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

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

Cloud Run ist eine verwaltete Computing-Plattform, mit der Sie Container direkt auf der Google Cloud-Infrastruktur ausführen können.

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:

    Enable the API

  2. Cloud SQL for SQL Server-Instanz erstellen Wir empfehlen, einen Cloud SQL-Instanzstandort in derselben Region wie Ihr Cloud Run-Dienst auszuwählen, um die Latenz zu verbessern, einige Netzwerkkosten zu vermeiden und das Risiko von regionenübergreifenden Ausfällen zu reduzieren.

    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 Run konfigurieren

Die Schritte zum Konfigurieren von Cloud Functions hängen vom Typ der IP-Adresse ab, die Sie der Cloud SQL-Instanz zugewiesen haben. Wenn Sie den gesamten ausgehenden Traffic über ausgehenden Direct VPC-Traffic oder einen Connector für serverlosen VPC-Zugriff weiterleiten, verwenden Sie eine private IP-Adresse. Vergleich der beiden Methoden für ausgehenden Netzwerktraffic

Öffentliche IP-Adresse (Standard)

Cloud Run unterstützt die Verbindung zu Cloud SQL for SQL Server über eine öffentliche IP-Adresse mit den Go-, Java- und Python-Connectors.

  • 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.
  • 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 Ihren Dienst. Achten Sie darauf, dass das Dienstkonto die entsprechenden Cloud SQL-Rollen und -Berechtigungen für die Verbindung mit Cloud SQL hat.
    • Das Dienstkonto für Ihren Dienst benötigt eine der folgenden IAM-Rollen:
      • Cloud SQL Client (bevorzugt)
      • Cloud SQL Admin
      Sie können stattdessen auch manuell die folgenden IAM-Berechtigungen zuweisen:
      • cloudsql.instances.connect
      • cloudsql.instances.get

Wie bei jeder Konfigurationsänderung führt das Festlegen einer neuen Konfiguration für die Cloud SQL-Verbindung zum Erstellen einer neuen Cloud Run-Überarbeitung. Nachfolgende Überarbeitungen erhalten dann automatisch ebenfalls diese Cloud SQL-Verbindung, sofern Sie sie nicht explizit ändern.

Console

  1. Zu Cloud Run

  2. Beginnen Sie mit der Konfiguration des Dienstes:

    • Wenn Sie eine Cloud SQL-Verbindung zu einem neuen Dienst hinzufügen:

      Der Dienst muss containerisiert und in Container Registry oder Artifact Registry hochgeladen worden sein. Wenn Sie noch keinen Dienst haben, lesen Sie die folgende Anleitung zum Erstellen und Bereitstellen eines Container-Images.

    • Wenn Sie Cloud SQL-Verbindungen zu einem vorhandenen Dienst hinzufügen:
      1. Klicken Sie auf den Dienstnamen.
      2. Klicken Sie auf den Tab Neue Überarbeitung bearbeiten und bereitstellen.
  3. Verbindung zu einer Cloud SQL-Instanz aktivieren:
    1. Klicken Sie auf Container, Variablen und Secrets, Verbindungen, Sicherheit.
    2. Klicken Sie auf den Tab Container.
    3. Scrollen Sie nach unten zu Cloud SQL-Verbindungen.
    4. Klicken Sie auf Verbindung hinzufügen.
    5. Klicken Sie auf die Schaltfläche Cloud SQL-Administrator aktivieren, wenn Sie die Cloud SQL Admin API noch nicht aktiviert haben.

    Cloud SQL-Verbindung hinzufügen

    • Wenn Sie in Ihrem Projekt eine Verbindung zu einer Cloud SQL-Instanz hinzufügen, wählen Sie die gewünschte Cloud SQL-Instanz aus dem Drop-down-Menü aus.
    • Wenn Sie eine Cloud SQL-Instanz aus einem anderen Projekt verwenden möchten, wählen Sie im Drop-down-Menü die Option Benutzerdefinierter Verbindungsstring aus und geben Sie dann den vollständigen Namen der Instanzverbindung im Format PROJECT-ID:REGION:INSTANCE-ID ein.
    • Zum Löschen einer Verbindung bewegen Sie den Mauszeiger rechts neben die Verbindung, um das Papierkorbsymbol sichtbar zu machen, und klicken Sie darauf.
  4. Klicken Sie auf Erstellen oder Bereitstellen.

Befehlszeile

Bevor Sie einen der unten aufgeführten Befehle verwenden, nehmen Sie die folgenden Ersetzungen vor:

  • IMAGE durch das Image, das Sie bereitstellen
  • SERVICE_NAME durch den Namen Ihres Cloud Run-Dienstes
  • INSTANCE_CONNECTION_NAME durch den Namen der Verbindung Ihrer Cloud SQL-Instanz oder eine durch Kommas getrennte Liste von Verbindungsnamen

    Wenn Sie einen neuen Container bereitstellen, verwenden Sie den folgenden Befehl:

    gcloud run deploy \
      --image=IMAGE \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
    Zum Aktualisieren eines vorhandenen Dienstes führen Sie den folgenden Befehl aus:
    gcloud run services update SERVICE_NAME \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME

Terraform

Mit dem folgenden Code wird ein Cloud Run-Basiscontainer mit einer verbundenen Cloud SQL-Instanz erstellt.

resource "google_cloud_run_v2_service" "default" {
  name     = "cloudrun-service"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello:latest" # Image to deploy

      volume_mounts {
        name       = "cloudsql"
        mount_path = "/cloudsql"
      }
    }
    volumes {
      name = "cloudsql"
      cloud_sql_instance {
        instances = [google_sql_database_instance.default.connection_name]
      }
    }
  }
  client     = "terraform"
  depends_on = [google_project_service.secretmanager_api, google_project_service.cloudrun_api, google_project_service.sqladmin_api]
}

  1. Um die Änderungen anzuwenden, geben Sie terraform apply ein.
  2. Prüfen Sie die Änderungen, indem Sie den Dienst Cloud Run aktivieren und auf den Tab Revisionen und dann auf den Tab Verbindungen klicken.

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.
Ausgehender Direct VPC-Traffic und Connectors verwenden private IP-Adressen für die Kommunikation mit Ihrem VPC-Netzwerk. So stellen Sie eine direkte Verbindung zu privaten IP-Adressen mithilfe einer dieser Methoden für ausgehenden Traffic her:
  1. Achten Sie darauf, dass die oben erstellte Cloud SQL-Instanz eine private IP-Adresse hat. Informationen zum Hinzufügen einer internen IP-Adresse finden Sie unter Private IP-Adresse konfigurieren.
  2. Konfigurieren Sie Ihre Methode für ausgehenden Traffic, um eine Verbindung zum selben VPC-Netzwerk wie Ihre Cloud SQL-Instanz herzustellen. Beachten Sie folgende Bedingungen:
    • Ausgehender Direct VPC-Traffic und serverloser VPC-Zugriff unterstützen beide die Kommunikation mit VPC-Netzwerken, die über Cloud VPN und VPC-Netzwerk-Peering verbunden sind.
    • Ausgehender Direct VPC-Traffic und serverloser VPC-Zugriff unterstützen keine Legacy-Netzwerke.
    • 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.
  3. Stellen Sie eine Verbindung über die private IP-Adresse der Instanz und den Port 1433 her.

Verbindung mit Cloud SQL herstellen

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

Öffentliche IP-Adresse (Standard)

Für öffentliche IP-Pfade bietet Cloud Run eine Verschlüsselung und stellt eine Verbindung über die Cloud SQL-Connectors her.

Mit Cloud SQL-Connectors verbinden

Die Cloud SQL-Connectors sind Bibliotheken, die für das Herstellen einer Verbindung zu einer Cloud SQL-Instanz eine Verschlüsselung sowie eine IAM-basierte Autorisierung ermöglichen.

Python

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

import os

from google.cloud.sql.connector import Connector, IPTypes
import pytds

import sqlalchemy

def connect_with_connector() -> sqlalchemy.engine.base.Engine:
    """
    Initializes a connection pool for a Cloud SQL instance of SQL Server.

    Uses the Cloud SQL Python Connector package.
    """
    # 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.

    instance_connection_name = os.environ[
        "INSTANCE_CONNECTION_NAME"
    ]  # e.g. 'project:region:instance'
    db_user = os.environ.get("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'

    ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

    connector = Connector(ip_type)

    connect_args = {}
    # If your SQL Server instance requires SSL, you need to download the CA
    # certificate for your instance and include cafile={path to downloaded
    # certificate} and validate_host=False. This is a workaround for a known issue.
    if os.environ.get("DB_ROOT_CERT"):  # e.g. '/path/to/my/server-ca.pem'
        connect_args = {
            "cafile": os.environ["DB_ROOT_CERT"],
            "validate_host": False,
        }

    def getconn() -> pytds.Connection:
        conn = connector.connect(
            instance_connection_name,
            "pytds",
            user=db_user,
            password=db_pass,
            db=db_name,
            **connect_args
        )
        return conn

    pool = sqlalchemy.create_engine(
        "mssql+pytds://",
        creator=getconn,
        # ...
    )
    return pool

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 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 ConnectorConnectionPoolFactory extends ConnectionPoolFactory {

  // 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.
  private static final String INSTANCE_CONNECTION_NAME =
      System.getenv("INSTANCE_CONNECTION_NAME");
  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");

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

    // The following is equivalent to setting the config options below:
    // jdbc:sqlserver://;user=<DB_USER>;password=<DB_PASS>;databaseName=<DB_NAME>;
    // socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
    // socketFactoryConstructorArg=<INSTANCE_CONNECTION_NAME>

    // 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
        .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
    config.setUsername(DB_USER); // e.g. "root", "sqlserver"
    config.setPassword(DB_PASS); // e.g. "my-password"
    config.addDataSourceProperty("databaseName", DB_NAME);

    config.addDataSourceProperty("socketFactoryClass",
        "com.google.cloud.sql.sqlserver.SocketFactory");
    config.addDataSourceProperty("socketFactoryConstructorArg", INSTANCE_CONNECTION_NAME);

    // The Java Connector provides SSL encryption, so it should be disabled
    // at the driver level.
    config.addDataSourceProperty("encrypt", "false");

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

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

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 (
	"context"
	"database/sql"
	"fmt"
	"log"
	"net"
	"os"

	"cloud.google.com/go/cloudsqlconn"
	mssql "github.com/denisenkom/go-mssqldb"
)

type csqlDialer struct {
	dialer     *cloudsqlconn.Dialer
	connName   string
	usePrivate bool
}

// DialContext adheres to the mssql.Dialer interface.
func (c *csqlDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	var opts []cloudsqlconn.DialOption
	if c.usePrivate {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}
	return c.dialer.Dial(ctx, c.connName, opts...)
}

func connectWithConnector() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Fatal Error in connect_connector.go: %s environment variable not set.\n", 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'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	dbURI := fmt.Sprintf("user id=%s;password=%s;database=%s;", dbUser, dbPwd, dbName)
	c, err := mssql.NewConnector(dbURI)
	if err != nil {
		return nil, fmt.Errorf("mssql.NewConnector: %w", err)
	}
	dialer, err := cloudsqlconn.NewDialer(context.Background())
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDailer: %w", err)
	}
	c.Dialer = &csqlDialer{
		dialer:     dialer,
		connName:   instanceConnectionName,
		usePrivate: usePrivate != "",
	}

	dbPool := sql.OpenDB(c)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Secret Manager verwenden

Google empfiehlt die Verwendung von Secret Manager zum Speichern vertraulicher Informationen wie SQL-Anmeldedaten. Mit Cloud Run können Sie Secrets als Umgebungsvariablen übergeben oder als Volume bereitstellen.

Nachdem Sie in Secret Manager ein Secret erstellt haben, aktualisieren Sie einen vorhandenen Dienst mit folgendem Befehl:

Befehlszeile

gcloud run services update SERVICE_NAME \
  --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
  --update-env-vars=INSTANCE_CONNECTION_NAME=INSTANCE_CONNECTION_NAME_SECRET \
  --update-secrets=DB_USER=DB_USER_SECRET:latest \
  --update-secrets=DB_PASS=DB_PASS_SECRET:latest \
  --update-secrets=DB_NAME=DB_NAME_SECRET:latest

Terraform

Mit der folgenden Secret-Ressource werden die Werte für Datenbanknutzer, Passwort und Name sicher mit google_secret_manager_secret und google_secret_manager_secret_version gespeichert. Beachten Sie, dass Sie das Compute-Dienstkonto des Projekts aktualisieren müssen, um Zugriff auf jedes Secret zu erhalten.


# Create dbuser secret
resource "google_secret_manager_secret" "dbuser" {
  secret_id = "dbusersecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbuser secret
resource "google_secret_manager_secret_version" "dbuser_data" {
  secret      = google_secret_manager_secret.dbuser.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbuser secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbuser" {
  secret_id = google_secret_manager_secret.dbuser.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}


# Create dbpass secret
resource "google_secret_manager_secret" "dbpass" {
  secret_id = "dbpasssecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbpass secret
resource "google_secret_manager_secret_version" "dbpass_data" {
  secret      = google_secret_manager_secret.dbpass.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbpass secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbpass" {
  secret_id = google_secret_manager_secret.dbpass.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}


# Create dbname secret
resource "google_secret_manager_secret" "dbname" {
  secret_id = "dbnamesecret"
  replication {
    auto {}
  }
  depends_on = [google_project_service.secretmanager_api]
}

# Attaches secret data for dbname secret
resource "google_secret_manager_secret_version" "dbname_data" {
  secret      = google_secret_manager_secret.dbname.id
  secret_data = "secret-data" # Stores secret as a plain txt in state
}

# Update service account for dbname secret
resource "google_secret_manager_secret_iam_member" "secretaccess_compute_dbname" {
  secret_id = google_secret_manager_secret.dbname.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" # Project's compute service account
}

Aktualisieren Sie die Cloud Run-Hauptressource, um die neuen Secrets aufzunehmen.

resource "google_cloud_run_v2_service" "default" {
  name     = "cloudrun-service"
  location = "us-central1"

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello:latest" # Image to deploy

      # Sets a environment variable for instance connection name
      env {
        name  = "INSTANCE_CONNECTION_NAME"
        value = google_sql_database_instance.default.connection_name
      }
      # Sets a secret environment variable for database user secret
      env {
        name = "DB_USER"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbuser.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }
      # Sets a secret environment variable for database password secret
      env {
        name = "DB_PASS"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbpass.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }
      # Sets a secret environment variable for database name secret
      env {
        name = "DB_NAME"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.dbname.secret_id # secret name
            version = "latest"                                      # secret version number or 'latest'
          }
        }
      }

      volume_mounts {
        name       = "cloudsql"
        mount_path = "/cloudsql"
      }
    }
    volumes {
      name = "cloudsql"
      cloud_sql_instance {
        instances = [google_sql_database_instance.default.connection_name]
      }
    }
  }
  client     = "terraform"
  depends_on = [google_project_service.secretmanager_api, google_project_service.cloudrun_api, google_project_service.sqladmin_api]
}

Um die Änderungen anzuwenden, geben Sie terraform apply ein.

Im Beispielbefehl wird die Secret-Version latest verwendet. Google empfiehlt jedoch, das Secret an eine bestimmte Version, SECRET_NAME:v1, anzuheften.

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 1433 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 SQL Server."""
    # 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. 1433

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

    return pool

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.


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

public class TcpConnectionPoolFactory extends ConnectionPoolFactory {

  // 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.
  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();

    // Configure which instance and what database user to connect with.
    config.setJdbcUrl(
        String.format("jdbc:sqlserver://%s:%s;databaseName=%s", INSTANCE_HOST, DB_PORT, DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", "sqlserver"
    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 mssql = require('mssql');

// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of SQL Server.
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 = {
    server: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
    port: parseInt(process.env.DB_PORT), // e.g. 1433
    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'
    options: {
      trustServerCertificate: true,
    },
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return mssql.connect(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 (
	"database/sql"
	"fmt"
	"log"
	"os"
	"strings"

	_ "github.com/denisenkom/go-mssqldb"
)

// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of SQL Server.
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.\n", 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'
		dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
		dbPort    = mustGetenv("DB_PORT")       // e.g. '1433'
		dbName    = mustGetenv("DB_NAME")       // e.g. 'my-database'
	)

	dbURI := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;",
		dbTCPHost, dbUser, dbPwd, dbPort, dbName)

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

	// ...

	return dbPool, nil
}

Ruby

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

tcp: &tcp
  adapter: sqlserver
  # Configure additional properties here.
  # 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: <%= 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("INSTANCE_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT") { 1433 }%> 

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\SQLServer;

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(
                'sqlsrv:server=%s;Database=%s',
                $instanceHost,
                $dbName
            );

            // 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/sqlserver/connect-external-app',
                    $e->getMessage()
                ),
                (int) $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.

Sie können lokale Tests auch mithilfe des Cloud SQL Proxy-Docker-Images ausführen.

Verbindungspools

Verbindungen zu den zugrunde liegenden Datenbanken können entweder vom Datenbankserver selbst oder von der Plattforminfrastruktur unterbrochen werden. Verwenden Sie eine Clientbibliothek, die Verbindungspools unterstützt. Diese Verbindungspools sollten unterbrochene Clientverbindungen wiederum automatisch wieder verbinden. Ausführlichere Beispiele zur Verwendung von Verbindungspools finden Sie unter Datenbankverbindungen verwalten.

Verbindungseinschränkungen

Die MySQL- und PostgreSQL-Editionen von Cloud SQL schreiben eine maximale Anzahl gleichzeitiger Verbindungen vor. Die Limits können je nach verwendetem Datenbankmodul variieren. Weitere Informationen finden Sie auf der Seite Cloud SQL-Kontingente und Limits.

Cloud Run-Containerinstanzen sind auf 100 Verbindungen zu einer Cloud SQL-Datenbank beschränkt. Jede Instanz eines Cloud Run-Dienstes oder -Jobs kann 100 Verbindungen zur Datenbank haben. Wenn dieser Dienst oder Job skaliert wird, kann die Gesamtzahl der Verbindungen pro Bereitstellung wachsen.

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

API-Kontingentlimits

Cloud Run 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 umfasst ungefähr das Doppelte der Anzahl der Cloud SQL-Instanzen, die durch die Anzahl der Cloud Run-Instanzen eines bestimmten Dienstes konfiguriert werden, der jeweils einmal bereitgestellt wird. Sie können die Anzahl der Cloud Run-Instanzen beschränken oder erhöhen, um das erwartete verbrauchte API-Kontingent zu ändern.

Nächste Schritte