Настройка подготовленного параллелизма для ваших веб-приложений

AWS Lambda - это экономичное и хорошо масштабируемое решение для бессерверных вычислений, которое упрощает запуск кода без развертывания серверов и управления ими. В результате большое количество предприятий предпочитают развертывать свой производственный код в AWS Lambda, чтобы обслуживать своих клиентов. Значительная часть этого кода - это приложения веб-сервера, которым необходимо быстро (‹1 с) отвечать на запросы пользователей. Холодный запуск AWS lambda может затруднить выполнение этого требования к производительности.

В этом блоге рассматривается решение проблем холодного запуска с использованием подготовленного параллелизма. Охваченные разделы включают:

  • Что такое холодный запуск?
  • Что такое подготовленный параллелизм?
  • Настройка Provisioned Concurrency с помощью консоли
  • Программная настройка Provisioned Concurrency. (полезно для конвейерной обработки CI / CD)
  • Использование подготовленных экземпляров
  • Использование событий облачного наблюдения

Что такое холодный старт?

Несмотря на значительные преимущества AWS Lambda, одним из его основных недостатков является проблема классического холодного запуска.

Это то место, где первый запрос, который новый рабочий процесс Lambda обычно выполняет относительно долго, то есть 3–20 секунд. Это недостаток того, как работают бессерверные функции, такие как AWS Lambda или Google Cloud Functions, поскольку они пытаются оптимизировать по цене, масштабируемости и удобству обслуживания. Обычно жизненный цикл бессерверной функции при создании среды выполнения выглядит следующим образом (согласно документации AWS):

  1. Создайте или разморозьте среду выполнения с настроенными ресурсами, то есть выделите соответствующий ЦП и память, необходимые для запуска кода приложения (этап инициализации).
  2. Загрузите любой код, необходимый для приложения, расширений и слоев, которые использует функция Lambda (этап инициализации).
  3. Инициализируйте расширения и среду выполнения, а также любой код приложения, который находится за пределами функции основного обработчика (этап инициализации).
  4. Когда запрос отправляется, Lambda затем вызывает обработчик функции, который запускает вашу основную бизнес-логику (фаза вызова). Второй вызов функции Lambda пропускает шаги 1, 2 и 3, следовательно, время отклика гораздо меньше.
  5. Если по прошествии определенного периода времени не происходит никаких вызовов, например Максимум 15 минут, AWS Lambda завершает работу среды выполнения, останавливает расширения и удаляет среду. (фаза выключения)

Как видите, в жизненном цикле функций есть 3 основные фазы: фаза инициализации, фаза вызова и фаза завершения. Фаза инициализации всегда происходит, когда новые экземпляры создаются либо во время новых развертываний, либо при масштабировании функции Lambda. Во время холодного запуска фаза инициализации и иногда фаза вызова являются узкими местами процесса.

Следует отметить несколько важных моментов:

  • Процесс масштабирования не обязательно означает, что у вас есть несколько пользователей на платформе, если вы запускаете веб-приложение с интерфейсом javascript, обычно несколько запросов отправляются на поддерживаемый конец одновременно, например. получить информацию о пользователе, получить конфигурацию пользователя и т. д. Если один из этих запросов получен, когда функция Lambda уже обрабатывает предыдущий запрос, будет создан новый экземпляр Lambda, таким образом пройдя этап инициализации и вызова. Это может произойти, даже если у вас есть один пользователь на платформе, при условии, что пользователь одновременно отправляет несколько запросов на бэкэнд.
  • Фаза вызова может быть медленной при первоначальном запуске. Это связано с тем, что даже несмотря на то, что Lambda инициализирует код приложения вне метода основного обработчика на этапе инициализации, иногда код приложения также должен инициализироваться изнутри, то есть подключаться к соответствующей БД, загружать конфигурации, выполнять проверки работоспособности и т. Д. (Особенно в Интернете сервер).

Что такое предоставленный параллелизм?

Есть несколько способов уменьшить проблемы с холодным запуском. Обеспеченный параллелизм - один из таких инструментов в арсенале.

Обычно минимальное количество рабочих экземпляров Lambda, которые остаются активными для обработки входящих запросов, зависит от последнего вызова экземпляра Lambda. Это означает, что если экземпляр не вызывается в течение определенного периода времени, он будет отключен, и в конечном итоге не останется доступных экземпляров для обработки новых запросов.

Предоставленный параллелизм просто выделяет определенное количество экземпляров Lambda, которые всегда будут доступны для обработки запросов. Эти экземпляры не закрываются после завершения вызова и должны быть отключены вручную.

При создании подготовленного экземпляра он решает проблемы холодного запуска, связанные с этапом инициализации жизненного цикла функции. Однако, если на этапе вызова все еще требуется дополнительная внутренняя инициализация, например при подключении к базе данных и т. д. он по-прежнему будет встречаться на вновь подготовленных экземплярах.

Подготовленные экземпляры, которые уже обработали запрос, не столкнутся с этой проблемой при последующих запросах, пока экземпляр не будет завершен. Чтобы исправить холодные запуски вызова, события облачного наблюдения полезны, хотя и не необходимы, особенно при развертывании новых экземпляров в настройке CI / CD.

Учет стоимости

Важно отметить, что подготовленный параллелизм не является бесплатным, и это связано с соответствующими затратами. Стоимость рассчитывается с момента запуска подготовленного экземпляра до момента его завершения и зависит от объема памяти, выделенной для функции, а также от количества подготовленных экземпляров.

Например, предполагая, что объем памяти 512 МБ на экземпляр в регионе us-east-1; 1 инстанс будет стоить 5,58 доллара в месяц, 5 экземпляров - 27,90 доллара, 50 - 279,02 доллара, 500 - 2790,22 доллара и т. Д. График ниже показывает эту тенденцию.

Как видите, цена изменяется линейно, поэтому примите это во внимание при создании подготовленных экземпляров.

Предоставленный параллелизм не является зарезервированным параллелизмом

Одна из возможных ошибок - использовать зарезервированный параллелизм для решения проблем с холодным запуском.

Установка параметра зарезервированного параллелизма устанавливает максимальное количество экземпляров, которые может создать лямбда-функция. Например, если для него установлено значение 5, это означает, что будет разрешено не более 5 экземпляров, следовательно, может быть обработано только 5 одновременных запросов, любой запрос вторичного распространения будет возвращен с ошибкой 5XX.

Настройка Provisioned Concurrency из консоли AWS

Псевдоним и версии

Прежде чем мы создадим подготовленные экземпляры, необходимо базовое понимание псевдонима и версии, поскольку они определяют, какая кодовая база будет развернута в подготовленных экземплярах.

Версия обычно представляет собой автоматически увеличивающееся целое число, где последнее целое число, например 77 указывает последнюю опубликованную версию. Версия также имеет тег $LATEST , который автоматически сопоставляется с последней опубликованной версией вашей кодовой базы. Доступ к лямбда-функции можно получить двумя способами;

  1. Использование неквалифицированного ARN, например arn:aws:lambda:aws-region:acct-id:function:helloworld, этот метод неявно вызывает тег $ LATEST.
  2. Использование квалифицированного ARN, например arn:aws:lambda:aws-region:acct-id:function:helloworld:<version|alias>, где <version|alias> может быть числом, например 42 для версии или определенного псевдонима и вызывает конкретную версию кодовой базы.

Псевдоним - это просто указатель на конкретную версию, который упрощает обновление кода приложения без необходимости обновлять вышестоящие службы, например. API Gateway, Dynamodb и т. Д., Использующие лямбда-функции с квалификацией ARN.

При создании подготовленных экземпляров нельзя использовать тег версии $LATEST или использовать псевдоним, указывающий на версию $LATEST. Вам необходимо указать конкретную опубликованную версию.

Создание псевдонима

При выборе между использованием псевдонима или версии лучше использовать псевдоним вместо версии. Это упростит конвейер CI / CD, особенно при использовании шлюза API и любых связанных служб, которым необходимо использовать квалифицированный ARN.

Чтобы создать псевдоним, выберите вкладку псевдонима и затем нажмите кнопку добавления псевдонима. Должен быть показан следующий вид:

Выберите имя своего псевдонима, а затем выберите версию, с которой должен быть связан псевдоним. Обратите внимание: при обновлении псевдонима всегда проверяйте взвешенный псевдоним и, если он установлен, измените его на 0. Однако этого не должно быть, если это делается программно.

Создайте подготовленные экземпляры

После создания псевдонима теперь можно создавать подготовленные экземпляры. Для начала выберите вкладку Конфигурация, а затем выберите ссылку подготовленного параллелизма в боковой панели навигации, как показано ниже.

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

Вы также увидите связанную стоимость подготовленного экземпляра для этого конкретного региона. Первоначально статус будет In progress, а через несколько минут он должен измениться на Ready, когда все экземпляры будут подготовлены.

Программная настройка Provisioned Concurrency

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

Эта часть кода заимствована из alecl из комментария к проблеме в пакете Django Zappa. Он дает представление о том, как обновлять LIVE-версию и создавать новые экземпляры. Измененный сценарий выглядит следующим образом:

function_name=<my-function-name>
alias=LIVE
instances=5
deployedversion=$(aws lambda list-versions-by-function --function-name $function_name --region $REGION --query "to_number(Versions[-1].[Version][0])" --no-paginate)
echo "Resetting provisioned concurrency on alias LIVE"
aws lambda delete-provisioned-concurrency-config --region $REGION \
    --function-name $function_name \
    --qualifier LIVE
echo "Updating alias LIVE to $deployedversion"
aws lambda update-alias \
    --function-name $function_name \
    --function-version $deployedversion \
    --name $alias
echo "Setting provisioned concurrency to $instances"
aws lambda put-provisioned-concurrency-config \
        --function-name $function_name \
        --qualifier $alias \
        --provisioned-concurrent-executions $instances

Сценарий предполагает наличие псевдонимов, а также подготовленных экземпляров, если их нет, его можно легко обновить с учетом этого сценария. Шаги, указанные в приведенных выше сценариях, следующие:

  1. Задайте переменные для имени функции, псевдонима и количества экземпляров.
  2. Получите последнюю развернутую версию базы кода.
  3. Удалите существующие подготовленные экземпляры, которые используют псевдоним LIVE. Если подготовленных экземпляров нет, это приведет к ошибке.
  4. Обновите псевдоним до последней развернутой версии, если псевдоним отсутствует, это должна быть команда create-alias вместо update-alias.
  5. Наконец, создайте подготовленную конфигурацию параллелизма, используя псевдоним, а также количество создаваемых экземпляров.

Использование подготовленных экземпляров

После создания подготовленных экземпляров с использованием псевдонима или версии. Всегда не забывайте использовать квалифицированный ARN с правильным псевдонимом или номером версии, например arn:aws:lambda:aws-region:acct-id:function:helloworld:<version|alias>.

Использование неквалифицированного ARN, например arn:aws:lambda:aws-region:acct-id:function:helloworld без указания псевдонима или номера версии означает, что будет вызываться $LATEST версия, которая не развернута на подготовленных экземплярах, поэтому возникнут проблемы с холодным запуском.

Использование событий Cloud Watch

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

Однако кто-то, знакомый с проблемой холодного запуска, может задаться вопросом, зачем нужно создавать подготовленные экземпляры, почему бы просто не использовать события облачного наблюдения для предварительного нагрева экземпляров?

Основная проблема с этим подходом заключается в том, что события облачного наблюдения являются синхронными, при этом минимальный временной интервал в запланированном событии составляет 1 минуту. Это означает, что в обычных условиях без использования подготовленных экземпляров или псевдонимов можно поддерживать работу только одного экземпляра.

Однако при предоставлении псевдонима с подготовленными экземплярами это единичное событие в минуту распределяется по количеству подготовленных экземпляров случайным образом, вызывая экземпляры Lambda.

Это полезно только тогда, когда среда выполнения изначально создается для подготовленных экземпляров. После вызова события облачного наблюдения становятся избыточными. Это означает, что этот шаг не является обязательным, но добавлен для полноты картины.

Для создания событий облачного наблюдения выберите сервис облачного наблюдения и в левой навигации выберите правила, как показано ниже.

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

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

Заключение

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

Если у вас есть какие-либо вопросы или вы хотите запланировать короткий звонок со мной, чтобы прояснить ситуацию, вы можете найти меня на https://mbele.io/mark

Спасибо за прочтение.

Использованная литература: