Тема сегодняшнего выпуска — то, о чём слышали почти всё, но почти никто не может объяснить. Серверлесос или бессерверные вычисления? Что же это такое на самом деле? Это действительно код, работающий в никуда или нечто гораздо более масштабное? Давайте сразу проясним один момент. Серверлесос не означает отсутствие серверов. Это значит, что вам не нужно о них думать, и это различие кардинально меняет подход к разработке. К концу этого выпуска вы поймёте, что такое Azure Functions, как устроена их тарификация и когда их стоит использовать. Мы разберём всё по кирпичикам, начав с самого главного мифа. Что же на самом деле означает серверлесос? Давайте сразу развеем несколько мифов. Название — бессерверный, худший маркетинговый термин, который когда-либо придумывала Microsoft. Он заставляет людей думать, что серверов вообще не существует. Это не так. Серверы есть, и их очень много. Просто вам никогда не приходится их касаться. 20 лет назад, чтобы запустить код в интернете, нужно было проделать огромную работу. Вы арендовали виртуальную машину, устанавливали ОС, настраивали веб-сервер и разворачивали приложение. А потом проводили каждые выходные, устанавливая патчи безопасности и следя, чтобы всё не упало в 3 часа ночи. И вот в чём штука. Вы платили за сервер, даже если ваш код не работал. Он гудел себе в стойке, сжигая ваши деньги, пока вы спали. Сервер Лесос переворачивает эту модель с ног на голову. Вы пишете код, загружаете его, а платформа берёт на себя всё остальное. Операционную систему, обновление безопасности, масштабирование и доступность. Ваша задача — писать только ту логику, которая важна. Представьте это как разницу между работой ресторанной кухни и торговым автоматом. Ресторанной кухне нужен штат сотрудников, постоянные поставки продуктов и обслуживания. Она требует денег каждый день, даже если туда не зашёл ни один клиент. Торговый автомат стоит в углу и ничего не делает, пока кто-то не нажмёт на кнопку. Затем он оживает, выполняет свою работу и снова засыпает. Вы платите за электричество только тогда, когда он действительно работает. Это и есть суть сервер Лесос в двух словах. Azure Functions — это версия такого подхода от Microsoft. Она запускает небольшие фрагменты кода в ответ на события. Ваш код спит, пока что-то его не разбудит. Затем он отрабатывает, завершается и снова засыпает. Так как же выглядит этот код? Что такое Azure Functions? Функция — это отдельный фрагмент кода, выполняющий одну конкретную задачу. Вот и всё. Это не целое приложение со страницей входа, базой данных и 20-ю экранами. Это одна узкоспециализированная задача. Представьте это как выключатель света в доме, либо выключен, либо включён для выполнения задачи, а затем снова выключен. Традиционный веб-сервер — это полная противоположность. Всё равно, что оставлять свет включённым 24 часа в сутки, 7 дней в неделю, даже когда дома никого нет. Azure Functions поддерживают множество различных языков программирования. Вы можете использовать то, что вам удобно, JavaScript, Python, C-решётка, Java, PowerShell. Здесь нет единственно верного ответа. Выбирайте язык, который вы уже знаете. А теперь давайте устраним распространённую путаницу. Приложение-функция, Function App — это не то же самое, что сама функция. Приложение-функция — это контейнер. Представьте его как ящик для инструментов. Вы создаёте одно приложение-функцию, а внутри этого ящика размещаете множество функций. Каждая функция — это отдельный инструмент, который выполняет свою работу. У вас может быть одна функция для регистрации пользователей, другая — для обработки загруженных изображений и третья — для рассылки ночных отчётов. Все они живут в одном ящике, но работают независимо друг от друга. И ещё кое-что о функциях. Они намеренно сделаны без сохранения состояния. Это всё. При следующем запуске она начинает с чистого листа, не помня о предыдущем разе. Звучит как ограничение, но именно эта особенность делает их такими мощными. Поскольку функции не хранят память или состояние, Azure может мгновенно запустить 100 копий вашей функции при скачке трафика и также быстро отключить их, когда нагрузка падает. Именно так вы получаете масштабируемость, не платя за простаивающие серверы. Возникает вопрос. Если функция просто бездействует, пока её что-то не разбудит, то что же её будет? Вот здесь на помощь приходят триггеры. Триггеры — это условие, когда. У каждой функции должен быть ровно один триггер. Это обязательное требование. Триггер — это событие, которое пробуждает вашу функцию. Без него ваш код просто будет висеть в бездействии. Представьте триггеры как дверной звонок. Ваша функция находится внутри дома и ждёт. Она может ждать вечно. Ничего не произойдёт, пока кто-то не нажмёт на звонок. Тогда функция включается в работу, открывает дверь, делает своё дело и возвращается в режим ожидания. Есть четыре триггера, с которыми новички сталкиваются чаще всего. HTTP-триггер — самая распространённая отправная точка. Кто-то переходит по ссылке или делает вызов API, и ваша функция запускается. Так можно создавать легковесные API, не настраивая полноценный веб-сервер. И есть ещё триггер по таймеру, который запускается по расписанию. Вы задаёте крон-выражение, например, запуск каждый час или в полночь каждую ночь, и ваша функция срабатывает в это точное время. Идеально подходит для задачи обслуживания, очистки или создания ночных отчётов. Триггер биелоби-объектов срабатывает при загрузке файла в хранилище Azure. Допустим, кто-то загружает PDF-файл в определённую папку. Триггер биелоби-объектов обнаруживает эту загрузку и автоматически запускает вашу функцию. Это очень полезно для обработки изображений, преобразования документов и проверки файлов. А триггер очереди срабатывает, когда в очереди появляется сообщение. Очереди — это способ разделения различных частей вашей системы. Один сервис помещает сообщение в очередь, а ваша функция забирает и обрабатывает его, когда будет готово. Это предотвращает ситуацию, когда один медленный сервис блокирует всё остальное. Вот ключевой момент. Когда триггер срабатывает, он автоматически передаёт данные в вашу функцию. Вам не нужно опрашивать систему или проверять, произошло ли что-то. Триггер предоставляет вам всё необходимое, а ваша функция просто это обрабатывает. Функция без триггера – это просто код, который ничего не делает. Именно триггер придает ей смысл. Итак, триггер говорит вашей функции, когда нужно запускаться. Но откуда берутся данные и куда они уходят? Вот здесь на помощь приходят привязки Bendinges. Привязки – это ввод данных и вывод данных. Привязки позволяют указать функции, какие данные считывать и куда отправлять результаты, без написания лишнего кода. Звучит сложно, поэтому позвольте упростить. Существует два типа. Входные привязки доставляют данные в вашу функцию. Выходные привязки отправляют данные наружу. Без привязок вам пришлось бы писать код SDK каждый раз, когда нужно обратиться к хранилищу, базе данных или очереди. Вам пришлось бы обрабатывать строки подключения, управлять повторными попытками, сериализовать данные и десериализовать ответы. Это слишком много шаблонного кода только для чтения файла. С привязками вы просто объявляете, что вам нужно. Вы говорите, я хочу читать данные из этого биологи контейнера. Или, я хочу записать данные в эту очередь. Среда выполнения берет остальное на себя. Она открывает соединение, считывает данные и передает их в вашу функцию в качестве параметра. Когда функция завершается, она берет возвращаемое значение и записывает его туда, где вы указали. Представьте привязки как трубы. Вы подключаете свою функцию к хранилищу, базе данных или очереди. Данные автоматически текут через эти трубы. Вашей функции не нужно знать, как работают эти трубы. Она просто получает то, что проходит через них, и отправляет то, что должно выйти. Вот конкретный пример. Допустим, у вас есть входная привязка для биологи объекта. Когда ваша функция запускается, она автоматически считывает файл из хранилища биологи объектов и передает его вам в качестве параметра. Вам не нужно писать код SDK для хранилища. Вы просто получаете данные и обрабатываете их. Другой пример – выходная привязка к очереди. Ваша функция что-то обрабатывает, а в конце вы возвращаете значение. Среда выполнения берет это значение, сериализует его и помещает в очередь. Вам не нужно писать код для очереди. Вы просто возвращаете значение. Привязки не обязательны. Их может быть ноль, одна или много. Некоторым функциям нужен только триггер, вообще без привязок. Другие могут иметь три или четыре привязки к разным службам. Сочетание триггеров и привязок делает Azure Functions такими мощными. Вы пишете бизнес-логику – основной код принятия решений. Платформа берет на себя всю интеграцию. Ваша функция остается небольшой, целенаправленной и понятной. Вопрос ценообразования. Цены – это то, что больше всего удивляет новичков. Для большинства людей план потребления – consumption – выбор по умолчанию. И в 90% случаев стоит начинать именно с него. Вот как это работает. Вы платите только тогда, когда ваша функция действительно выполняется. Когда она простаивает, вы ничего не платите. Ноль, ни копейки. Счет состоит из двух компонентов. Во-первых, количество выполнений, то есть сколько раз срабатывает ваша функция. Во-вторых, время выполнения, измеряемое в так называемых GB секундах. Это, по сути, время работы функции, умноженное на объем использованной памяти. Бесплатная квота очень щедрая. Вы получаете 1 миллион выполнений в месяц и 400 тысяч гигабайтов в секунду совершенно бесплатно. Для большинства небольших проектов, любительских приложений и прототипов вы никогда не заплатите ни цента. Вообще, если вы выйдете за рамки бесплатной квоты, тарифы все равно останутся невероятно низкими. 20 центов за миллион выполнений. Это не опечатка. 20 центов за миллион запусков. Представьте это как оплату за электричество только тогда, когда вы включаете выключатель. Нет никакой ежемесячной абонентской платы за проводку в ваших стенах. Вы платите только за ту энергию, которую реально потребили. Конечно, есть и другие планы. Flex Consumption – более новый план, предоставляющий поддержку виртуальных сетей. Премиум держит ваши функции всегда разогретыми, чтобы не было задержек при холодном старте. Dedicated предоставляет фиксированную емкость в рамках традиционного плана App Service. Но для начала работы Consumption почти всегда является правильным выбором. Однако есть одно предостаряжение. Бесплатная квота распределяется между всеми вашими приложениями-функциями в рамках одной подписки. Если у вас 10 приложений-функций, все они используют тот же 1 миллион бесплатных выполнений. Так что следите за этим, если начнете создавать больше нескольких приложений. Ценообразование отличное. Но давайте разберем это на реальном примере. Сценарии из жизни. Представьте, что вы управляете сайтом, где пользователи загружают фотографии профиля. Эти изображения огромные, например, по 10 мегабайтам каждая. И это создает несколько серьезных проблем. Большие файлы дороже хранить. Они замедляют сайт при каждой загрузке страницы и раздражают пользователей, вынужденных ждать фото. Поэтому вам нужно автоматически уменьшать эти изображения. Без Azure Functions вам пришлось бы создавать фоновый процесс с нуля. Это значит арендовать отдельный сервер, настраивать очередь для управления нагрузкой и писать код для координации всех элементов. Это куча ненужной сложности для такой простой задачи, как сжатие изображения. С Azure Functions вам нужны только один блок, триггер и одна функция. И никаких серверов, о которых нужно беспокоиться. Позвольте мне показать, как это работает. Пользователь загружает фото на ваш сайт, и файл попадает в Azure Blob Storage. Как только он появляется, автоматически срабатывает Blob Trigger. Ваша функция просыпается, выполняет код сжатия и сохраняет уменьшенную версию обратно в хранилище. Все это происходит за считанные секунды. Пользователь даже не ждет, ведь весь процесс идет в фоновом режиме, совершенно незаметно. Вот еще один повседневный пример – отправка приветственного письма при регистрации в вашем сервисе. HTTP Trigger перехватывает запрос на регистрацию с вашего сайта. Ваша функция запускается, получает email пользователя, отправляет приветствие через SendGrid. И на этом все. Пользователь получает письмо почти мгновенно. Не нужно настраивать почтовый сервер или очередь отправки, всего одна функция, одна задача и готово. Именно для таких задач и были созданы Azure Functions. Небольшие, узкоспециализированные, событийно-ориентированные задачи. Немасштабные приложения и сложные рабочие процессы, а одно хорошо выполненное дело, запущенное событием извне. Когда использовать Azure Functions? Итак, когда стоит использовать функции, а когда что-то другое? Вот быстрый способ принять решение. Спросите себя, является ли задача короткой, событийно-ориентированной и не имеющей состояния. Если вы ответили «да» на все три вопроса, то Azure Functions – подходящий инструмент. Начнем с хороших вариантов использования. API и WebHooki подходят идеально. Вам нужен легкий in-point, который отвечает на HTTP запрос, выполняет одно действие и возвращает результат. Это как раз-то для чего созданы HTTP-треггеры. Обработка файлов и изображений – еще один отличный пример. Файл попадает в хранилище, ваша функция срабатывает, преобразует его и сохраняет результат без всякого сервера. Плановые задачи, такие как ночная очистка или создание отчетов, отлично работают с триггерами по таймеру. Преобразование данных для ETL-конвейеров также является распространенной задачей. Функции идеально подходят в качестве «клея» для интеграции, связывая сервисы, которые не взаимодействуют напрямую. Теперь поговорим о том, когда функции не подходят. Длительные процессы – это проблема, так как в плане потребления у функций по умолчанию есть ограничение по времени в 5 минут, которое можно увеличить до 10 при настройке. Если ваша задача выполняется дольше, вам нужно другое решение. Приложение с сохранением состояния – еще один неподходящий вариант. Функция «Ничего не помнят» между запусками. Если вам нужно поддерживать состояние сеанса или отслеживать прогресс между этапами, это противоречит их архитектуре. Тяжелые вычислительные нагрузки также не подходят. Если вам требуется постоянная нагрузка на процессор в течение минут или часов, лучше выбрать виртуальную машину или контейнер. А сложные рабочие процессы, где одна задача зависит от другой, лучше обрабатывать с помощью Durable Functions или Logic Apps. Вот краткий обзор альтернатив. Azure Logic Apps – это вариант без написания кода для связывания сервисов. Если вам не нужно писать собственный код, Logic Apps справится с задачей с помощью визуального конструктора. Azure App Service предназначен для полноценных веб-приложений, работающих круглосуточно. Если вам нужен полноценный веб-сайт или API, которые всегда доступны, это ваш инструмент. Azure Container Apps предоставляет контейнеризированные микросервисы с расширенным контролем над средой выполнения. А Azure Virtual Machines дает вам полный контроль над операционной системой, если это необходимо. Вот простое правило. Если вы можете описать задачу одним предложением, она, скорее всего, отлично подходит для функции. Сжимать изображение при их загрузке. Отправлять приветвенное письмо при регистрации пользователя. Запускать задачу очистки каждую полночь. Одно предложение, одна задача, одна функция. Распространенные ошибки новичков, которых следует избегать. Теперь поговорим о том, на что стоит обратить внимание. Это ошибки, на которых спотыкаются почти все начинающие. Типичная ошибка новичка – думать, что функции всегда бесплатны. Бесплатный лимит щедр и миллион выполнений кажется огромным числом, но если ваша функция станет виральной или ее атакует бот, выполнение закончится быстро. Поэтому следите за использованием, настройте бюджетные оповещения в Azure и не получите неожиданный счет в конце месяца. Еще одна ошибка – игнорирование холодных запусков. Первый запуск функции после простоя занимает больше времени. В плане потребления это может занять несколько секунд. Для большинства случаев это приемлемо. Но если вы создаете API, чувствительный к задержкам, где важна каждая милля секунда, рассмотрите тарифный план премиум или включите всегда готовые экземпляры. И, наконец, создание функций, которые работают слишком долго. У плана потребления есть время ожидания – 5 минут по умолчанию, максимум 10 минут. Если вашей функции нужно 15 минут на обработку файла, она будет прервана на полпути. Разбейте задачу на части поменьше или используйте другой план размещения. Еще одна частая ошибка – не использовать развертывание Run from Package. Это простое изменение конфигурации улучшает холодный старт и повышает надежность развертывания. Вместо копирования отдельных файлов вы развертываете цип архив. Это одна галочка на портале. Просто поставьте ее. Открытие HTTP-инпоинтов без аутентификации – еще одна ловушка. Легко оставить функцию в анонимном режиме во время тестирования и забыть ограничить к ней доступ. Устанавливайте правильный уровень авторизации сразу. Используйте ключи функции или администратора. Не оставляйте дверь открытой. Использование одной учетной записи хранения для нескольких функций также является проблемой. При разработке это допустимо. В продакшене у каждой функции должна быть своя учетная запись хранения. Иначе возникнет проблема шумного соседа, когда трафик одной функции замедляет другую. И, наконец, отсутствие Application Insights. Без него вы работаете вслепую. Вы не увидите сбоев, ошибок или проблем с производительностью. Вы не узнаете, работает ли функция слишком долго или тихо завершается с ошибкой. Включите его с самого первого дня. Это займет 30 секунд и сэкономит часы отладки. Золотое правило – функции должны быть маленькими, узкоспециализированными и без сохранения состояния. Одна задача на одну функцию, не более. Итак, это и есть вся система. Azure Functions – это бессерверные вычисления, запускающие фрагменты кода в ответ на события. Вы платите только тогда, когда ваш код выполняется. Триггеры активируют функцию, привязки соединяют ее с нужными данными, а план потребления делает ее почти бесплатной для небольших проектов. Лучшее, что можно сделать прямо сейчас – создать простую функцию с HTTP-триггером на портале Azure. Это займет 5 минут и ничего не стоит. Подписывайтесь на Microsoft Knowledge на Getas для простых разборов и делитесь видео с теми, кто спрашивает, что такое сервер Лесос. Фрау