问题描述
我正在尝试从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'
我认为问题有两个部分:
- CORS
-
pool.query()
是异步的
我已经针对CORS解决方案查看了多个问题,例如here和here,但是没有一个解决方案对我有用。关于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
来指定要部署的区域。