В зависимости от документации AWS, которую я читаю, я вижу разные методы доступа к полезной нагрузке функций AWS Lambda, что приводит к разным и несовместимым реализациям.
Обычно, согласно документации AWS и практическим экспериментам, на примере лямбды, вычисляющей area
на основе length
и width
, нам потребуются разные реализации для поддержки этих двух вызовов:
aws lambda invoke --function-name $MY_LAMBDA_NAME \
--payload '{"length": 10, "width": 10}' \
--cli-binary-format raw-in-base64-out /dev/stdout
И:
curl $MY_LAMBDA_URL -H 'Content-Type: application/json' \
-d '{"length": 10, "width": 10}'
Например, в Начало работы с Lambdaevent
— это документ JSON, содержащий полезную нагрузку. В документации указано: «Если ваша функция вызывается другим сервисом AWS, объект события содержит информацию о событии, вызвавшем вызов». Предоставленный пример реализации работает, как описано, при вызове лямбды через консоль, aws cli и т. д. Он не работает при вызове лямбды через Curl, Postman и т. д. Доступ к length
и width
выглядит следующим образом:
def lambda_handler(event, context):
length = event["length"]
width = event["width"]
...
На других страницах документации AWS полезная нагрузка представляет собой строку, доступную через event
body
. Одним из таких примеров является Учебное пособие: Создание лямбда-функции с URL-адресом функции. Предоставленный пример реализации работает при вызове лямбды через Curl, Postman и т. д. Однако он не будет работать при вызове лямбды через консоль, aws cli и т. д. В этом случае доступ к length
и width
выглядит следующим образом (концептуальное преобразование из узла в питон):
def lambda_handler(event, context):
# requires more work to check for encoding, etc.
body = json.loads(event["body"])
length = body["length"]
width = body["width"]
...
Помимо бездействия, я могу придумать два очевидных способа устранить это несоответствие:
event
и почему такое поведение варьируется в зависимости от контекстаevent
(в основном проверяет, содержит ли он body
или нет, поддерживает различные кодировки и т. д.)Первый вариант неудовлетворителен, поскольку вызывает ненужную головную боль при обслуживании. Второй вариант неуклюж и может вызвать недоумение у разработчиков, которые не читали эту часть документа.
Каковы разумные варианты устранения этого несоответствия? Есть ли в документации AWS разделы, содержащие хорошие рекомендации? Есть ли способы настроить лямбды AWS, чтобы устранить несоответствие? Существуют ли способы вызова лямбды, которые приводят к единообразному поведению независимо от того, вызывается ли она через другой сервис AWS или нет?
Функции AWS Lambda обычно пишутся с явным знанием данных, которые передаются им через event
. Редко можно написать функцию, которая получает разные типы входных данных.
Это похоже на обычную «функцию», которую можно использовать в программе Python: функции пишутся так, чтобы принимать определенные входные данные и выполнять определенные действия. Редко можно написать функцию на Python, которая должна выяснить, какие входные данные ей были переданы и что она должна делать с этими входными данными.
В ваших примерах, если функция предназначена для вычисления площади прямоугольника, то в качестве входных данных она будет ожидать length
и width
. Он не знает, как обрабатывать событие, генерируемое Amazon S3 при создании нового объекта, и не должен этого делать — цель функции — вычислить площадь прямоугольника, а не реагировать на создание новых объектов.
Как и при определении функции на любом языке программирования, знание входных данных очень важно для написания функции.
Если вы не понимаете, что передается в функцию, вы можете добавить print(event)
в начало lambda_handler()
функции. Это выведет содержимое события в журнал. Вы можете использовать CloudWatch Events, чтобы просмотреть журнал и узнать, что было передано в функцию.
Вас также может заинтересовать Анонс URL-адресов функций AWS Lambda: встроенные конечные точки HTTPS для однофункциональных микросервисов | Блог новостей AWS. Это дает возможность вызвать функцию Lambda из Интернета без использования шлюза API.
Обычно для каждого типа ввода используются разные лямбда-функции. Например, если вы реагируете на новые объекты, создаваемые в S3, вы, вероятно, захотите выполнить операции над объектом. Если вы отвечаете на сообщения из очереди Amazon SQS, вам, вероятно, захочется что-то сделать с содержимым сообщения. Если вы отвечаете на запросы API-шлюза, вы, вероятно, захотите обработать данные, предоставленные в HTTP-запросе. Каждый из них представляет собой совершенно разные варианты использования, и их следует обрабатывать с помощью разных функций Lambda.
Извините, если я утомляю, но это настолько удивительно, что мне хотелось бы подтверждения. Вы хотите сказать, что если мне нужен один сервис «calculate_area», который принимает длину и ширину в качестве входных данных и возвращает площадь=длина*ширина, я должен реализовать, развернуть и управлять двумя разными лямбда-выражениями: «calculate_area_when_invoked_through_aws» и «calcul_area_when_invoked_ Differently»? Это то, что обычно делают люди в мире AWS? Если да, то как они справляются с понесенными накладными расходами? Для этого нужны лямбда-слои?
@ComeRaczy Обычно вы пишете одну лямбда-функцию для каждого процесса (например, вычисления площади). Все, что вызывает эту функцию, желательно передавать входные данные таким же образом (например, JSON, содержащий length
и width
). Я не уверен, что вы подразумеваете под «вызывать через AWS» и «вызывать по-другому», но вы можете закодировать функцию, которая будет принимать любые входные данные и выполнять любую операцию по вашему желанию — это ваш код, поэтому вы можете делать то, что хотите. ты хочешь.
@JohnRotenstein, это и есть суть проблемы: AWS не передает входные данные так же, как Curl. если я реализую лямбду, чтобы можно было вызывать ее дома с помощью Curl, width
и length
находятся внутри элемента body
. Если по какой-либо причине я решу вызвать лямбду через любую функциональность AWS, например. aws lambda invoke
— Мне нужно изменить реализацию, иначе лямбда выйдет из строя, потому что AWS передает входные данные по-другому — доступ к length
и width
должен осуществляться напрямую, а не к элементу body
. И я, кажется, не могу это контролировать, потому что это вне моего кода.
Если вы используете aws lambda invoke
, вы можете предоставить полезную нагрузку, соответствующую curl
. Например, --payload '{"body": {"length": 10, "width": 10}}'
Вас также может заинтересовать: Анонс URL-адресов функций AWS Lambda: встроенные конечные точки HTTPS для однофункциональных микросервисов | Блог новостей AWS
@JohnRotenstein Это действительно то, что меня интересовало! Поначалу это казалось немного жестковатым, но эти URL-адреса лямбда-функций, безусловно, имеют большую ценность. Пожалуйста, добавьте это к своему ответу, чтобы я мог его принять. Большое спасибо за ваше время и приверженность.
Спасибо за ваш ответ. Я полностью согласен с тем, что «как и определение функции на любом языке программирования, знание входных данных очень важно для написания функции». Исходя из этого, могли бы вы предложить, как справиться с тем фактом, что мы получаем разные события в зависимости от того, как вызывается лямбда?