Ответ довольно прост, если вам нужен ответ. Но что, если вы не хотите ждать ответа?
HTTP без ожидания
Рассмотрим случай функции Lambda, которая после обработки накапливает некоторые метрики, а затем отправляет их обратно в службу агрегатора REST для обработки. Если метрики являются счетчиками, может не иметь значения, если запрос метрик иногда завершается ошибкой, так как следующий запрос отправит обновленные итоговые значения счетчика. В подобных случаях будет быстрее не ждать ответа HTTP.
Так как же нам это сделать в NodeJS?
Давайте сначала рассмотрим наивный пример запроса (без обработки ошибок), где мы ждем ответа.
Только для этого примера мы создадим асинхронную функцию узла «запрос», которая возвращает обещание, которое мы можем ждать.
```javascript
константа https = требуется ('https')
постоянный URL = требуется('url')
запрос асинхронной функции (url, данные) {
вернуть новое обещание ((разрешить, отклонить) => {
пусть req = https.request(URL.parse(url), function (res) {
пусть тело = ''
res.on('данные', (фрагмент) => {тело += фрагмент})
res.on('конец', () => { разрешение(тело) })
требуется запись (данные)
запрос.конец()
Тогда наша лямбда будет выглядеть так:
```javascript
exports.handler = асинхронный (событие, контекст) {
let result = await request('https://metric-service.com', metrics)
вернуть результат
Чтобы вызвать наш HTTP-запрос внутри Lambda, мы используем «ожидание», которое выдает запрос, а затем ожидает ответа.
Если службе агрегатора метрик требуется 950 миллисекунд для обработки запроса и возврата кода состояния, нам будет выставляться счет за дополнительную секунду при каждом вызове.
В течение этого времени ожидания наша функция Lambda неактивна, но AWS по-прежнему выставляет нам счет за это время. При использовании AWS Lambda вы платите за прошедшее время, а не за использованное процессорное время.
Хотя Lambda необычайно дешев, с большими объемами транзакций, эти короткие ожидания в 950 миллисекунд могут составить значительный счет.
Не ждите
Итак, что произойдет, если мы просто не вызовем «ожидание» и, следовательно, не будем ждать ответа на наш HTTP-запрос?
```javascript
exports.handler = асинхронный (событие, контекст) {
/ подождите / request('https://example.com', метрики)
вернуть «готово»
:::Информация
Странные вещи случаются
Иногда запрос отправляется, а иногда запрос не отправляется.
Иногда запрос поступает агрегатору метрик сразу, а иногда запрос поступает после следующего запуска нашей лямбды. Что происходит?
Замораживание контейнеров Lambda
Функции Lambda выполняются внутри контейнера AWS Firecracker. Когда вы возвращаетесь из функции Lambda, AWS немедленно замораживает контейнер и его глобальное состояние. При следующем вызове Lambda контейнер разморозится для обслуживания нового вызова.
Если мы отправим HTTP-запрос, и этот запрос не будет полностью отправлен по сети, и мы вернемся из функции Lambda, AWS немедленно приостановит работу нашего контейнера Lambda, И частично отправленный запрос также будет приостановлен. Запрос останется замороженным до тех пор, пока Lambda не будет вызвана в следующий раз, после чего цикл событий Node возобновит обработку, и запрос будет полностью передан.
Как решить?
Мы могли бы попробовать короткий сон, чтобы дать время для отправки запроса? Но как долго мы должны ждать.
```javascript
exports.handler = асинхронный (событие, контекст) {
/ подождите / request('https://example.com', метрики)
жду сна(100)
вернуть «готово»
Это вряд ли кажется надежным.
Ожидание передачи запроса
Правильное решение — использовать Node req.end(,,callback) API и дождаться полной отправки запроса, но не ждать получения ответа.
Вот пример:
```javascript
константа https = требуется ('https')
постоянный URL = требуется('url')
запрос асинхронной функции (url, данные) {
вернуть новое обещание ((разрешить, отклонить) => {
пусть запрос = https.request(URL.parse(url))
требуется запись (данные)
req.end(null, null, () => {
/ Запрос полностью отправлен /
разрешить (требуется)
Обратите внимание, что запрос разрешается с помощью обратного вызова end на объекте «req», а не на объекте «res» в предыдущем примере.
Эта модифицированная функция запроса должна вызываться нашей лямбдой с помощью «ожидания». В этом случае мы ждем не ответа HTTP, а полной отправки запроса. Это намного быстрее, чем 750 миллисекунд для получения ответа с нашими показателями, обычно менее 20 миллисекунд.
```javascript
exports.handler = асинхронный (событие, контекст) {
ожидание запроса('https://example.com', метрики)
вернуть «готово»
Альтернативные шаблоны проектирования
Есть много других отличных способов избежать ожидания и блокировки в функциях Lambda, таких как использование функций Step, очередей SQS и прямой вызов функций Lambda как событий без ожидания. Подумайте о наилучшем подходе для вашего приложения, но если вы должны использовать HTTP и вам не нужно ждать ответа, рассмотрите описанный выше метод, чтобы сократить время ожидания и счет за AWS.
SenseDeep
Наша SenseDeep Serverless Developer Studio использует этот метод в Watcher Lambda, который отслеживает ваши Lambda, запускает сигналы тревоги и получает данные журнала. Нам нужно, чтобы Наблюдатель был исключительно быстрым и не ждал никаких запросов REST/HTTP API. Таким образом, Наблюдатель использует этот метод без ожидания при отправке статуса обратно в сервис SenseDeep.

Чтобы узнать больше о SenseDeep Serverless Developer Studio и попробовать ее бесплатно, перейдите по ссылке: https://www.sensedeep.com.
Использованная литература
Вот еще несколько полезных материалов об асинхронном программировании Lambda и AWS.
- Замораживание цикла событий узла: https://levelup.gitconnected.com/avoiding-the-pitfalls-of-async-node-js-functions-in-aws-lambda-941220582e7a
- Lambda Billing: https://www.jeremydaly.com/serverless-tip-dont-overpay-when-waiting-on-remote-api-calls/
- Асинхронное программирование: https://read.acloud.guru/save-time-and-money-with-aws-lambda-using-asynchronous-programming-3548ea65f751
- Опасности ступенчатых функций: https://blog.scottlogic.com/2018/06/19/step-functions.html
- Вызов асинхронного режима Lambda: https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html
- Обзор вызовов Lambda: https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html