이 페이지에는 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 주소를 할당할 수도 있습니다. 두 옵션의 연결 옵션에 대한 자세한 내용은 연결 개요 페이지를 참조하세요.
App Engine 가변형 환경 구성
App Engine 가변형 환경을 구성하는 단계는 Cloud SQL 인스턴스에 할당된 IP 주소 유형에 따라 다릅니다.공개 IP(기본값)
Cloud SQL 인스턴스에 연결할 수 있도록 App Engine 가변형 환경을 구성하려면 다음 안내를 따르세요.
- 인스턴스에 공개 IP 주소가 있는지 확인합니다. Google Cloud 콘솔의 인스턴스에 대한 개요 페이지에서 이를 확인할 수 있습니다. 공개 IP 주소를 추가해야 하는 경우 공개 IP 구성 페이지의 안내를 참조하세요.
- 인스턴스의 INSTANCE_CONNECTION_NAME을 가져옵니다. Google Cloud 콘솔의 인스턴스 개요 페이지에서 또는 다음
gcloud sql instances describe
명령어를 실행하여 이 값을 확인할 수 있습니다. INSTANCE_NAME을 Cloud SQL 인스턴스의 이름으로 바꿉니다.gcloud sql instances describe INSTANCE_NAME
- 앱에서 Cloud SQL 호출을 인증하는 데 사용하는 서비스 계정에 적절한 Cloud SQL 역할 및 권한이 있는지 확인합니다.
- 서비스의 서비스 계정에는 다음 IAM 역할 중 하나가 필요합니다.
Cloud SQL Client
(권장)Cloud SQL Editor
Cloud SQL Admin
cloudsql.instances.connect
cloudsql.instances.get
기본적으로 앱은 App Engine 가변형 환경 서비스 계정을 사용하여 연결을 승인합니다. 서비스 계정은
PROJECT_ID@appspot.gserviceaccount.com
형식입니다.승인 서비스 계정이 Cloud SQL 인스턴스와 다른 프로젝트에 속하는 경우 두 프로젝트에 Cloud SQL Admin API 및 IAM 권한을 추가해야 합니다.
- 서비스의 서비스 계정에는 다음 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 네트워크에 있어야 합니다. 배포에 VPC 네트워크를 지정하는 방법은 네트워크 설정에 대한 구성 문서를 참조하세요.
배포 후에는 애플리케이션이 인스턴스의 비공개 IP 주소 및 포트 5432
을 사용하여 직접 연결할 수 있습니다.
Cloud SQL에 연결
App Engine 가변형 환경을 구성한 후 Cloud SQL 인스턴스에 연결할 수 있습니다.
공개 IP(기본값)
공개 IP 경로의 경우 App Engine 가변형 환경은 암호화를 제공하고 세 가지 방법으로 Cloud SQL 인증 프록시를 사용하여 연결합니다.
- TCP 소켓을 통해
- Unix 소켓을 통해
- Cloud SQL 커넥터를 사용하여
TCP로 연결
172.17.0.1:PORT
를 사용하여 직접 연결합니다. 여기서 PORT
는 app.yaml
파일에 지정한 포트입니다. Cloud SQL 인증 프록시는 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
자바
웹 애플리케이션의 컨텍스트에서 이 스니펫을 보려면 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 소켓으로 연결
구성이 올바르다면 다음 /cloudsql/INSTANCE_CONNECTION_NAME
경로에서 환경의 파일 시스템에서 액세스한 Cloud SQL 인스턴스의 Unix 도메인 소켓에 서비스를 연결할 수 있습니다.
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
자바
웹 애플리케이션의 컨텍스트에서 이 스니펫을 보려면 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);
}
// ... 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 커넥터는 Cloud SQL 인스턴스에 연결할 때 암호화 및 IAM 기반 승인을 제공하는 언어별 라이브러리입니다.
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()
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
자바
웹 애플리케이션의 컨텍스트에서 이 스니펫을 보려면 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");
// ... 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()))
}
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
}
비공개 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
자바
웹 애플리케이션의 컨텍스트에서 이 스니펫을 보려면 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 인증 프록시를 사용할 수 있습니다. 자세한 내용은 빠른 시작: Cloud SQL 인증 프록시 사용을 참조하세요.
연결 풀
기본 데이터베이스에 대한 연결은 데이터베이스 서버 자체 또는 기본 인프라에 의해 중단될 수 있습니다. 이 문제를 완화하려면 연결 풀 및 자동 재연결을 지원하는 클라이언트 라이브러리를 사용하는 것이 좋습니다.
연결 한도
표준 환경에서 실행되는 각 App Engine 인스턴스에서 하나의 인스턴스로의 동시 연결은 최대 100개까지 가능합니다. PHP 5.5 앱의 경우 동시 연결 한도는 60개입니다. 이 한도는 애플리케이션 인스턴스별로 적용됩니다. 즉, App Engine 애플리케이션의 각 인스턴스는 데이터베이스에 대한 많은 연결을 가질 수 있으며, 이에 따라 배포당 총 연결 수가 늘어날 수 있습니다. 자세한 내용은 요소 확장을 참조하세요.
연결 풀을 사용하면 인스턴스마다 사용되는 최대 연결 수를 제한할 수 있습니다. 연결 수를 제한하는 방법에 대한 자세한 예시는 데이터베이스 연결 관리 페이지를 참조하세요.
App Engine 애플리케이션에는 사용량과 환경에 따른 요청 시간 제한이 적용됩니다. 자세한 내용은 App Engine 표준 환경 표준 환경 및 가변 환경의 인스턴스 관리 방법을 참조하세요.
API 할당량 한도
App Engine은 Cloud SQL Admin API를 사용하는 Cloud SQL 인증 프록시를 사용하여 연결하는 메커니즘을 제공합니다. API 할당량 한도가 Cloud SQL 인증 프록시에 적용됩니다. Cloud SQL Admin API가 시작되면 할당량 2와 이후 시간당 평균 2를 사용합니다. 기본 할당량은 사용자별로 분당 180입니다. 또한 App Engine 애플리케이션에는 App Engine 할당량 페이지에서 살펴본 바와 같이 추가 할당량과 한도가 적용됩니다.