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

Раньше я представлялся техническим специалистам как бессерверный архитектор и прилагал все усилия для создания приложений с помощью Lambda, Step Functions или прямой интеграции через API Gateway в качестве единственной формы вычислений.

Но я ошибся в своих размышлениях. Это не обязательно идеальный способ создания программного обеспечения. Лучший способ создания программного обеспечения — тот, который решает бизнес-задачу с наименьшей совокупной стоимостью владения.

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

Установка рекорда прямо

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

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

Вероятно, самый большой миф заключается в том, что бессерверные сервисы предназначены исключительно для бессерверных приложений. Это неправда! Вы можете использовать бессерверные службы в любом программном обеспечении, будь то приложение на основе Kubernetes, локальное решение или бессерверный API. Эти сервисы предоставляют бессерверные возможности, такие как оплата за то, что вы используете, эластичное масштабирование (в том числе до 0, когда оно не используется) и простые операции управления/плоскости данных по принципу «это просто работает».

Вы можете использовать такие сервисы, как Amazon DynamoDB или MongoDB Atlas, в качестве основного хранилища данных в приложении на основе контейнера. Эти бессерверные службы баз данных предназначены для упрощения разработки и долгосрочного обслуживания за счет предоставления простых API-интерфейсов для выполнения мощных операций. Они отвлекают вас от обслуживания и управления оборудованием, чтобы ваши инженерные команды могли сосредоточиться на чем-то более важном — решении бизнес-задачи.

Они непомерно дороги «в масштабе»

Раньше я получал это от высших руководителей крупных предприятий. Прежде всего, не многие люди могут сформулировать, что на самом деле означает «в масштабе». Означает ли это количество платящих клиентов? Относится ли это к объему трафика, поступающего в ваше приложение? Это количество активных пользователей в день? Даже если мы все согласны с тем, что имеется в виду под «в масштабе», перспектива также играет большую роль в уравнении. Для стартапа «в масштабе» может означать 100 транзакций в час. Для крупных предприятий с несколькими арендаторами это может означать 10 000 транзакций в секунду.

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

Холодные пуски не запускаются

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

По какой-то причине многие люди предполагают, что это занимает несколько секунд и что большинство вызовов бессерверного API приводят к холодному запуску. Это не так, если у вас нет постоянно скачкообразных рабочих нагрузок. Постоянный трафик редко приводит к холодному запуску. Что касается длительности, вы можете убедиться сами, она варьируется от ~18 мс до ~500 мс в зависимости от используемого времени выполнения.

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

Вы никогда раньше не использовали бессерверные технологии

У меня есть сюрприз. Вы, вероятно, использовали бессерверный сервис и не осознавали этого. Вы когда-нибудь использовали Amazon EC2? Ваши AMI хранятся в S3, который является бессерверным сервисом. Вы отправляли с помощью API Twilio? Они бессерверные.

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

Рекомендации по дизайну

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

Эластичность имеет значение

Интересным моментом при создании приложения с бессерверными службами является то, что иногда службы масштабируются слишком хорошо. Если вы создаете бессерверный API, который отправляет сообщения в веб-перехватчик, поддерживаемый EC2, вам лучше убедиться, что они масштабируются с одинаковой скоростью или имеют способ ограничения входящих вызовов!

В приведенном выше примере у нас было существующее приложение, живущее в EC2. Наше усовершенствование добавило бессерверный API, который действует как точка входа. Он выполняет проверки и дополнения перед публикацией веб-перехватчика для запуска существующего процесса в EC2.

Новый бессерверный API и вспомогательные сервисы будут масштабироваться до 10 000 запросов в секунду (ограничение пропускной способности сервиса API Gateway). Функция Lambda использует SNS для публикации в веб-перехватчик, предоставляемый экземпляром EC2. Размер экземпляра EC2 может обрабатывать только до 500 запросов в секунду.

Если вы получите большой всплеск трафика, бессерверный API будет масштабироваться, чтобы удовлетворить спрос. Он может успешно обрабатывать 10 000 запросов каждую секунду и отправлять сообщения в EC2 на несколько порядков быстрее, чем может обработать. Это перегружает экземпляр, и вы в конечном итоге отбрасываете события и, в конечном итоге, имеете значительную потерю данных.

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

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

Начните с оркестровки

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

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

В консоли AWS при каждом выполнении рабочего процесса Step Function будет отображаться путь, по которому прошли данные, чтобы вы могли быстро увидеть, что произошло в конкретном случае. Это упрощает отладку и знакомит ваших инженеров с концепцией модульных многоэтапных процессов. Вот схема выполнения из моего рабочего процесса кросс-постинга в блоге.

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

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

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

Дизайн для повторной попытки

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

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

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

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

Краткое содержание

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

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

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

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

Удачного кодирования!