本頁面包含從在 App Engine 彈性環境中執行的服務連線至 Cloud SQL 執行個體的資訊與範例。
Cloud SQL 是一項全代管資料庫服務,可協助您在雲端設定、維護及管理關聯資料庫。
App Engine 是全代管的無伺服器平台,適用於大規模開發和代管網頁應用程式。您可以選擇多種常見的語言、程式庫和架構來開發應用程式,然後讓 App Engine 負責根據需求佈建伺服器,以及擴充應用程式執行個體。
設定 Cloud SQL 執行個體
- 在您要連線的 Google Cloud 專案中啟用 Cloud SQL Admin API (如果尚未啟用):
- 建立 PostgreSQL 適用的 Cloud SQL 執行個體。建議您選擇與 Cloud Run 服務位於相同區域的 Cloud SQL
執行個體位置,以縮短延遲時間、避免部分網路費用,並降低跨區域故障風險。
根據預設,Cloud SQL 會為新執行個體指派公開 IP 位址。 您也可以選擇指派私人 IP 位址。如要進一步瞭解這兩者的連線選項,請參閱「 連線總覽」頁面。
- 建立執行個體時,您可以選擇執行個體的
伺服器憑證 (CA) 階層,然後將該階層設定為執行個體的
serverCaMode
。如要從 App Engine 彈性環境網頁應用程式連線至執行個體,請務必選取「每個執行個體 CA」選項 (GOOGLE_MANAGED_INTERNAL_CA
) 做為執行個體的伺服器 CA 模式。
設定 App Engine 彈性環境
設定 App Engine 彈性環境的步驟取決於您指派給 Cloud SQL 執行個體的 IP 位址類型。公開 IP (預設)
如要設定 App Engine 彈性環境,以啟用與 Cloud SQL 執行個體的連線,請按照下列步驟操作:
- 確認執行個體有公開 IP 位址。您可以在 Google Cloud 控制台中,前往執行個體的「總覽」頁面確認這項資訊。 如需新增公開 IP,請參閱「設定公開 IP」頁面瞭解操作說明。
- 取得執行個體的 INSTANCE_CONNECTION_NAME。您可以在 Google Cloud console 中,前往執行個體的「Overview」(總覽) 頁面找到這個值,也可以執行下列
gcloud sql instances describe
指令: 將 INSTANCE_NAME 改成 Cloud SQL 執行個體的名稱。gcloud sql instances describe INSTANCE_NAME
確認應用程式用來驗證對 Cloud SQL 呼叫的服務帳戶具有
Cloud SQL Client
IAM 角色。如需將身分與存取權管理角色新增至服務帳戶的詳細操作說明,請參閱為服務帳戶授予角色一文。
根據預設,應用程式會使用
App Engine 彈性環境服務帳戶授權連線。服務帳戶的格式為 PROJECT_ID@appspot.gserviceaccount.com
。
如果授權服務帳戶與 Cloud SQL 執行個體屬於不同專案,則必須為這兩個專案新增 Cloud SQL Admin API 和 IAM 權限。
app.yaml
檔案。
您可以使用以逗號分隔的執行個體清單,一次指定多個選項。
啟用 Unix 網域通訊端
如要啟用 Unix 網域通訊端,請在專案的 app.yaml
檔案中加入下列其中一項,視您要連線至一個或多個執行個體而定:
beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME
beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME,INSTANCE_CONNECTION_NAME_2,...
啟用 TCP 連接埠
如要啟用本機 TCP 連接埠,請在專案的app.yaml
檔案中加入下列其中一項,視您要連線至一個或多個執行個體而定:
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,...
私人 IP
如要透過私人 IP 連線至 Cloud SQL 執行個體,App Engine 彈性環境部署作業必須與 Cloud SQL 執行個體位於相同的虛擬私有雲網路。如需如何為部署作業指定 VPC 網路的說明,請參閱「 網路設定」的設定說明文件。
部署完成後,應用程式就能使用執行個體的私人 IP 位址和通訊埠 5432
直接連線。
連線至 Cloud SQL
設定 App Engine 彈性環境後,即可連線至 Cloud SQL 執行個體。
公開 IP (預設)
如果是公開 IP 路徑,App Engine 彈性環境會提供加密功能,並透過 Cloud SQL Auth Proxy 以三種方式連線:
- 透過 TCP 通訊端
- 透過 Unix 通訊端
- 使用 Cloud SQL 連接器
透過 TCP 連線
使用 172.17.0.1:PORT
直接連線,其中 PORT
是您在 app.yaml
檔案中指定的連接埠。Cloud SQL 驗證 Proxy 會監聽 172.17.0.1
,並將連線加密及轉送至 Cloud SQL 執行個體。
Python
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
import os
import ssl
import sqlalchemy
def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a TCP connection pool for a Cloud SQL instance of Postgres."""
# 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. 5432
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,
password=db_pass,
host=db_host,
port=db_port,
database=db_name,
),
# ...
)
return pool
Java
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
注意:
- CLOUD_SQL_CONNECTION_NAME 應表示為 <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>
- 使用 ipTypes=PRIVATE 引數會強制 SocketFactory 連線至執行個體相關聯的私人 IP
- 請參閱 pom.xml 檔案的 JDBC 通訊端處理站版本規定。
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();
// The following URL is equivalent to setting the config options below:
// jdbc:postgresql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?user=<DB_USER>&password=<DB_PASS>
// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:postgresql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
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
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
const Knex = require('knex');
const fs = require('fs');
// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of Postgres.
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 = {
client: 'pg',
connection: {
host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
port: process.env.DB_PORT, // e.g. '5432'
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'
},
// ... Specify additional properties here.
...config,
};
// Establish a connection to the database.
return Knex(dbConfig);
};
Go
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
package cloudsql
import (
"database/sql"
"fmt"
"log"
"os"
// Note: If connecting using the App Engine Flex Go runtime, use
// "github.com/jackc/pgx/stdlib" instead, since v5 requires
// Go modules which are not supported by App Engine Flex.
_ "github.com/jackc/pgx/v5/stdlib"
)
// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of Postgres.
func connectTCPSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.", k)
}
return v
}
// Note: Saving credentials in environment variables is convenient, but not
// secure - consider a more secure solution such as
// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
// keep secrets safe.
var (
dbUser = mustGetenv("DB_USER") // e.g. 'my-db-user'
dbPwd = mustGetenv("DB_PASS") // e.g. 'my-db-password'
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. '5432'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
)
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: %w", err)
}
// ...
return dbPool, nil
}
C#
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
using Npgsql;
using System;
namespace CloudSql
{
public class PostgreSqlTcp
{
public static NpgsqlConnectionStringBuilder NewPostgreSqlTCPConnectionString()
{
// Equivalent connection string:
// "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
var connectionString = new NpgsqlConnectionStringBuilder()
{
// 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.
Host = Environment.GetEnvironmentVariable("INSTANCE_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'
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = SslMode.Disable,
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;
}
}
}
Ruby
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
tcp: &tcp
adapter: postgresql
# 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") { 5432 }%>
PHP
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
namespace Google\Cloud\Samples\CloudSQL\Postgres;
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('pgsql:dbname=%s;host=%s', $dbName, $instanceHost);
// Connect to the database
$conn = new PDO(
$dsn,
$username,
$password,
# ...
);
} catch (TypeError $e) {
throw new RuntimeException(
sprintf(
'Invalid or missing configuration! Make sure you have set ' .
'$username, $password, $dbName, and $instanceHost (for TCP mode). ' .
'The PHP error was %s',
$e->getMessage()
),
$e->getCode(),
$e
);
} catch (PDOException $e) {
throw new RuntimeException(
sprintf(
'Could not connect to the Cloud SQL Database. Check that ' .
'your username and password are correct, that the Cloud SQL ' .
'proxy is running, and that the database exists and is ready ' .
'for use. For more assistance, refer to %s. The PDO error was %s',
'https://cloud.google.com/sql/docs/postgres/connect-external-app',
$e->getMessage()
),
$e->getCode(),
$e
);
}
return $conn;
}
}
透過 Unix 通訊端連線
正確設定後,您就可以將服務連線至 Cloud SQL 執行個體的 Unix 網域通訊端,該通訊端位於環境的檔案系統中,路徑如下:/cloudsql/INSTANCE_CONNECTION_NAME
。
INSTANCE_CONNECTION_NAME 使用格式 project:region:instance-id
。您可以在Google Cloud 控制台中,前往執行個體的「總覽」頁面查看,也可以執行下列指令:
gcloud sql instances describe [INSTANCE_NAME]
系統會自動加密這些連線,無須進行額外設定。
以下程式碼範例是從 GitHub 網站上的完整範例擷取而來。按一下 View on GitHub
即可查看更多資訊。
Python
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
import os
import sqlalchemy
def connect_unix_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a Unix socket connection pool for a Cloud SQL instance of Postgres."""
# 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_user = os.environ["DB_USER"] # e.g. 'my-database-user'
db_pass = os.environ["DB_PASS"] # e.g. 'my-database-password'
db_name = os.environ["DB_NAME"] # e.g. 'my-database'
unix_socket_path = os.environ[
"INSTANCE_UNIX_SOCKET"
] # e.g. '/cloudsql/project:region:instance'
pool = sqlalchemy.create_engine(
# Equivalent URL:
# postgresql+pg8000://<db_user>:<db_pass>@/<db_name>
# ?unix_sock=<INSTANCE_UNIX_SOCKET>/.s.PGSQL.5432
# Note: Some drivers require the `unix_sock` query parameter to use a different key.
# For example, 'psycopg2' uses the path set to `host` in order to connect successfully.
sqlalchemy.engine.url.URL.create(
drivername="postgresql+pg8000",
username=db_user,
password=db_pass,
database=db_name,
query={"unix_sock": f"{unix_socket_path}/.s.PGSQL.5432"},
),
# ...
)
return pool
Java
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
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 INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
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 URL is equivalent to setting the config options below:
// jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_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", INSTANCE_CONNECTION_NAME);
// Unix sockets are not natively supported in Java, so it is necessary to use the Cloud SQL
// Java Connector to connect. When setting INSTANCE_UNIX_SOCKET, the connector will
// call an external package that will enable Unix socket connections.
// Note: For Java users, the Cloud SQL Java Connector can provide authenticated connections
// which is usually preferable to using the Cloud SQL Proxy with Unix sockets.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
if (INSTANCE_UNIX_SOCKET != null) {
config.addDataSourceProperty("unixSocketPath", INSTANCE_UNIX_SOCKET);
}
// cloudSqlRefreshStrategy set to "lazy" is used to perform a
// refresh when needed, rather than on a scheduled interval.
// This is recommended for serverless environments to
// avoid background refreshes from throttling CPU.
config.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy");
// ... Specify additional connection properties here.
// ...
// Initialize the connection pool using the configuration object.
return new HikariDataSource(config);
}
}
Node.js
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
const Knex = require('knex');
// createUnixSocketPool initializes a Unix socket connection pool for
// a Cloud SQL instance of Postgres.
const createUnixSocketPool = 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.
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: process.env.INSTANCE_UNIX_SOCKET, // e.g. '/cloudsql/project:region:instance'
},
// ... Specify additional properties here.
...config,
});
};
C#
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
using Npgsql;
using System;
namespace CloudSql
{
public class PostgreSqlUnix
{
public static NpgsqlConnectionStringBuilder NewPostgreSqlUnixSocketConnectionString()
{
// Equivalent connection string:
// "Server=<INSTANCE_UNIX_SOCKET>;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
var connectionString = new NpgsqlConnectionStringBuilder()
{
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = SslMode.Disable,
// 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.
Host = Environment.GetEnvironmentVariable("INSTANCE_UNIX_SOCKET"), // e.g. '/cloudsql/project:region:instance'
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;
}
}
}
Go
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
package cloudsql
import (
"database/sql"
"fmt"
"log"
"os"
// Note: If connecting using the App Engine Flex Go runtime, use
// "github.com/jackc/pgx/stdlib" instead, since v5 requires
// Go modules which are not supported by App Engine Flex.
_ "github.com/jackc/pgx/v5/stdlib"
)
// connectUnixSocket initializes a Unix socket connection pool for
// a Cloud SQL instance of Postgres.
func connectUnixSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_unix.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'
unixSocketPath = mustGetenv("INSTANCE_UNIX_SOCKET") // e.g. '/cloudsql/project:region:instance'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
)
dbURI := fmt.Sprintf("user=%s password=%s database=%s host=%s",
dbUser, dbPwd, dbName, unixSocketPath)
// dbPool is the pool of database connections.
dbPool, err := sql.Open("pgx", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
// ...
return dbPool, nil
}
Ruby
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
unix: &unix
adapter: postgresql
# 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" } %>
# Specify the Unix socket path as host
host: "<%= ENV["INSTANCE_UNIX_SOCKET"] %>"
PHP
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
namespace Google\Cloud\Samples\CloudSQL\Postgres;
use PDO;
use PDOException;
use RuntimeException;
use TypeError;
class DatabaseUnix
{
public static function initUnixDatabaseConnection(): 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'
$instanceUnixSocket = getenv('INSTANCE_UNIX_SOCKET'); // e.g. '/cloudsql/project:region:instance'
// Connect using UNIX sockets
$dsn = sprintf(
'pgsql:dbname=%s;host=%s',
$dbName,
$instanceUnixSocket
);
// 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 $instanceUnixSocket (for UNIX socket mode). ' .
'The PHP error was %s',
$e->getMessage()
),
(int) $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/postgres/connect-external-app',
$e->getMessage()
),
(int) $e->getCode(),
$e
);
}
return $conn;
}
}
使用 Cloud SQL 連接器連線
Cloud SQL 連接器是語言專屬的程式庫,可提供加密和 IAM 型授權,用於連線至 Cloud SQL 執行個體。
Python
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
import os
from google.cloud.sql.connector import Connector, IPTypes
import pg8000
import sqlalchemy
def connect_with_connector() -> sqlalchemy.engine.base.Engine:
"""
Initializes a connection pool for a Cloud SQL instance of Postgres.
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["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
# initialize Cloud SQL Python Connector object
connector = Connector(refresh_strategy="LAZY")
def getconn() -> pg8000.dbapi.Connection:
conn: pg8000.dbapi.Connection = connector.connect(
instance_connection_name,
"pg8000",
user=db_user,
password=db_pass,
db=db_name,
ip_type=ip_type,
)
return conn
# The Cloud SQL Python Connector can be used with SQLAlchemy
# using the 'creator' argument to 'create_engine'
pool = sqlalchemy.create_engine(
"postgresql+pg8000://",
creator=getconn,
# ...
)
return pool
Java
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
注意:
- CLOUD_SQL_CONNECTION_NAME 應表示為 <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>
- 如要瞭解 pom.xml 檔案的 JDBC 通訊端處理站版本需求,請參閱 這篇文章 。
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 INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
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 URL is equivalent to setting the config options below:
// jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_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", INSTANCE_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");
// cloudSqlRefreshStrategy set to "lazy" is used to perform a
// refresh when needed, rather than on a scheduled interval.
// This is recommended for serverless environments to
// avoid background refreshes from throttling CPU.
config.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy");
// ... Specify additional connection properties here.
// ...
// Initialize the connection pool using the configuration object.
return new HikariDataSource(config);
}
}
Go
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
package cloudsql
import (
"context"
"database/sql"
"fmt"
"log"
"net"
"os"
"cloud.google.com/go/cloudsqlconn"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/stdlib"
)
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 passwords and other 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")
)
dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPwd, dbName)
config, err := pgx.ParseConfig(dsn)
if err != nil {
return nil, err
}
var opts []cloudsqlconn.Option
if usePrivate != "" {
opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()))
}
// WithLazyRefresh() Option is used to perform refresh
// when needed, rather than on a scheduled interval.
// This is recommended for serverless environments to
// avoid background refreshes from throttling CPU.
opts = append(opts, cloudsqlconn.WithLazyRefresh())
d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
if err != nil {
return nil, err
}
// Use the Cloud SQL connector to handle connecting to the instance.
// This approach does *NOT* require the Cloud SQL proxy.
config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
return d.Dial(ctx, instanceConnectionName)
}
dbURI := stdlib.RegisterConnConfig(config)
dbPool, err := sql.Open("pgx", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
return dbPool, nil
}
Node.js
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
const Knex = require('knex');
const {Connector} = require('@google-cloud/cloud-sql-connector');
// In case the PRIVATE_IP environment variable is defined then we set
// the ipType=PRIVATE for the new connector instance, otherwise defaults
// to public ip type.
const getIpType = () =>
process.env.PRIVATE_IP === '1' || process.env.PRIVATE_IP === 'true'
? 'PRIVATE'
: 'PUBLIC';
// connectWithConnector initializes connection pool for a Cloud SQL instance
// of Postgres using the Cloud SQL Node.js Connector.
const connectWithConnector = 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 connector = new Connector();
const clientOpts = await connector.getOptions({
instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
ipType: getIpType(),
});
const dbConfig = {
client: 'pg',
connection: {
...clientOpts,
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'
},
// ... Specify additional properties here.
...config,
};
// Establish a connection to the database.
return Knex(dbConfig);
};
私人 IP
透過 TCP 連線
使用 Cloud SQL 執行個體的私人 IP 位址做為主機和通訊埠 5432
進行連線。
Python
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
import os
import ssl
import sqlalchemy
def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a TCP connection pool for a Cloud SQL instance of Postgres."""
# 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. 5432
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,
password=db_pass,
host=db_host,
port=db_port,
database=db_name,
),
# ...
)
return pool
Java
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
注意:
- CLOUD_SQL_CONNECTION_NAME 應表示為 <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME>
- 使用 ipTypes=PRIVATE 引數會強制 SocketFactory 連線至執行個體相關聯的私人 IP
- 請參閱 pom.xml 檔案的 JDBC 通訊端處理站版本規定。
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();
// The following URL is equivalent to setting the config options below:
// jdbc:postgresql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?user=<DB_USER>&password=<DB_PASS>
// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:postgresql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
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
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
const Knex = require('knex');
const fs = require('fs');
// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of Postgres.
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 = {
client: 'pg',
connection: {
host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
port: process.env.DB_PORT, // e.g. '5432'
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'
},
// ... Specify additional properties here.
...config,
};
// Establish a connection to the database.
return Knex(dbConfig);
};
Go
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
package cloudsql
import (
"database/sql"
"fmt"
"log"
"os"
// Note: If connecting using the App Engine Flex Go runtime, use
// "github.com/jackc/pgx/stdlib" instead, since v5 requires
// Go modules which are not supported by App Engine Flex.
_ "github.com/jackc/pgx/v5/stdlib"
)
// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of Postgres.
func connectTCPSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.", k)
}
return v
}
// Note: Saving credentials in environment variables is convenient, but not
// secure - consider a more secure solution such as
// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
// keep secrets safe.
var (
dbUser = mustGetenv("DB_USER") // e.g. 'my-db-user'
dbPwd = mustGetenv("DB_PASS") // e.g. 'my-db-password'
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. '5432'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
)
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: %w", err)
}
// ...
return dbPool, nil
}
C#
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
using Npgsql;
using System;
namespace CloudSql
{
public class PostgreSqlTcp
{
public static NpgsqlConnectionStringBuilder NewPostgreSqlTCPConnectionString()
{
// Equivalent connection string:
// "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
var connectionString = new NpgsqlConnectionStringBuilder()
{
// 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.
Host = Environment.GetEnvironmentVariable("INSTANCE_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'
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = SslMode.Disable,
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;
}
}
}
Ruby
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
tcp: &tcp
adapter: postgresql
# 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") { 5432 }%>
PHP
如要查看網頁應用程式中的程式碼片段,請參閱 GitHub 上的 README。
namespace Google\Cloud\Samples\CloudSQL\Postgres;
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('pgsql:dbname=%s;host=%s', $dbName, $instanceHost);
// Connect to the database
$conn = new PDO(
$dsn,
$username,
$password,
# ...
);
} catch (TypeError $e) {
throw new RuntimeException(
sprintf(
'Invalid or missing configuration! Make sure you have set ' .
'$username, $password, $dbName, and $instanceHost (for TCP mode). ' .
'The PHP error was %s',
$e->getMessage()
),
$e->getCode(),
$e
);
} catch (PDOException $e) {
throw new RuntimeException(
sprintf(
'Could not connect to the Cloud SQL Database. Check that ' .
'your username and password are correct, that the Cloud SQL ' .
'proxy is running, and that the database exists and is ready ' .
'for use. For more assistance, refer to %s. The PDO error was %s',
'https://cloud.google.com/sql/docs/postgres/connect-external-app',
$e->getMessage()
),
$e->getCode(),
$e
);
}
return $conn;
}
}
最佳做法和其他資訊
在本機測試應用程式時,可以使用 Cloud SQL Auth Proxy。如需詳細操作說明,請參閱使用 Cloud SQL 驗證 Proxy 的快速入門導覽課程。
連線集區
資料庫伺服器本身或基礎架構可能會捨棄與基礎資料庫的連線。為減輕這類問題,建議您使用支援連線集區和自動重新連線的用戶端程式庫。
連線限制
以 App Engine 標準環境來說,當中運作的執行個體與其他執行個體之間的並行連線數不得超過 100 個。如果是以 PHP 5.5 編寫而成的應用程式,則上限為 60 個並行連線。這項限制適用於每個應用程式執行個體,也就是說,每個 App Engine 應用程式執行個體與資料庫之間的連線數不得超過 100 個。如果擴充執行個體,每項部署作業的總連線數可隨之增加。詳情請參閱調整元素的資源配置。
您可以使用連線集區,限制每個執行個體使用的連線數量上限。如需如何限制連線數量的詳細範例,請參閱「 管理資料庫連線」頁面。
App Engine 應用程式必須符合要求時間限制,實際情況則視用量和環境而定。詳情請參閱 App Engine 標準環境中 標準與 彈性環境的執行個體管理方式說明。
API 配額限制
App Engine 提供透過 Cloud SQL 驗證 Proxy 連線的機制,該 Proxy 會使用 Cloud SQL Admin API。 API 配額限制適用於 Cloud SQL 驗證 Proxy。Cloud SQL Admin API 啟動時會使用兩個配額,之後平均每小時使用兩個配額。預設配額為每位使用者每分鐘 180 項要求。App Engine 應用程式也必須符合其他配額與限制的規定,詳情請參閱 App Engine 配額頁面。