【问题标题】:Can't connect to Cloud SQL using node-postgres无法使用 node-postgres 连接到 Cloud SQL
【发布时间】:2020-01-27 11:41:01
【问题描述】:

我一直在尝试使用 pg 模块连接到我的 Cloud SQL 实例,但到目前为止还没有成功。

我在网上看了很多,但对这个主题不太了解。我还想在某个时候在 Cloud Run 上部署我的 Express 应用并让它连接到我的 Cloud SQL 实例,但我不知道该怎么做。

这里列出了一些我不明白的事情,想简要解释一下:

  1. 什么是 Unix 套接字连接,为什么要在普通连接上使用它们?
  2. 什么是 Cloud SQL 代理?我需要使用它吗?如果是,为什么?
  3. 我是否需要做任何额外的工作才能从 Cloud Run 连接到我的 Cloud SQL 实例?

以下是我尝试使用pg.Client 对象的所有连接对象和连接字符串:

  1. 第一个连接字符串:postgresql+psycopg2://postgres:password@/cloudsql/myapp:us-central1:mydb?host=/var/lib/postgresql
  2. 第二个连接字符串:postgresql://postgres:password@hostip:5432/myapp:us-central1:mydb
  3. 第三个连接字符串:postgresql://postgres:password@hostip:5432/sarcdb
  4. 连接对象:{ host: "/cloudsql/myapp:us-central1:mydb", username: "postgres", password: "password", database: "mydb" }

所有这些都给我一个Connection terminated unexpectedly 错误。

【问题讨论】:

    标签: postgresql database-connection google-cloud-sql google-cloud-run cloud-sql-proxy


    【解决方案1】:

    什么是 Unix 套接字连接,为什么我应该在普通连接上使用它们?

    Unix domain socket 是用于进程间通信的套接字。如果您可以选择 TCP 连接和 Unix 域套接字之间的通信,则 Unix 域套接字可能更快。

    什么是 Cloud SQL 代理?我需要使用它吗?如果是这样,为什么?

    Cloud SQL 代理允许您使用服务帐号的 IAM 权限对连接进行身份验证以连接到您的数据库。

    由于 Cloud SQL 是一个云数据库,它需要(默认情况下)某种形式的身份验证来帮助它保持安全。与自我管理的 SSL 证书或列入白名单的 IP 地址相比,代理是一种更安全的连接方法。

    我是否需要做任何额外的工作才能从 Cloud Run 连接到我的 Cloud SQL 实例?

    Cloud Run 会为您运行代理,但您需要执行以下操作:

    1. 启用 Cloud SQL Admin API
    2. 将 Cloud SQL 实例添加到您的 Run 部署中 (follow these steps)。
    3. 确保运行您的代码的服务帐户具有Cloud SQL Client IAM 权限(这是通过第 2 步为默认服务帐户完成的)
    4. 配置您的应用程序以连接/cloudsql/INSTANCE_CONNECTION_NAME

    【讨论】:

    • 不幸的是,这不起作用。它仍然在 Cloud Run 日志中显示“连接意外终止”。你觉得哪里出了问题?我使用了我的问题中提到的第四个连接对象。
    【解决方案2】:

    Cloud Functions documentation for Node.js & Cloud SQL(向下滚动到 PostgreSQL)包含有关构建连接字符串和凭据所需的其他配置的适用信息。

    一旦为您的应用设置好了这些,您需要add the Cloud SQL instance to your Cloud Run service,然后它才能使用该连接字符串访问数据库。

    这里直接从文档中复制代码示例,使用 Cloud Run 时,max 配置为 1 可能跟不上其他并发设置。

    const pg = require('pg');
    
    /**
     * TODO(developer): specify SQL connection details
     */
    const connectionName =
      process.env.INSTANCE_CONNECTION_NAME || '<YOUR INSTANCE CONNECTION NAME>';
    const dbUser = process.env.SQL_USER || '<YOUR DB USER>';
    const dbPassword = process.env.SQL_PASSWORD || '<YOUR DB PASSWORD>';
    const dbName = process.env.SQL_NAME || '<YOUR DB NAME>';
    
    const pgConfig = {
      max: 1,
      user: dbUser,
      password: dbPassword,
      database: dbName,
    };
    
    if (process.env.NODE_ENV === 'production') {
      pgConfig.host = `/cloudsql/${connectionName}`;
    }
    
    // Connection pools reuse connections between invocations,
    // and handle dropped or expired connections automatically.
    let pgPool;
    
    exports.postgresDemo = (req, res) => {
      // Initialize the pool lazily, in case SQL access isn't needed for this
      // GCF instance. Doing so minimizes the number of active SQL connections,
      // which helps keep your GCF instances under SQL connection limits.
      if (!pgPool) {
        pgPool = new pg.Pool(pgConfig);
      }
    
      pgPool.query('SELECT NOW() as now', (err, results) => {
        if (err) {
          console.error(err);
          res.status(500).send(err);
        } else {
          res.send(JSON.stringify(results));
        }
      });
    
      // Close any SQL resources that were declared inside this function.
      // Keep any declared in global scope (e.g. mysqlPool) for later reuse.
    };
    

    【讨论】:

    • 我可以将 Cloud SQL 实例连接到 Cloud Run 实例,但我仍然无法使用 pg 模块从 Cloud Run 实例内部连接我的 express 应用程序。我究竟做错了什么?我正在使用我的问题中提到的第四个连接对象。
    • 不确定是否重要,但在上面的示例代码中,键 user 是预期的,并且在您问题的第四个连接对象中,您有 username
    • 是的……这就是问题所在……我太笨了……不过还是谢谢!
    • 看起来这个答案来自 Cloud Run/Cloud SQL 文档不包含连接到 Cloud SQL 的说明,因此使用了 Cloud Functions 文档。目前,Cloud SQL 文档似乎包含以下信息:cloud.google.com/sql/docs/postgres/connect-run
    猜你喜欢
    • 1970-01-01
    • 2021-06-18
    • 2023-02-07
    • 2017-04-11
    • 1970-01-01
    • 2014-01-28
    • 2022-01-24
    • 2020-06-07
    • 2020-11-15
    相关资源
    最近更新 更多