异步代码独立工作,但不能一起工作。没有任何异常,只是超时
Posted
技术标签:
【中文标题】异步代码独立工作,但不能一起工作。没有任何异常,只是超时【英文标题】:Asynchronous code works independently, but not together. Not getting any exceptions, just timing out 【发布时间】:2022-01-20 15:56:53 【问题描述】:我正在编写一个 lambda 函数来将主机添加到 SQS 队列以进行滚动重启。我编写的代码单独工作,但不能一起工作。即使我在构造函数中硬编码值。这似乎不是内存/CPU。我尝试使用 1GB 内存运行该函数,尽管它只使用了大约 80MB。单个函数的平均执行时间约为 0.5 秒(总共执行时间不应超过 1.5 秒)。我曾尝试以 30 秒的超时时间运行此函数,但它仍然超时。
我在公司代理后面工作,不得不手动编写代码。我的面向 Internet 的网络上没有 IDE 或智能感知。这里可能有错别字,但实际代码中没有。我省略了模块导入和变量声明以节省时间。它与手头的问题无关。
编辑:我在第一个示例中添加了模块导入和变量声明,希望能减轻一些混乱。
这里只是我尝试过的一些事情。这不起作用(超时):
// Custom lambda layer
const marklogic, aws = require('nodejs-layer-lib');
const HOSTS, DOMAIN, PORT, USERNAME, PASSWORD, RESTART_QUEUE_NAME = process.env;
const params = [
'format=json'
];
const options =
port: PORT,
params: params,
httpOptions:
headers:
'Authorization': `Basic $Buffer.from(`$USERNAME:$PASSWORD`).toString('base64')`
,
method: 'GET'
;
const taskServers = (HOSTS.split(',') || []).map(host =>
const _host = host.split(':');
return
id: _host[0],
name: `http://$_host[1].toLowerCase().$DOMAIN`
;
);
exports.handler = async () =>
let hosts, queueUrl, addToQueueResults;
try
hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
catch (e) console.error('hosts', e);
try
queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
catch (e) console.error('queueUrl ', e);
try
addToQueueResults = await aws.sqs.addMessages(queueURL, hosts);
catch (e) console.error('addToQueueResults ', e);
return
status: 200,
body: addToQueueResults
;
这不起作用(超时):
// Modules imports and variable declarations here...
exports.handler = async () =>
const hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
const queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
const addToQueueResults = await aws.sqs.addMessages(queueURL, hosts);
return
status: 200,
body: addToQueueResults
;
这不起作用(超时):
// Modules imports and variable declarations here...
exports.handler = async () =>
const hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
const queueUrl = await aws.sqs.getQueueUrlByName('my-queue-name');
const addToQueueResults = await aws.sqs.addMessages('http://queueurl.com', ['anything', 'in', 'here']); // Doesn't even need the queueUrl or hosts anymore
return
status: 200,
body: addToQueueResults
;
这行得通。它将在响应中返回我期望的主机对象:
// Modules imports and variable declarations here...
exports.handler = async () =>
const hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
return
status: 200,
body: hosts
;
这行得通。它将获取队列 url,然后将消息添加到我的 SQS 队列并返回 SQS 响应:
// Modules imports and variable declarations here...
exports.handler = async () =>
const queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
const addToQueueResults = await aws.sqs.addMessages(queueUrl , ['anything', 'in', 'here']);
return
status: 200,
body: addToQueueResults
;
我尝试在 AWS Lambda function handler in Node.js 中实现异步处理程序,并查看了许多 AWS Lambda 执行故障排除文档。 marklogic 管理 API 默认在 8002 端口上运行,我认为 aws-sdk 模块使用 http/https (80/443),所以我不认为端口被占用。
我在这里错过了什么?
编辑 2:这与 AWS Lambda 如何处理承诺有关。我找不到太多关于此的信息。即使按照 AWS Lambda function handler in Node.js 中关于“异步处理程序”的说明,我也无法让它工作。无论有没有我的自定义 lambda 层,它都可以在本地完美运行。
Node.js 运行时:12.x(我之前没有提到)
这也不起作用(超时):
// Modules imports and variable declarations here...
exports.handler = async function (event)
const promise = function ()
return new Promise(async function (resolve, reject)
try
const hosts = await marklogic.hosts.getHosts(taskServers, options) || [];
const queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
const addToQueueResults = await aws.sqs.addMessages(queueUrl, hosts);
resolve(
status: 200,
body: addToQueueResults
);
catch (error)
reject(
status: 500,
error: error
);
);
;
return promise(); // Throws error without constructor despite the AWS doc example
除非有人 AWS Lambda 天才之前在使用 Node.js 时遇到过类似的问题,否则我只会将其转换为 2 个 lambda 函数并使用 Step Functions 来处理它们。
【问题讨论】:
“不起作用”是什么意思?有什么例外吗?它会记录什么吗? 您是否在每次尝试/捕获主机、queueurl 和 addToQueueResults 后尝试额外的日志记录,以检查哪些成功以及发生超时的位置? @kichik 抱歉,我应该添加更多上下文。函数超时。每个操作只需要大约 0.5 秒即可运行,但仍会超时,最大超时时间为 30 秒。 @LeighMathieson 第一次尝试/捕获时超时。我只是不明白为什么。没有 sqs 代码它工作正常。没有 marklogic 代码,sqs 代码也能正常工作。 怎么初始化marklogic和sqs?这应该很重要。 【参考方案1】:queueUrl 中有一个错字(我想不是这样,但值得一试!)
请运行:
// Custom lambda layer
const marklogic, aws = require('nodejs-layer-lib');
const HOSTS, DOMAIN, PORT, USERNAME, PASSWORD, RESTART_QUEUE_NAME = process.env;
const params = [
'format=json'
];
const options =
port: PORT,
params,
httpOptions:
headers:
Authorization: `Basic $Buffer.from(`$USERNAME:$PASSWORD`).toString('base64')`
,
method: 'GET'
;
const taskServers = (HOSTS.split(',') || []).map(host =>
const _host = host.split(':');
return
id: _host[0],
name: `http://$_host[1].toLowerCase().$DOMAIN`
;
);
exports.handler = async () =>
let hosts, queueUrl, addToQueueResults;
try
hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
catch (e) console.error('hosts', e);
try
queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
catch (e) console.error('queueUrl ', e);
try
addToQueueResults = await aws.sqs.addMessages(queueUrl, hosts);
catch (e) console.error('addToQueueResults ', e);
return
status: 200,
body: JSON.stringify(addToQueueResults)
;
;
//保持相同的格式.. ^^
如果不走运 - 我的想法是,aws-sdk 已包含在 lambda 中,开箱即用。通过层额外要求它是不习惯的,尽管它可能看起来不像是在顶层导入的通过 marklogic,它可能被深深地捆绑在 marklogic 中,然后当您导入 AWS 并更改配置(在层中)时,它会覆盖它
让我们找出答案..:
第 1 步:
那么,你说的应该可以工作.. 如果我们忽略 AWS 导入,只导入 marklogic?
// Custom lambda layer
// const marklogic, aws = require('nodejs-layer-lib'); // ignoring AWS for now
const marklogic = require('nodejs-layer-lib');
const HOSTS, DOMAIN, PORT, USERNAME, PASSWORD, RESTART_QUEUE_NAME = process.env;
const params = [
'format=json'
];
const options =
port: PORT,
params,
httpOptions:
headers:
Authorization: `Basic $Buffer.from(`$USERNAME:$PASSWORD`).toString('base64')`
,
method: 'GET'
;
const taskServers = (HOSTS.split(',') || []).map(host =>
const _host = host.split(':');
return
id: _host[0],
name: `http://$_host[1].toLowerCase().$DOMAIN`
;
);
exports.handler = async () =>
// let hosts, queueUrl, addToQueueResults;
let hosts;
try
hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
console.log('hosts => ', hosts);
// queueUrl = await aws.sqs.getQueueUrlByName(RESTART_QUEUE_NAME);
// addToQueueResults = await aws.sqs.addMessages(queueUrl, hosts);
return
status: 200,
body: JSON.stringify(hosts)
;
catch (error)
console.log('error => ', error);
throw error;
;
好的,如果可行的话..:
第 2 步(请设置 SQS 的区域以及 queueUrl 中的硬编码):
// Custom lambda layer
// const marklogic, aws = require('nodejs-layer-lib');
const marklogic = require('nodejs-layer-lib');
const AWS = require('aws-sdk');
AWS.config.update( region: 'eu-west-1' ); // Please set region accordingly
const sqs = new AWS.SQS( apiVersion: '2012-11-05' );
const HOSTS, DOMAIN, PORT, USERNAME, PASSWORD, RESTART_QUEUE_NAME = process.env;
const params = [
'format=json'
];
const options =
port: PORT,
params,
httpOptions:
headers:
Authorization: `Basic $Buffer.from(`$USERNAME:$PASSWORD`).toString('base64')`
,
method: 'GET'
;
const taskServers = (HOSTS.split(',') || []).map(host =>
const _host = host.split(':');
return
id: _host[0],
name: `http://$_host[1].toLowerCase().$DOMAIN`
;
);
exports.handler = async () =>
let hosts, addToQueueResults;
try
hosts = (await marklogic.hosts.getHosts(taskServers, options) || []);
console.log('hosts => ', hosts);
const queueUrl = 'Please hard code the queueUrl for now';
const sqsParams =
MessageBody: hosts,
QueueUrl: queueUrl
;
addToQueueResults = await sqs.sendMessage(sqsParams).promise();
console.log('addToQueueResults => ', addToQueueResults);
return
status: 200,
body: JSON.stringify(addToQueueResults)
;
catch (error)
console.log('error => ', error);
throw error;
;
如果 .. 这不起作用.. 然后第 3 步 .. 将 marklogic 的要求移至 AWS 的要求以下,并在最后一个示例中设置区域.. (所以我们是任何深度嵌套的 marklogic AWS 逻辑不知道现在覆盖了您的 AWS 要求..) 重新运行它.. 手指交叉:-)
【讨论】:
这是个好主意。我实际上可能会更进一步,完全删除 lambda 层。然后,我可以确认该错误是否与图层本身有关。我会让你知道会发生什么。 任何更新@dj11223344 ..? 是的。对不起。我应该给你一个评论。不幸的是,您提供的答案不起作用。我又尝试了几件事。在这一点上,我几乎已经放弃了。我只是要使用一个阶梯函数来链接几个 lambda 函数。该代码在本地运行良好。所以它有一个 Lambda 特定的问题。以上是关于异步代码独立工作,但不能一起工作。没有任何异常,只是超时的主要内容,如果未能解决你的问题,请参考以下文章
Django REST 权限类不能在 OR 中一起工作,而是按预期独立工作
为啥以下 jquery 可以在 jsfiddle 中工作,但不能在任何浏览器上工作? [关闭]