Рубрики
Без рубрики

Изучение бессерверности с помощью Python, пошаговых функций и веб-интерфейса

Бессерверное приглашение slack и проект регистрации сообщества. Шаблон проекта Python без сервера. История моего исследования без сервера. Советы, рекомендации, ссылки.

Автор оригинала: Dmitri Zimine.

Бессерверное приглашение slack и проект регистрации сообщества. Шаблон проекта Python без сервера. История моего исследования без сервера. Советы, рекомендации, ссылки. Первоначально опубликовано dzimine@medium

Slack invite был каноническим примером бессерверного приложения. Но что, если вы хотите сделать что-то более сложное? Например , наша регистрация сообщества StackStorm , где мы просим Slack пригласить пользователя, а также записать его в активную кампанию CRM с соответствующими тегами и создать запись пользователя в базе данных? Идеальный случай для стартового проекта без сервера, более реалистичный, чем aws-python-rest-api-with-dynamodb , но менее пугающий, чем витрина “Hello Retail” . И, для разнообразия, это на Python!

Код находится по адресу https://github.com/dzimine/slack-signup-serverless . Там вы найдете:

  • Стандартный проект Python для лямбда-функций с бережливым управлением зависимостями, модульным тестированием в соответствии с развертыванием лямбда-кода и сборкой на основе tox для упаковки и непрерывной интеграции.
  • AWS Выполняет пошаговые функции для определения логики лямбда-вызовов.
  • Веб-интерфейс, развернутый на S3 с помощью шлюза API.

Схема приложения для регистрации сообщества без сервера.

Развертывание полностью автоматизировано: вы можете использовать его “как есть”: клонировать код, настроить учетные данные и запустить (enjoy Evan Powell !). Или используйте код в качестве отправной точки: измените и добавьте шаги, измените стиль веб — формы-настройте ее по своему вкусу или полностью перепрофилируйте.

Читайте дальше историю моего исследования без сервера. Наслаждайтесь и используйте советы, рекомендации и ссылки, распространяемые по пути. Или сразу перейти к Резюме и прокомментировать мои выводы.

1. Лямбда

Получение лямбда-функций-это легкий ветерок с serverless.com . Чтобы оценить это, я сначала попытался реализовать original serverless-slack-invite в Python с помощью raw AWS Lambda. Я потратил на это целый день, и настройка шлюза API была настолько болезненной, что < некоторые серьезные ругательства были удалены отсюда >. Мне потребовался час, чтобы переделать его с помощью Serverless — повышение производительности в 10 раз! и радость от наличия четкой, воспроизводимой инфраструктуры в виде кода. Несколько заметок об эффективной лямбде с Python:

Структура проекта. Следует ли вам следовать “hello-retailer” и создать uber-проект, где каждая лямбда-это отдельная бессерверная услуга? Или пойти на один бессерверный сервис проекта) с мелкозернистым управлением частями? Попробовав и то, и другое, я понял, что один проект выигрывает за 3-7 услуг. По мере того, как число сервисов растет за дюжину, а разные разработчики работают над разными сервисами с разной частотой развертывания, пришло время его разбить. Имейте в виду, что все управление uber-проектом — сборка, развертывание, зависимости от служб, управление версиями — не подпадает под бессерверный фреймворк, и вам будет интересно изобретать и поддерживать его.

Переменные среды : элегантный способ управления переменными среды-это один файл env.yml YAML с разделом для каждой службы. Затем вы можете использовать environment: ${file(env.yml):my_service для передачи специфичного для службы раздела env.yml в Lambda в виде единого набора переменных среды. Имя файла -“. gitignore”, чтобы предотвратить передачу ваших секретов на GitHub.

Зависимости Python: Создание лямбда-пакетов с достаточным количеством зависимостей надежно удерживает вас в пределах Ограничений размера лямбда-пакетов и делает развертывание приятным и быстрым.

Первым шагом является указание serverless управлять лямбда-функциями индивидуально. Это достигается путем установки package/индивидуально: true и определения раздела package для каждой функции в serverless.yml .

Затем подготовьте зависимости Python. Есть несколько бессерверных плагинов, которые помогут в этом. Для простых случаев я рекомендую serverless-python-requirements . Если ваш Lambda вызывается как веб-служба, и вы настраиваете шлюз API как lambda-прокси , делая управление запросом-ответом на код функции Lambda, a https://github.com/logandk/serverless-wsgi плагин-это хороший способ.

Я предпочел не использовать плагины и управлять зависимостями от кода, опираясь на эту бессерверную подсказку форума . “Бережливые” лямбда-пакеты ускоряют развертывание и обеспечивают безопасность в пределах ограничений размера пакета AWS lambda. Самое главное, что эта настройка позволяет локальному модульному тестированию соответствовать удаленному выполнению. В build.sh скрипт автоматизирует построение зависимостей, и tox используется для полной сборки и тестирования Python. Обратите внимание, что setup.cfg требуется для этой подсказки AWS .

Модели программирования и расхождения в вызовах. В процессе разработки и тестирования я пробовал и вызывал свои лямбда — функции по-разному-как отдельную службу, как часть тестирования с помощью бессерверной cli и консоли AWS, а также как пошаговую функцию. Здесь следует обратить внимание на то, что тип и структура входных и возвращаемых значений, а также обработка исключений различны для разных типов вызовов. Когда Лямбда вызывается из шлюза API, бессерверный фреймворк поощряет лямбда-прокси метод : “Мы настоятельно рекомендуем использовать метод лямбда-прокси, если он поддерживает ваш вариант использования, так как метод лямбда очень утомителен”. С помощью “лямбда-прокси” полный HTTP-запрос передается обработчику во входном параметре event , оставляя обработчику анализировать тело и возвращать правильный HTTP-ответ для успеха и сбоев, например, 500 в случае ошибок службы. (Если вы выберете этот маршрут, рассмотрите упомянутый плагин serverless-wsgi

Вы можете придерживаться AWS mainstream преобразования строки в JSON на шлюзе API и сигнализировать о сбоях, создавая исключения Python. Это упрощает обработчик лямбда-кода Python, но усложняет часть конфигурации шлюза API в serverless.ямл . Выбери свой яд.

Когда Лямбда вызывается из Шаговой функции, событие | содержит входные данные для шага Шаговой функции. Обработчик возвращает объект для вывода шага и выдает исключение при сбоях. Особая осторожность необходима для передачи входных данных API в Лямбды вниз по шаговой функции (подробнее об этом в разделе "Шаговая функция" ниже).

Наконец, мы часто вызываем Лямбду из бессерверного CLI, как часть удобного рабочего процесса устройств, предлагаемого бессерверным:

sls invoke stepf --name signup --data '{"foo":"bar"}'

Бессерверный сначала пытается проанализировать входные данные как JSON и передает dict , возвращаясь к строке, если анализ не удался. Это облом, если вы следовали бессерверной рекомендации использовать lambda-proxy и ожидали события в виде строки JSON в своем обработчике. Однако не беспокойтесь: если вы попробовали, вы уже знаете об этом, если нет, эта ошибка , скорее всего, будет исправлена к тому времени, когда вы попробуете.

2. Проводная логика с рабочим процессом пошаговой функции.

Рабочие процессы играют важную роль в объединении логики отдельных лямбда-вызовов в полные бессерверные решения. Бессерверная платформа не поддерживает пошаговые функции в “ядре”, но есть плагин serverless-step-functions , который это делает. Я решил использовать его вместо подхода raw CloudFormation, показанного в Hello Retail .

AWS Step Functions заслуживает отдельного обзора, но я дам вам БОЛЬШОЕ СМЕЛОЕ ПРЕДУПРЕЖДЕНИЕ прямо здесь. При любом изменении история выполнения исчезает. То есть: функции шага неизменяемы; любое изменение создает новый экземпляр, предыдущий экземпляр удаляется (пока все в порядке), и история выполнения предыдущего экземпляра исчезает вместе с удаленным экземпляром (действительно? ВТФ!!!)

Если это не мешает вам использовать пошаговые функции, читайте дальше, чтобы узнать несколько трюков.

Передача входных данных рабочего процесса в шаги. Поток данных пошаговой функции, разработанный на основе “необходимости знать”: по умолчанию никакие дополнительные данные не передаются. Первый лямбда-код получает входные данные рабочего процесса (тело вызова REST API). Вторая лямбда получает только вывод первой лямбды. Но я хочу, чтобы все шаги Лямбды были доступны для ввода рабочего процесса! Хитрость здесь заключается в том, чтобы использовать Путь к результату : это способ управления ключом, в котором результат выполнения Лямбды помещается в состояние рабочего процесса. По умолчанию Result Path=$ устанавливает ключ в корневой контекст, чтобы он перезаписывал начальный ввод рабочего процесса. Но если мы добавим результат каждой лямбды под некоторым ключом, например Result Path: $.results.При использовании черного ( как это ) входные данные рабочего процесса сохраняются и могут использоваться всеми шагами Лямбда.

Вызов пошаговых функций из serverless-это радость: плагин запускает рабочие процессы, следит за выполнением и распечатывает результаты каждого шага по мере его выполнения:

sls invoke stepf --name signup --data '{"email":"your@email.com", "first_name":"Donald", "last_name":"Trump"}'

Предоставление доступа через API, вызов из Интернета и работа с CORS. Выставление методов пошаговых функций с помощью шлюза API так же просто с помощью плагина, как и с бессерверной лямбдой. Но мне нужно вызвать его из WebUI, размещенного на s3. Для этого требуется конфигурация CORS, которую плагин не поддерживал в то время (теперь он поддерживает). Я не знал, что делать. Есть ли “лямбда” перед функцией шага только для того, чтобы вызвать ее? И платить за это? Не-е-ет. Перейти на темную сторону и использовать CloudFormation для настройки всех шлюзов API? Нет-о-о веселья. Ответ? Читайте дальше, чтобы “Добавить веб, без CORS”.

Что выбрать? Ночь на перекрестке , классический русский эпос о Ложном выборе Заблуждения.

1*_nceOvoxc6VfG4w5oPXCpg.jpeg

3. Добавьте Web, без CORS.

Третий, выигрышный способ был представлен плагином serverless-api-s3 . Плагин делает две вещи. Он помещает веб-контент на S3, как указано в serverless.yml ( ./web в моем случае ), и включает веб-доступ. Он также настраивает шлюз API для обслуживания статического контента из того же домена, обходя любые проблемы CORS. Есть некоторые другие плагины для работы с веб-интерфейсом, но для меня выигрывает обход ядер.

Пара неудач, за которыми нужно следить:

При добавлении или удалении веб-файлов недостаточно развернуть клиент, требуется полное развертывание sls . Это имеет смысл, когда вы знаете, как все работает: часть шлюза API плагина изменяет стек CloudFormation, который необходимо обновить, а часть sls client deploy помещает файлы в корзину s3.

Я добавил изображение в форму, настраивая его для регистрации сообщества StackStorm. Изображение не проходило. Мне потребовалось некоторое время, чтобы понять, почему: двоичные полезные нагрузки не включены по умолчанию и должны быть настроены . Если вам это понадобится, настройте его вручную, с помощью CloudFormation, попробуйте serverless-apigw-binary plugin или сделайте PR, чтобы исправить https://github.com/sdd/serverless-apig-s3/issues/12 .

Резюме

Бессерверный фреймворк работает как шарм для Лямбды. По мере расширения за пределы “FaaS” до более широкого “бессерверного” набора услуг все становится сложнее. Вы либо полагаетесь на плагины, где milage варьируется, либо переходите на темную сторону AWS CloudFormation. Тем не менее, фреймворк Serverless намного опережает конкурентов, признавая и поддерживая тот факт, что Serverless > FaaS.

Фреймворк без сервера хорошо разработан. Это делает общие задачи и конфигурации действительно простыми, обеспечивает надежную расширяемость для изменения и расширения набора функций “ядра” с помощью плагинов. Для расширенных конфигураций и вещей, которые еще не поддерживаются, пользователь может вернуться к облачным конфигурациям. Вы будете писать шаблоны CloudFormation для любого, кроме тривиального проекта, но фреймворк помогает поместить его в код и вплести в жизненный цикл разработки.

Экосистема плагинов динамична — многие проблемы, с которыми я столкнулся, были исправлены за время написания блога. Проверьте кураторский список бессерверных плагинов , когда вы что-то упускаете: возможно, он уже есть или дает вам подсказку. Экосистема по-прежнему чувствует себя “дикой” и “ранней”, выиграет от большего внимания, кураторства и вклада основной команды @goserverless. Я уверен, что они доберутся туда.

Хмм… В чем разница между этими двумя плагинами, на самом деле?

Сообщество пользователей большое, милое и полезное. Между documentation , Gitter chat , forum и Github я быстро нашел ответы на свои вопросы.

Лингвистическая гнида: С serverless , именем фреймворка, и serverless , большой тенденцией, пишущей об использовании serverless/| для serverless/| приближается к поэзии: “A serverless is a serverless is a serverless” [*] .

Самая лучшая часть? Как только код написан, он развертывается как заклинание с без сервера . Клонирование кода, настройка учетных данных, построение зависимостей, развертывание:

serverless deployserverless client deploy

и наслаждайтесь преимуществами #бессерверных вычислений.

Проверьте последние истории Дмитрия Зимина или следуйте @dzimine в Twitter .