从 Cloud Functions 连接到 Cloud SQL

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

Cloud SQL 是一项全代管式数据库服务,可帮助您在云端设置、维护、管理和控制关系型数据库。

Cloud Functions 是一个轻量级计算解决方案,可供开发者创建单一用途的独立函数,无需管理服务器或运行时环境即可对云端事件作出响应。

设置 Cloud SQL 实例

  1. 在您要从中进行连接的项目中启用 Cloud SQL Admin API(如果您尚未执行此操作):

    启用 API

  2. 创建 Cloud SQL for SQL Server 实例

    默认情况下,Cloud SQL 会为新实例分配公共 IP 地址。Cloud Functions 不支持通过公共 IP 地址连接到 Cloud SQL for SQL Server。请改用专用 IP 地址。如需了解详情,请参阅配置专用 IP 地址

配置 Cloud Functions

配置 Cloud Functions 的步骤取决于您分配给 Cloud SQL 实例的 IP 地址类型。

公共 IP 地址(默认)

Cloud Functions 不支持通过公共 IP 地址连接到 Cloud SQL for SQL Server。请改用专用 IP 地址。

专用 IP 地址

无服务器 VPC 访问通道连接器会处理与您的 VPC 网络的通信。 如需直接使用专用 IP 进行连接,您需要:

  1. 确保上面创建的 Cloud SQL 实例具有专用 IP 地址。如果您需要添加 IP 地址,请参阅配置专用 IP 页面来查看相关说明。
  2. 在 Cloud SQL 实例所在的同一 VPC 网络中创建无服务器 VPC 访问通道连接器。
  3. 除非您使用共享 VPC,否则连接器必须与使用它的资源位于同一项目和区域中,但该连接器可向其他区域中的资源发送流量。

    无服务器 VPC 访问通道支持与通过 Cloud VPNVPC 网络对等互连连接的 VPC 网络进行通信。

    无服务器 VPC 访问通道不支持旧版网络

  4. 将 Cloud Functions 配置为使用该连接器
  5. 使用实例的专用 IP 地址和端口 1433 进行连接。

连接到 Cloud SQL

配置 Cloud Functions 后,您可以连接到 Cloud SQL 实例。

公共 IP(默认)

Cloud Functions 不支持通过公共 IP 地址连接到 Cloud SQL for SQL Server。请改用专用 IP。

对于公共 IP 路径,Cloud Functions 通过 Cloud SQL Auth 代理提供加密/授权连接

专用 IP

对于专用 IP 路径,您的应用将通过无服务器 VPC 访问通道直接连接到您的实例。

使用 TCP 进行连接

直接使用您实例的专用 IP 地址和端口 1433 进行连接。

Python

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

# 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 environment variable DB_HOST
host_args = db_host.split(":")
db_hostname, db_port = host_args[0], int(host_args[1])

# SQL Server drivers don't account for this
if db_hostname == "localhost":
    db_hostname = "127.0.0.1"

# The SQLAlchemy engine will help manage interactions, including automatically
# managing a pool of connections to your database
pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # mssql+pytds://<db_user>:<db_pass>@/<host>:<port>/<db_name>?driver=ODBC+Driver+17+for+SQL+Server
    sqlalchemy.engine.url.URL(
        "mssql+pytds",
        username=db_user,
        password=db_pass,
        database=db_name,
        host=db_hostname,
        port=db_port,
    ),
    **db_config
)

Java

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

// 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 is equivalent to setting the config options below:
// jdbc:sqlserver://;user=<DB_USER>;password=<DB_PASS>;databaseName=<DB_NAME>;
// socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
// socketFactoryConstructorArg=<CLOUD_SQL_CONNECTION_NAME>

// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

// Configure which instance and what database user to connect with.
config
    .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
config.setUsername(DB_USER); // e.g. "root", "sqlserver"
config.setPassword(DB_PASS); // e.g. "my-password"
config.addDataSourceProperty("databaseName", DB_NAME);

config.addDataSourceProperty("socketFactoryClass",
    "com.google.cloud.sql.sqlserver.SocketFactory");
config.addDataSourceProperty("socketFactoryConstructorArg", CLOUD_SQL_CONNECTION_NAME);

// ... Specify additional connection properties here.

// ...

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

Node.js

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

const createPool = async () => {
  const config = {pool: {}};
  config.user = process.env.DB_USER; // e.g. 'my-db-user'
  config.password = process.env.DB_PASS; // e.g. 'my-db-password'
  config.database = process.env.DB_NAME; // e.g. 'my-database'
  // set the server to '172.17.0.1' when connecting from App Engine Flex
  config.server = process.env.DEPLOYED ? '172.17.0.1' : '127.0.0.1';
  config.port = 1433;

  // ...
  return await mssql.connect(config);
};

Go

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

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. '1433'
	dbName    = mustGetenv("DB_NAME") // e.g. 'my-database'
)

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

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

// ...

return dbPool, nil

PHP

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

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

// Connect using TCP
$dsn = sprintf('sqlsrv:server=%s;Database=%s', $dbHost, $dbName);

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

最佳做法和其他信息

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

连接池

与底层数据库的连接可能会被数据库服务器本身或 Cloud Functions 的底层基础架构断开。我们建议您使用支持连接池的客户端库,因为连接池可自动重新连接断开的客户端连接。此外,我们建议您使用全局范围的连接池,以便提高函数在后续调用中重复使用同一连接的可能性,并在逐出(自动缩减)实例时自然关闭连接。如需查看有关如何使用连接池的详细示例,请参阅管理数据库连接

连接限制

Cloud SQL 对并发连接数量设定了上限,这些限制可能因所选的数据库引擎而有所不同(请参阅 Cloud SQL 配额和限制)。建议使用与 Cloud Functions 的连接,但务必将连接数上限设置为 1。

您应该尽可能保证仅为需要访问数据库的函数初始化连接池。某些连接池会采用抢占的方式创建连接,这可能会耗用过多资源,也会占用您的连接限额。因此,建议使用延迟初始化来将连接池的创建推迟到必要的时候,并且仅在使用连接池的函数中包含连接池。

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

API 配额限制

Cloud Functions 提供了一种使用 Cloud SQL Auth 代理进行连接的机制,该代理使用 Cloud SQL Admin API。API 配额限制适用于 Cloud SQL Auth 代理。