查询AWS RDS PostgreSQL数据库时,Firebase Functions超时

问题描述

我正在尝试从Firebase Node JS云功能查询Amazon RDS数据库。我建立了查询,并可以使用firebase functions:shell在本地成功运行代码。但是,当我部署该功能并从站点上的客户端js调用它时,客户端和服务器端都会收到错误消息。

客户端:

Error: internal
Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.
Fetch API cannot load https://us-central1-*****.cloudfunctions.net/query due to access control checks.
Failed to load resource: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.

服务器端:

Function execution took 60004 ms,finished with status: 'timeout'

我认为问题有两个部分:

  1. CORS
  2. pool.query()是异步的

我已经针对CORS解决方案查看了多个问题,例如herehere,但是没有一个解决方案对我有用。关于pool.query()是异步的,我相信我已经正确处理了,但是结果和错误都不会打印到服务器日志中。

下面是我项目中的所有相关代码

客户端:

var queryRDS = firebase.functions().httpsCallable('query');
queryRDS({
     query: document.getElementById("search-input").value
})
.then(function (result) {
     if (result) {
          console.log(result)
     }
})
.catch(function (error) {
     console.log(error);
});

服务器端:

const functions = require('firebase-functions');
const { Pool } = require('pg');

const pool = new Pool({
    user: 'postgres',host: '*****.*****.us-west-2.rds.amazonaws.com',database: '*****',password: '*****',port: 5432
})

exports.query = functions.https.onCall((data,context) => {
     // This is not my real query,I just changed it for the
     // simplicity of this question
     var query = "Select * FROM table"

     pool.query(query)
          .then(result_set => {
               console.log(result_set)
               return result_set
          }).catch(err => {
               console.log(err)
               return err
          })
})

我知道一切工作到pool.query()为止,根据我的日志来看,似乎从未达到.then().catch(),而且收益也从未到达客户端。

更新:

我将Firebase Functions的超时从60s增加到120s,并通过在pool.query()之前添加返回语句来更改服务器功能代码

return pool.query(query)
     .then(result_set => {
          console.log(result_set)
          return result_set
     }).catch(err => {
          console.log("Failed to execute query: " + err)
          return err
     })

现在我收到一条错误消息,内容Failed to execute query: Error: connect ETIMEDOUT **.***.***.***:5432,其IP地址是我的AWS RDS数据库。看来这可能一直是潜在的问题,但我不确定RDS为什么给我超时。

解决方法

应该由onCall处理程序自动处理CORS。有关CORS的错误消息很可能不准确,并且由于服务器端错误正在显示,导致函数超时。

话虽如此,根据Cloud Functions Documentation on Function's Timeout的说法,Cloud Functions的默认超时为60秒,这相当于错误消息上的〜60000 ms,这意味着1分钟是不够的以便您的函数执行此类查询,如果您认为该函数正在访问外部提供程序(即Amazon RDS数据库),这将很有意义。

要对其进行修复,您将必须使用一个用于设置函数执行超时的标志来重新部署函数,如下所示:

gcloud functions deploy FUNCTION_NAME --timeout=TIMEOUT

TIMEOUT的值可以是直到540的任何值,这是Cloud Functions在超时(9分钟)之前允许的最大秒数。

注意:也可以通过将功能部署到与Amazon RDS数据库所在位置最近的位置来缓解这种情况,您可以检查this link关于云可用的位置函数,您可以在deploy命令上使用--region=REGION来指定要部署的区域。