#javascript #node.js #aws-lambda #amazon-cloudwatch
#javascript #node.js #aws-lambda #amazon-cloudwatch
Вопрос:
Я ищу решение, с помощью которого я мог бы безопасно (и почти надежно) генерировать метрики CW (putMetricData) в синхронном коде. Мой вариант использования выглядит следующим образом:
// Lambda Main Handler
export const handler = async () => {
await step1Aync();
step2Sync();
step3Sync();
return {};
}
async function step1Aync() {
await doSomething();
await doSomething();
// could await this call, but dont want to since I dont need the value, nor do I want to handle failures
cloudwatch.putMetricData();
}
function step2Sync() {
doSomething();
// do not want to make this function async to use await here
cloudwatch.putMetricData();
}
function step3Sync() {
doSomething();
// do not want to make this function async to use await here
cloudwatch.putMetricData();
}
Я понимаю, что, поскольку putMetricData
запросы передаются в цикл событий Lambda, нет никакой гарантии, что они в конечном итоге отправят свой HTTP-запрос в CW (поскольку контекст выполнения Lambda может зависнуть до выполнения запроса). Это, конечно, если я не создаю step2Sync
и step3Sync
не использую асинхронно await
для каждого обещания.
Часть моих рассуждений здесь заключается в том, что я хотел бы сократить время отклика лямбды, специально не обрабатывая ответы от CloudWatch. Этот лямбда-интерфейс является чувствительным ко времени API (API Gateway). Если «некоторые» запросы на CW завершаются неудачей (менее 1%), все в порядке.
Я читал, что если снова использовать тот же лямбда-контекст, он опустошит цикл событий. Однако это НЕ гарантировано. Я не знаю, что такое SLA, так сказать.
Короче говоря, я не хочу использовать асинхронные функции, когда в этом нет явной необходимости. Правильно ли я понимаю?
Ответ №1:
Возможное решение:
Определите глобальный массив, который постоянно добавляется, а затем сбросьте массив в CloudWatch одним Promise.all
вызовом в конце функции. Нам все еще нужно дождаться вызовов, но это выполняется одновременно или параллельно в конце (в зависимости от базового silicon).
// массив глобальных показателей
export const PENDING_METRICS: PutMetricDataInput[] = [];
// обработчик
// Lambda Main Handler
export const handler = async () => {
await step1Aync();
step2Sync();
step3Sync();
// emit all of the metrics
await Promise.all( PENDING_METRICS.map(emitMetricToCloudWatch) );
// clear the global array for safety
PENDING_METRICS.length = 0;
return {};
}
async function step1Aync() {
await doSomething();
await doSomething();
PENDING_METRICS.push(PutMetricDataInput)
}
function step2Sync() {
doSomething();
PENDING_METRICS.push(PutMetricDataInput)
}
function step3Sync() {
doSomething();
PENDING_METRICS.push(PutMetricDataInput)
}
// Код CloudWatch
export const emitMetricToCloudWatch = async (client, input) => client.putMetricData(input);
Примечание: глобальные объекты могут перетекать в другие контексты выполнения. Поэтому массив необходимо очищать после отправки каждой метрики.