从 App Engine 连接到 Cloud SQL

本页面介绍从 App Engine 中运行的服务连接到 Cloud SQL 实例的相关信息和示例。

Cloud SQL 是一种完全托管式数据库服务,可让您轻松地在云端设置、维护、管理和控制关系型 PostgreSQL 及 MySQL 数据库。

App Engine 是完全托管式无服务器平台,可用于大规模开发和托管 Web 应用。您可以选择多种主流的语言、库和框架来开发应用,然后让 App Engine 为您预配服务器并根据需求扩缩应用实例数量。

设置 Cloud SQL 实例

  1. 创建 Cloud SQL for MySQL 实例

  2. 实例详情页面上找到实例的 INSTANCE_CONNECTION_NAME。该名称采用 PROJECT_ID:REGION:INSTANCE_ID 格式,用于标识您要连接的 Cloud SQL 实例。

  3. 启用 Cloud SQL Admin API(如果您尚未执行此操作):

    启用 API

配置 App Engine

标准环境

App Engine 只需要确保您使用的服务帐号拥有正确的权限,而无需任何特殊配置。

柔性环境

使用最适用的选项更新项目的 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>=tcp:<PORT>,<INSTANCE_CONNECTION_NAME_2>=tcp:<PORT>,...
    

App Engine 使用服务帐号向您与 Cloud SQL 的连接授权。此服务帐号必须具有正确的 IAM 权限才能成功连接。除非另行配置,否则默认服务帐号采用 service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com 格式。

您可以视情况允许或禁止其他应用或客户端连接到您的 Cloud SQL 实例。如需了解详情,请参阅身份验证选项,确定允许谁连接到您的实例以及从何处进行连接。

在连接属于两个不同项目的资源时,请确保这两个项目均已启用正确的 IAM 角色,且已向服务帐号授予正确的权限。

确保您的服务帐号具有下列其中一个 IAM 角色

  • Cloud SQL Client(首选)
  • Cloud SQL Editor
  • Cloud SQL Admin

您也可以手动分配下列 IAM 权限

  • cloudsql.instances.connect
  • cloudsql.instances.get

如需详细了解如何将 IAM 角色添加到服务帐号,请参阅向服务帐号授予角色

连接到 Cloud SQL

正确配置后,您可以按照 /cloudsql/INSTANCE_CONNECTION_NAME 格式将服务连接到 Cloud SQL 实例的 Unix 网域套接字。

这些连接会自动加密,无需任何额外配置。

下面显示的代码示例摘自 GitHub 网站上提供的更完整示例。如需了解详情,请点击View on GitHub。在 GitHub 网站上,在代码所在的目录中查找 README 文件。README 文件讨论了重要的设置主题,例如将环境变量用于凭据、连接路径和数据库变量。README 文件还提供了测试和部署方面的提示。

App Engine 柔性环境还支持通过 TCP 进行连接。如果您配置的实例具有 TCP 端口,请将您的应用配置改为连接到 172.17.0.1:PORT

Python

# The SQLAlchemy engine will help manage interactions, including automatically
    # managing a pool of connections to your database
    db = sqlalchemy.create_engine(
        # Equivalent URL:
        # mysql+pymysql://<db_user>:<db_pass>@/<db_name>?unix_socket=/cloudsql/<cloud_sql_instance_name>
        sqlalchemy.engine.url.URL(
            drivername="mysql+pymysql",
            username=db_user,
            password=db_pass,
            database=db_name,
            query={"unix_socket": "/cloudsql/{}".format(cloud_sql_connection_name)},
        ),
        # ... Specify additional properties here.
        # ...
    )
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

Java

// 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:mysql:///%s", DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", "postgres"
    config.setPassword(DB_PASS); // e.g. "my-password"

    // For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
    // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
    config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);
    config.addDataSourceProperty("useSSL", "false");

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

    // Initialize the connection pool using the configuration object.
    DataSource pool = new HikariDataSource(config);
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

Node.js

let pool;
    const createPool = async () => {
      pool = await mysql.createPool({
        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'
        // If connecting via unix domain socket, specify the path
        socketPath: `/cloudsql/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
        // If connecting via TCP, enter the IP and port instead
        // host: 'localhost',
        // port: 3306,

        //...
      });
    };
    createPool();
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

C#

var connectionString = new MySqlConnectionStringBuilder(
        Configuration["CloudSql:ConnectionString"])
    // ConnectionString set in appsetings.json formatted as:
    // "Uid=aspnetuser;Pwd=;Host=cloudsql;Database=votes"
    {
        // Connecting to a local proxy that does not support ssl.
        SslMode = MySqlSslMode.None,
    };
    connectionString.Pooling = true;
    // ...
    DbConnection connection =
        new MySqlConnection(connectionString.ConnectionString);
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

Ruby

development:
      adapter: mysql2
      # ...
      username: <%= ENV["MYSQL_USERNAME"] %>
      password: <%= ENV["MYSQL_PASSWORD"] %>
      database: <%= ENV.fetch("MYSQL_DATABASE") { "vote_development" } %>
      socket:   "/cloudsql/<%= ENV["INSTANCE_CONNECTION_NAME"] %>"
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

Go

var (
    	dbUser                 = mustGetenv("DB_USER")
    	dbPwd                  = mustGetenv("DB_PASS")
    	instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME")
    	dbName                 = mustGetenv("DB_NAME")
    )

    var dbURI string
    dbURI = fmt.Sprintf("%s:%s@unix(/cloudsql/%s)/%s", dbUser, dbPwd, instanceConnectionName, dbName)

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

    // ...

    return dbPool, nil
如需了解 Web 应用环境下的此代码段,请查看 GitHub 上的源代码

最佳做法和其他信息

在本地测试应用时,您可以使用 Cloud SQL 代理。如需了解详细说明,请参阅《快速入门:使用代理进行本地测试》

连接池

与底层数据库的连接可能会被数据库服务器本身或底层基础架构断开。为了缓解此问题,我们建议您使用支持连接池和自动重新连接的客户端库。

如需查看有关如何使用连接池的详细示例,请参阅管理数据库连接

连接限制

Cloud SQL 对并发连接数量设定了上限,这些限制可能因所选的数据库引擎而有所不同(请参阅 Cloud SQL 配额和限制)。

App Engine 会在负载增加时自动创建更多实例,这可能导致超出这些限制。为避免此问题,请限制 App Engine 实例数量上限。如需了解详情,请参阅扩缩元素

每个在标准环境中运行的 App Engine 实例与其他实例的并发连接数不能超过 100 个。对于 PHP 5.5 应用,并发连接数上限为 60 个

App Engine 应用受请求时间限制的约束,具体取决于使用情况和环境。如需了解详情,请参阅实例在 App Engine 标准环境柔性环境中的管理方式。

App Engine 应用还受 App Engine 配额页面上所述的其他 App Engine 配额和限制的约束。