Como se conectar do ambiente flexível do App Engine ao Cloud SQL

Nesta página, você encontra informações e exemplos para se conectar a uma instância do Cloud SQL a partir de um serviço em execução no ambiente flexível do App Engine.

O Cloud SQL é um serviço de banco de dados totalmente gerenciado que ajuda a configurar, manter, gerenciar e administrar seus bancos de dados relacionais na nuvem.

O ambiente padrão do App Engine é uma plataforma sem servidor totalmente gerenciada para desenvolver e hospedar aplicativos da Web em escala. Você pode escolher entre várias linguagens, bibliotecas e bibliotecas conhecidas para desenvolver seus aplicativos e deixar que o ambiente flexível do App Engine cuide do provisionamento de servidores e do escalonamento das instâncias do aplicativo com base na demanda.

Como configurar uma instância do Cloud SQL

  1. Ative a API Cloud SQL Admin no projeto do qual você está se conectando, caso ainda não tenha feito isso:

    Ative a API

  2. Crie uma instância do Cloud SQL para PostgreSQL.

    Por padrão, o Cloud SQL atribui um endereço IP público a uma nova instância. Você também tem a opção de atribuir um endereço IP particular. Para mais informações sobre as opções de conectividade de ambos, consulte a página Visão geral da conexão.

Como configurar o ambiente flexível do App Engine

As etapas para configurar o ambiente flexível do App Engine dependem do tipo de endereço IP atribuído à instância do Cloud SQL.

IP público (padrão)

Para configurar o ambiente flexível do App Engine para ativar conexões com uma instância do Cloud SQL:

  1. Verifique se a instância criada acima tem um endereço IP público. Você pode verificar isso na página Visão geral da sua instância no Console do Google Cloud. Se precisar adicionar um, consulte a página Como configurar o IP público para ver instruções.
  2. Receba o INSTANCE_CONNECTION_NAME da instância. Isso pode ser encontrado na página Visão geral da instância no Console do Google Cloud ou executando o seguinte comando: gcloud sql instances describe [INSTANCE_NAME].
  3. Verifique se a conta de serviço usada pelo aplicativo para autenticar chamadas para o Cloud SQL tem os papéis e permissões apropriados do Cloud SQL.
    • A conta de serviço do seu serviço precisa de um dos seguintes papéis do IAM:
      • Cloud SQL Client (recomendável)
      • Cloud SQL Editor
      • Cloud SQL Admin
      Ou você pode atribuir manualmente as duas permissões do IAM a seguir:
      • cloudsql.instances.connect
      • cloudsql.instances.get
      Para receber instruções detalhadas sobre como adicionar papéis do IAM a uma conta de serviço, consulte Como conceder papéis a contas de serviço.

    Por padrão, o aplicativo autorizará suas conexões usando a conta de serviço do ambiente flexível do App Engine. A conta de serviço está no formato service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com.

    Se a conta de serviço de autorização pertencer a um projeto diferente da instância do Cloud SQL, as permissões da API Cloud SQL Admin e do IAM precisarão ser adicionadas aos dois projetos.

  4. Atualize o arquivo app.yaml do seu projeto com a opção que funcionar melhor. É possível usar uma lista de instâncias separada por vírgulas para especificar várias opções de uma só vez.

    Como ativar um soquete de domínio Unix

    Para ativar um soquete de domínio Unix, adicione uma das seguintes opções ao arquivo app.yaml do projeto, dependendo de se você está se conectando a uma ou várias instâncias:

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME
    

    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME,INSTANCE_CONNECTION_NAME_2,...
    

    Como ativar uma porta TCP

    Para ativar uma porta TCP local, adicione uma das seguintes opções ao arquivo app.yaml do projeto, dependendo de se você está se conectando a uma ou várias instâncias:

    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 particular

Para se conectar à instância do Cloud SQL por um IP particular, a implantação do ambiente flexível do App Engine precisa estar na mesma rede VPC que a instância do Cloud SQL. Consulte a documentação de configuração em Configurações de rede para ver instruções sobre como especificar uma rede VPC na implantação.

Depois de implantado, seu aplicativo poderá se conectar diretamente por meio de um endereço IP particular e da porta 5432 da instância.

Como se conectar ao Cloud SQL

Depois de configurar o ambiente flexível do App Engine, conecte-se à instância do Cloud SQL.

IP público (padrão)

Para caminhos de IP públicos, o ambiente flexível do App Engine fornece criptografia e se conecta usando o Cloud SQL Auth Proxy.

IP particular

Para caminhos de IP particulares, o aplicativo se conectará diretamente à instância usando o acesso VPC sem servidor. Esse método se conecta diretamente à instância do Cloud SQL sem o proxy do Cloud SQL Auth.

Como se conectar com TCP

Conecte-se diretamente usando o endereço IP particular e a porta 5432 da instância.

Python

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_host = os.environ["DB_HOST"]

# Extract host and port from db_host
host_args = db_host.split(":")
db_hostname, db_port = host_args[0], int(host_args[1])

pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # postgres+pg8000://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
    sqlalchemy.engine.url.URL(
        drivername="postgresql+pg8000",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        host=db_hostname,  # e.g. "127.0.0.1"
        port=db_port,  # e.g. 5432
        database=db_name  # e.g. "my-database-name"
    ),
    **db_config
)

Java

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub (em inglês).

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

// The configuration object specifies behaviors for the connection pool.
HikariConfig config = new HikariConfig();

// The following URL is equivalent to setting the config options below:
// jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<CLOUD_SQL_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_USER>&password=<DB_PASS>
// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);

// The ipTypes argument can be used to specify a comma delimited list of preferred IP types
// for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
// SocketFactory to connect with an instance's associated private IP.
config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

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

// Initialize the connection pool using the configuration object.
DataSource pool = new HikariDataSource(config);

Node.js

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

const createTcpPool = config => {
  // Extract host and port from socket address
  const dbSocketAddr = process.env.DB_HOST.split(':'); // e.g. '127.0.0.1:5432'

  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
      host: dbSocketAddr[0], // e.g. '127.0.0.1'
      port: dbSocketAddr[1], // e.g. '5432'
    },
    // ... Specify additional properties here.
    ...config,
  });
};

Go

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

var (
	dbUser    = mustGetenv("DB_USER") // e.g. 'my-db-user'
	dbPwd     = mustGetenv("DB_PASS") // e.g. 'my-db-password'
	dbTCPHost = mustGetenv("DB_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	dbPort    = mustGetenv("DB_PORT") // e.g. '5432'
	dbName    = mustGetenv("DB_NAME") // e.g. 'my-database'
)

var dbURI string
dbURI = fmt.Sprintf("host=%s user=%s password=%s port=%s database=%s", dbTCPHost, dbUser, dbPwd, dbPort, dbName)

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

// ...

return dbPool, nil

C#

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub (em inglês).

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

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

Ruby

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

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

PHP

Para ver esse snippet no contexto de um aplicativo da Web, consulte o README no GitHub.

// $username = 'your_db_user';
// $password = 'yoursupersecretpassword';
// $dbName = 'your_db_name';
// $dbHost = "127.0.0.1";

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

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

Práticas recomendadas e outras informações

Use o proxy do Cloud SQL Auth ao testar seu aplicativo localmente. Consulte o guia de início rápido para usar o proxy do Cloud SQL Auth para instruções detalhadas.

Pools de conexões

As conexões aos bancos de dados subjacentes podem ser descartadas pelo próprio servidor de banco de dados ou pela infraestrutura subjacente. Para atenuar isso, recomendamos que você use uma biblioteca de cliente que ofereça suporte a pools de conexão e à reconexão automática.

Limites de conexão

Cada instância do App Engine executada em um ambiente padrão não pode ter mais de 100 conexões simultâneas com uma instância. Nos apps em PHP 5.5, o limite é de 60 conexões simultâneas. Esse limite é aplicado por instância do aplicativo. Isso significa que cada instância do aplicativo do App Engine pode ter muitas conexões com o banco de dados e, à medida que ela cresce, o número total de conexões por implantação pode aumentar. Para mais informações, consulte os Elementos de escalonamento.

É possível limitar o número máximo de conexões por instância usando um pool de conexões. Para exemplos mais detalhados sobre como limitar o número de conexões, consulte a página Como gerenciar conexões de banco de dados.

Os aplicativos do App Engine estão sujeitos a limites de tempo de solicitação, dependendo do uso e do ambiente. Para mais informações, veja como as instâncias são gerenciadas nos ambientes padrão e flexível do App Engine.

Os aplicativos do App Engine também estão sujeitos a outras cotas e limites, conforme descrito na página Cotas do App Engine.

Limites de cota da API

O App Engine fornece um mecanismo que se conecta usando o proxy do Cloud SQL Auth, que usa a API Cloud SQL Admin. Os limites de cota da API se aplicam ao proxy do Cloud SQL Auth.