Terhubung dari Cloud Run

Halaman ini berisi informasi dan contoh untuk menghubungkan ke instance Cloud SQL dari layanan yang berjalan di Cloud Run.

Untuk petunjuk langkah demi langkah cara menjalankan aplikasi web sampel Cloud Run yang terhubung ke Cloud SQL, lihat panduan memulai untuk terhubung dari Cloud Run ini.

Cloud SQL adalah layanan database yang terkelola sepenuhnya untuk membantu Anda menyiapkan, memelihara, mengelola, dan mengatur database relasional di cloud.

Cloud Run adalah platform komputasi terkelola yang memungkinkan Anda menjalankan container secara langsung di atas infrastruktur Google Cloud.

Menyiapkan instance Cloud SQL

  1. Aktifkan Cloud SQL Admin API di project Google Cloud yang menjadi sumber koneksi, jika Anda belum melakukannya:

    Enable the API

  2. Buat instance Cloud SQL untuk SQL Server. Sebaiknya pilih lokasi instance Cloud SQL di region yang sama dengan layanan Cloud Run Anda untuk latensi yang lebih baik, menghindari beberapa biaya jaringan, dan mengurangi risiko kegagalan lintas region.

    Secara default, Cloud SQL menetapkan alamat IP publik ke instance baru. Anda juga memiliki opsi untuk menetapkan alamat IP pribadi. Untuk mengetahui informasi selengkapnya tentang opsi konektivitas untuk keduanya, lihat halaman Menghubungkan Ringkasan.

Mengonfigurasi Cloud Run

Langkah-langkah untuk mengonfigurasi Cloud Run bergantung pada jenis alamat IP yang Anda tetapkan ke instance Cloud SQL. Jika Anda merutekan semua traffic keluar melalui traffic keluar VPC Langsung atau konektor Akses VPC Serverless, gunakan alamat IP pribadi. Bandingkan kedua metode keluar jaringan.

IP Publik (default)

Cloud Run mendukung koneksi ke Cloud SQL untuk SQL Server melalui IP publik menggunakan konektor Go, Java, dan Python.

  • Pastikan instance memiliki alamat IP publik. Anda dapat memverifikasinya di halaman Ringkasan untuk instance Anda di konsol Google Cloud. Jika perlu menambahkan alamat IP, lihat Mengonfigurasi halaman IP publik untuk mendapatkan petunjuk.
  • Dapatkan INSTANCE_CONNECTION_NAME untuk instance Anda. Anda dapat menemukan nilai ini di halaman Ringkasan untuk instance di konsol Google Cloud atau dengan menjalankan perintah gcloud sql instances describe berikut:
    gcloud sql instances describe INSTANCE_NAME
       
    Ganti INSTANCE_NAME dengan nama instance Cloud SQL Anda.
  • Dapatkan CLOUD_RUN_SERVICE_ACCOUNT_NAME untuk layanan Cloud Run Anda. Anda dapat menemukan nilai ini di halaman IAM dari project yang menghosting layanan Cloud Run di konsol Google Cloud atau dengan menjalankan perintah gcloud run services describe berikut di project yang menghosting layanan Cloud Run:
    gcloud run services describe CLOUD_RUN_SERVICE_NAME
    --region CLOUD_RUN_SERVICE_REGION --format="value(spec.template.spec.serviceAccountName)"
       
    Ganti variabel berikut:
    • CLOUD_RUN_SERVICE_NAME: nama layanan Cloud Run Anda
    • CLOUD_RUN_SERVICE_REGION: region layanan Cloud Run Anda
  • Konfigurasikan akun layanan untuk layanan Cloud Run Anda. Pastikan akun layanan memiliki peran dan izin Cloud SQL yang sesuai untuk terhubung ke Cloud SQL.
    • Akun layanan untuk layanan Anda memerlukan salah satu peran IAM berikut:
      • Cloud SQL Client (Pilihan)
      • Cloud SQL Admin
      Atau, Anda dapat menetapkan izin IAM berikut secara manual:
      • cloudsql.instances.connect
      • cloudsql.instances.get
  • Jika menambahkan koneksi Cloud SQL ke layanan baru, Anda harus membuat layanan Anda di-container dan diupload ke Container Registry atau Artifact Registry. Jika Anda belum memiliki koneksi, lihat petunjuk tentang mem-build dan men-deploy image container ini.

Seperti perubahan konfigurasi lainnya, menetapkan konfigurasi baru untuk koneksi Cloud SQL akan membuat revisi Cloud Run baru. Revisi berikutnya juga akan otomatis mendapatkan koneksi Cloud SQL ini, kecuali jika Anda membuat pembaruan eksplisit untuk mengubahnya.

Konsol

  1. Buka Cloud Run

  2. Mulai konfigurasi layanan. Untuk menambahkan koneksi Cloud SQL ke layanan yang ada, lakukan hal berikut:

    1. Dari daftar Layanan, klik nama layanan yang Anda inginkan.
    2. Di bagian Lihat di Cloud Functions, klik nama layanan.
    3. Klik Edit and Redeploy.
  3. Aktifkan koneksi ke instance Cloud SQL:
    1. Klik Container, Variables & Secrets, Connections, Security .
    2. Klik tab Container.
    3. Scroll ke Koneksi Cloud SQL.
    4. Klik Tambahkan koneksi.
    5. Klik tombol Aktifkan Admin Cloud SQL jika Anda belum mengaktifkan Cloud SQL Admin API.

    Menambahkan koneksi Cloud SQL

    • Jika Anda menambahkan koneksi ke instance Cloud SQL di project Anda, pilih instance Cloud SQL yang Anda inginkan dari menu.
    • Jika Anda menggunakan instance Cloud SQL dari project lain, pilih string koneksi kustom di menu, lalu masukkan nama lengkap koneksi instance dalam format PROJECT-ID:REGION:INSTANCE-ID.
    • Untuk menghapus koneksi, tahan kursor ke kanan koneksi untuk menampilkan ikon Hapus, lalu klik ikon tersebut.
  4. Klik Buat atau Deploy.

Command line

Sebelum menggunakan salah satu perintah berikut, lakukan penggantian berikut:

  • IMAGE dengan image yang Anda deploy
  • SERVICE_NAME dengan nama layanan Cloud Run Anda
  • INSTANCE_CONNECTION_NAME dengan nama koneksi instance dari instance Cloud SQL, atau daftar nama koneksi yang dipisahkan koma.

    Jika Anda men-deploy penampung baru, gunakan perintah berikut:

    gcloud run deploy \
      --image=IMAGE \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME
    Jika Anda mengupdate layanan yang sudah ada, gunakan perintah berikut:
    gcloud run services update SERVICE_NAME \
      --add-cloudsql-instances=INSTANCE_CONNECTION_NAME

Terraform

Kode berikut membuat container Cloud Run dasar, dengan instance Cloud SQL yang terhubung.

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

  deletion_protection = false # set to "true" in production

  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. Terapkan perubahan dengan memasukkan terraform apply.
  2. Verifikasi perubahan dengan memeriksa layanan Cloud Run, mengklik tab Revisi, lalu tab Koneksi.

IP Pribadi

Jika akun layanan yang memberi otorisasi merupakan bagian dari project yang berbeda dengan project yang berisi instance Cloud SQL, lakukan tindakan berikut:

  • Di kedua project, aktifkan Cloud SQL Admin API.
  • Untuk akun layanan di project yang berisi instance Cloud SQL, tambahkan izin IAM.
Traffic keluar VPC Langsung dan konektor menggunakan alamat IP pribadi untuk menangani komunikasi ke jaringan VPC Anda. Untuk terhubung langsung dengan alamat IP pribadi menggunakan salah satu metode keluar ini, lakukan hal berikut:
  1. Pastikan instance Cloud SQL yang dibuat sebelumnya memiliki alamat IP pribadi. Untuk menambahkan alamat IP internal, lihat Mengonfigurasi IP pribadi.
  2. Konfigurasi metode keluar untuk terhubung ke jaringan VPC yang sama dengan instance Cloud SQL Anda. Perhatikan kondisi berikut:
    • Traffic keluar VPC Langsung dan Akses VPC Serverless mendukung komunikasi ke jaringan VPC yang terhubung menggunakan Cloud VPN dan Peering Jaringan VPC.
    • Traffic keluar VPC langsung dan Akses VPC Serverless tidak mendukung jaringan lama.
    • Kecuali jika Anda menggunakan VPC Bersama, konektor harus memiliki project dan region yang sama dengan resource yang menggunakannya, meskipun konektor dapat mengirim traffic ke resource di region yang berbeda.
  3. Hubungkan menggunakan alamat IP pribadi instance dan port 1433.

Menghubungkan ke Cloud SQL

Setelah mengonfigurasi Cloud Run, Anda dapat terhubung ke instance Cloud SQL.

IP Publik (default)

Untuk jalur IP publik, Cloud Run menyediakan enkripsi dan menghubungkan menggunakan konektor Cloud SQL.

Terhubung dengan konektor Cloud SQL

Konektor Cloud SQL adalah library khusus bahasa yang menyediakan enkripsi dan otorisasi berbasis IAM saat terhubung ke instance Cloud SQL.

Python

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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

Untuk menemukan cuplikan ini dalam konteks aplikasi web, lihat README pada GitHub.

Catatan:

  • CLOUD_SQL_CONNECTION_NAME harus direpresentasikan sebagai <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>
  • Lihat persyaratan versi factory soket JDBC untuk file pom.xml di sini .


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);
  }
}

Go

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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
}

Menggunakan Secret Manager

Google merekomendasikan agar Anda menggunakan Secret Manager untuk menyimpan informasi sensitif seperti kredensial SQL. Anda dapat meneruskan secret sebagai variabel lingkungan atau memasangnya sebagai volume dengan Cloud Run.

Setelah membuat secret di Secret Manager, update layanan yang ada dengan perintah berikut:

Command line

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

Kode berikut membuat resource rahasia untuk menyimpan nilai pengguna, sandi, dan nama database dengan aman menggunakan google_secret_manager_secret dan google_secret_manager_secret_version. Perhatikan bahwa Anda harus mengupdate akun layanan komputasi project agar memiliki akses ke setiap secret.


# 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
}

Update resource Cloud Run utama untuk menyertakan secret baru.

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

  deletion_protection = false # set to "true" in production

  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]
}

Terapkan perubahan dengan memasukkan terraform apply.

Contoh perintah menggunakan versi secret, latest; Namun, Google merekomendasikan untuk menyematkan secret ke versi tertentu, SECRET_NAME:v1.

IP Pribadi

Untuk jalur IP pribadi, aplikasi Anda terhubung langsung ke instance melalui jaringan VPC. Metode ini menggunakan TCP untuk terhubung langsung ke instance Cloud SQL tanpa menggunakan Proxy Auth Cloud SQL.

Terhubung dengan TCP

Hubungkan menggunakan alamat IP pribadi instance Cloud SQL Anda sebagai host dan port 1433.

Python

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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

Untuk menemukan cuplikan ini dalam konteks aplikasi web, lihat README pada GitHub.

Catatan:

  • CLOUD-SQL-CONNECTION-NAME harus ditampilkan sebagai <MY-PROJECT>:<INSTANCE-REGION><INSTANCE-NAME>
  • Menggunakan argumen ipTypes=PRIVATE akan memaksa SocketFactory untuk terhubung dengan IP pribadi yang terkait dengan instance.
  • Lihat persyaratan versi factory soket JDBC untuk file pom.xml di sini .


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

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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);
};

Go

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di GitHub.

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;
    }
}

Praktik terbaik dan informasi lainnya

Anda dapat menggunakan Proxy Auth Cloud SQL saat menguji aplikasi Anda secara lokal. Lihat panduan memulai penggunaan Proxy Auth Cloud SQL mendapatkan petunjuk terperinci.

Anda juga dapat menguji menggunakan Proxy Cloud SQL melalui container Docker.

Kumpulan Koneksi

Koneksi ke database pokok dapat terputus, entah oleh server database itu sendiri, atau oleh infrastruktur platform. Sebaiknya gunakan library klien yang mendukung kumpulan koneksi yang secara otomatis menghubungkan kembali koneksi klien yang rusak. Untuk contoh yang lebih detail tentang cara menggunakan kumpulan koneksi, lihat halaman Mengelola koneksi database.

Batas Koneksi

Baik Cloud SQL edisi MySQL maupun PostgreSQL menerapkan batas maksimum pada koneksi serentak, dan batas ini dapat bervariasi bergantung pada mesin database yang dipilih (lihat Kuota dan Batas Cloud SQL).

Instance container Cloud Run dibatasi hingga 100 koneksi ke database Cloud SQL. Setiap instance layanan atau tugas Cloud Run dapat memiliki 100 koneksi ke database. Seiring meningkatnya skala layanan atau tugas ini, jumlah total koneksi per deployment dapat bertambah.

Anda dapat membatasi jumlah maksimum koneksi yang digunakan per instance dengan menggunakan kumpulan koneksi. Untuk contoh yang lebih detail mengenai cara membatasi jumlah koneksi, lihat halaman Mengelola koneksi database.

Batas Kuota API

Cloud Run menyediakan mekanisme yang terhubung menggunakan Proxy Auth Cloud SQL, yang menggunakan Cloud SQL Admin API. Batas kuota API berlaku untuk Proxy Auth Cloud SQL. Kuota Cloud SQL Admin API yang digunakan sekitar dua kali lipat jumlah instance Cloud SQL yang dikonfigurasi oleh jumlah instance Cloud Run dari layanan tertentu yang di-deploy pada satu waktu. Anda dapat membatasi atau meningkatkan jumlah instance Cloud Run untuk mengubah kuota API yang digunakan.

Langkah selanjutnya