【发布时间】:2020-03-04 16:38:48
【问题描述】:
我有一个普通的云函数,它需要 60 秒,然后用一个简单的 JSON 对象返回状态 200。该函数的超时设置为 150 秒。在本地测试时,以及通过其 cloudfunctions.net 地址运行该函数时,该函数在 60 秒时完成,并且 200 响应和正文正确传递给客户端。到目前为止一切顺利。
这是关键 - 如果我通过 firebase 托管运行完全相同的功能(通过 firebase.json 中的“目标”设置),根据堆栈驱动程序日志,该功能会立即重新启动 1-3 次,当这些完成时,有时会再次重新启动该功能,最终从 Varnish 返回 503 Timeout。
只有在通过 firebase 托管代理的域上调用该函数时,此行为才能始终如一地复制。它似乎只在函数需要大约 60 秒或更长时间时才会发生。它不依赖于返回的响应代码或响应正文。
您可以在我在这里设置的测试函数中看到这种行为:https://trellisconnect.com/testtimeout?sleepAmount=60&retCode=200
此行为最初是在通过无服务器部署的函数中识别的。为了排除无服务器,我创建了一个测试函数,使测试和验证行为变得容易,并使用常规的 firebase 函数部署它,并从它的 cloudfunctions.net 域调用它,并验证我在 60 秒时总是得到正确的响应。然后我更新了我的 firebase.json 以添加一个指向该函数并能够复制问题的新路由。
index.js
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
exports.testtimeout = functions.https.onRequest((req, res) => {
const { sleepAmount, retCode } = req.query;
console.log(`starting test sleeping ${sleepAmount}...`);
sleep(1000 * sleepAmount).then(result => {
console.log(`Ending test func, returning ${retCode}`);
return res.status(retCode).json({ message: 'Random Response' });
});
});
firebase.json
{
"hosting": {
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "/testtimeout",
"function": "testtimeout"
}
]
},
"functions": {}
}
</snip>
正确/预期的响应(sleepAmount=2 秒)
zgoldberg@zgblade:~$ time curl "https://trellisconnect.com/testtimeout?sleepAmount=2&retCode=200"
{"message":"Random Response"}
real 0m2.269s
user 0m0.024s
sys 0m0.000s
以及当 sleepAmount 设置为 60 秒时的情况示例
zgoldberg@zgblade:~$ curl -v "https://trellisconnect.com/testtimeout?sleepAmount=60&retCode=200"
* Trying 151.101.65.195...
* TCP_NODELAY set
* Connected to trellisconnect.com (151.101.65.195) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=admin.cliquefood.com.br
* start date: Oct 16 20:44:55 2019 GMT
* expire date: Jan 14 20:44:55 2020 GMT
* subjectAltName: host "trellisconnect.com" matched cert's "trellisconnect.com"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x563f92bdc580)
> GET /testtimeout?sleepAmount=60&retCode=200 HTTP/2
> Host: trellisconnect.com
> User-Agent: curl/7.58.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 503
< server: Varnish
< retry-after: 0
< content-type: text/html; charset=utf-8
< accept-ranges: bytes
< date: Fri, 08 Nov 2019 03:12:08 GMT
< x-served-by: cache-bur17523-BUR
< x-cache: MISS
< x-cache-hits: 0
< x-timer: S1573182544.115433,VS0,VE184552
< content-length: 449
<
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>503 first byte timeout</title>
</head>
<body>
<h1>Error 503 first byte timeout</h1>
<p>first byte timeout</p>
<h3>Guru Mediation:</h3>
<p>Details: cache-bur17523-BUR 1573182729 2301023220</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
* Connection #0 to host trellisconnect.com left intact
real 3m3.763s
user 0m0.024s
sys 0m0.031s
这是疯狂的部分,检查堆栈驱动程序日志,注意函数是如何在 60 秒内完成的,并且几乎是在另外 3 次执行之后立即完成...
请注意,最初的通话在 19:09:04.235 进入并在 19:10:04.428 结束 - 几乎正好是 60 秒后。几乎正好 500 毫秒后,19:10:05.925 函数重新启动。我向你保证,在初始响应后 0.5 秒我没有再次点击我的 curl 命令。这里函数的后续执行都不是我生成的,它们似乎都是幻影重试?
https://i.imgur.com/WDY17pw.png (编辑:我没有 10 声望来发布实际图片,所以只是上面的链接)
非常感谢任何想法或帮助
【问题讨论】:
标签: firebase google-cloud-platform google-cloud-functions serverless