“Serverless” — это популярный в наши дни технический термин, который означает не совсем то, что мы думаем, когда его слышим. Это потому, что сервер все таки есть — на нем размещены эти самые бессерверные приложения и функции. Но дело в том, что у нас действительно создается впечатление, что никакого сервера нет, потому что нам не нужно работать с ним, заниматься его управлением или беспокоиться о таких вещах, как масштабирование, потому что все это делается за нас. Serverless functions — это не просто веб-сервисы, которые размещаются в облаке. Эти функции имеют событийно-ориентированную архитектуру и предоставляют прекрасный способ оркестровки различных служб с помощью настраиваемых триггеров и привязок, что сокращает объем кода, который нам нужно писать самим. Мы можем просто сосредоточиться на логике, которую мы хотим реализовать, не растрачивая усилия на возню с оркестровками.
HTTP-запросы, как и для веб-сервисов, — это всего лишь один из всех возможных типов событий, которые могут инициировать выполнение ваших функции. Вы также можете подвязать функции на другие триггеры, такие как прослушивание изменений в базе данных Azure Cosmo DB или очереди сообщений. Также, если вы хотите выполнить какие-нибудь дополнительные задачи, вы можете указать их с помощью настраиваемых привязок, которые тоже не требуют от вас написания дополнительного кода. Например, вы можете использовать входную привязку (input binding) для извлечения из базы данных некоторых данных, которые необходимы вашей функции. Выходные привязки (output binding), которые опять же определяются с помощью конфигураций, а не кода, позволяют отправлять результаты в другой сервис. От вашей функции требуется только создать в коде результаты — привязка гарантирует, что эти результаты будут переданы по назначению. Например, функция может запускаться по факту записи в базу данных Cosmos DB, использовать входную привязку для сбора соответствующих данных из этой базы данных, а затем с помощью выходной привязки к очереди сообщений обновлять кэш. Если вам не нужна никакая дополнительная логика, функцию можно целиком и полностью определить триггером и привязками.
Все эти привязки и триггеры избавляют нас от многих трудоемких задач, которые в противном случае легли бы на наши плечи, и позволяют сосредоточиться на логике функции. А сервис Azure Functions берет на себя все заботы, связанные с хостингом сервера. Интеграция с Application Insights позволяет мониторить ваши функции, чтобы отслеживать, как они работают и используются.
Структура Azure-функций
Структура Azure-функций определяется приложением-функцией (Function App), в котором эти функции размещаются (одна или несколько связанных функций). Приложение имеет собственные настройки, которые по умолчанию выставлены на обеспечение максимальной безопасности. Поэтому это подходящее место для хранения таких сведений, как строки подключения, учетные данные и многое другое. Каждая функция в приложении представляет собой отдельный самодостаточный набор триггеров и привязок со своими собственными настройками. Единственное, что объединяет функции, — это URL поддомена и настройки приложения. На рисунке 1 вы можете видеть несколько приложений-функций из моей подписки. Я раскрыла список приложения DataAPINode, чтобы вы также могли видеть три функции, которые я создала в рамках этого приложения.
Подготовка среды
Хоть функции можно создавать непосредственно на портале, Visual Studio и Visual Studio Code имеют расширения, упрощающие разработку, отладку и развертывание Azure-функций. В этом руководстве я буду использовать VS Code и его расширение Azure Functions.
У меня есть хорошая идея для новой функции. Мне часто нужно знать, сколько слов я написал для таких вещей, как описание тезисов конференции и т. д. Чтобы подсчитать это количество, я копирую текст в Microsoft Word. Мы можем создать свою собственную функцию, которая будет возвращать количество символов и слов в заданном фрагменте текста.
Я буду использовать Visual Studio Code, его расширение Azure Functions и еще пару других связанных расширений. Если вы еще ни разу не использовали Visual Studio Code, я рекомендую вам установить его (бесплатно для MacOS, Linux или Windows), чтобы опробовать его по ходу работы. VS Code является кроссплатформенным редактором кода, и его очень легко установить (перейдите на code.visualstudio.com для его установки и получения дополнительной информации). Вы можете использовать Visual Studio 2017 или 2019, в котором аналогичное расширение встроено в ворклоад Azure. Однако рабочий процесс с расширением VS будет отличаться. Перед тем как разбираться с функциям, созданными в этой статье, я рекомендую вам почитать документацию соответствующего расширения.
В VS Code же мы начнем с установки расширения "Azure Functions", кликнув по иконке "Extensions" на панели действий (Activity Bar) VS Code (в левой части IDE). Чтобы расширение Azure Functions работало, нам необходимо установить Azure Functions Core Tools. Ссылки на установщики для конкретных ОС вы можете найти в разделе “Prerequisites” сведений о расширении (marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions). Сразу предупрежу, что даже для Windows это будет установка npm, но это достаточно быстро и безболезненно.
Для использования этого расширения вам не потребуется учетная запись, если только позже вы не планируете реализовать тестирование развертывания. Обратите внимание: если у вас есть подписка Visual Studio, то у вас есть учетная запись Azure. Если у вас нет ни того, ни другого, вы можете бесплатно создать учетную запись по ссылке https://azure.microsoft.com/en-us/free/.
Создание нашей первой функции
Я начну с корневой папки Code Functions на случай, если позже я захочу добавить еще функции. Затем я создам подпапку под названием WordCount. Откройте в VS Code папку WordCount.
Далее с помощью расширение Azure Functions мы преобразуем папку WordCount в проект Azure Functions.
Кликните по иконке “Azure” на панели действий, чтобы отобразить обозреватель Azure. Вы увидите окно Azure Functions. Если вы залогинились в учетную запись Azure, обозреватель Azure Functions также покажет вам приложения-функции в вашей учетной записи (рисунок 2). В моей подписке много приложений с функциями демонстрационного характера. Чтобы сэкономить ресурсы, выделенные на мою учетную запись, я остановила все, которыми я не пользуюсь активно.
Наведите указатель мыши на панель инструментов “Functions” (как я сделал на рисунке 2) и вы увидите, что появилось несколько иконок расширения. Иконка папки в правом верхнем углу предназначен для создания проекта Azure Functions в папке. Иконка молнии, чтобы создать функцию внутри проекта. Стрелка вверх (“upload”) предназначена для развертывания вашей функции в облаке, а последняя — стандартная иконка обновления.
Кликните по иконке папки, чтобы создать проект Azure Functions. Вы увидите ряд диалоговых окон, которые помогут вам создать и настроить проект.
Выберите папку для проекта: при необходимости перейдите в папку WordCount.
Выберите язык для вашего проекта из раскрывающегося списка: я выбрала C#, но есть и другие варианты — это JavaScript, TypeScript, Java и превью для Python и PowerShell.
Выберите среду выполнения: вы увидите это диалоговое окно только в том случае, если core tools нет в PATH вашей системы. Выберите Azure Functions v2, чтобы создать функцию на основе .NET Standard.
Теперь нужно выбрать шаблон: выберите HttpTrigger.
Укажите имя функции: я назвала свою функцию WordCount.
Укажите пространство имен: я указала CodeMagFunctions.WordCount.
Выберите права доступа: чтобы немного упростить пример в этом руководстве я буду использовать “Anonymous”.
Вот и все. Затем расширение создаст ресурсы, необходимые для этого проекта.
В редакторе вы увидите новый основополагающий для функции файл HttpTrigger, а ресурсы для шаблона — в обозревателе решений (смотрите рисунок 3). Полный код приведен в листинге 1. Обратите внимание на четыре файла в папке .vscode внутри корневой папки (CodeFunctions). Файлы extensions.json представляют собой файлы рекомендаций VS Code code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions, которые гарантируют, что любой, кто также будет работать с этим кодом, будет предупрежден о необходимости установки нужных расширений. В папке WordCount помимо файлов csproj и cs есть еще несколько файлов. Самый важный из этих новых файлов — local.settings.json. В нем мы храним локальную версию параметров приложения-функции, таких как строки подключения и учетные данные, если вы их используете. В этом руководстве мы опустим эти детали. Если у вас есть приложение-функция в Azure, состоящее из одной или нескольких функций, то существует набор параметров уровня приложения, общий для всех его функций, который вы должны устанавливать явно. Вот вокруг чего сосредоточены эти настройки.
Запуск дефолтной функции
Прежде чем модифицировать функцию для подсчета слов, давайте посмотрим на логику шаблона в действии. Полный листинг файла, за исключением операторов using, приведен в листинге 1. Эта функция принимает входящую строку, предполагая, что это чье-то имя, и отвечает “Hello,” вместе с этим именем. Функция является гибкой - она проверяя имя как в параметрах HttpRequest, так и в теле запроса (если оно существует и имеет свойство с именем “name”).
Листинг 1: Код дефолтной функции, созданной по шаблону HttpTrigger
public static class WordCount
{
[FunctionName("WordCount")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous,"get",
"post", Route=null)] HttpRequest req,ILogger log)
{
log.LogInformation("C# HTTP trigger function 9 processed a request.");
string name = req.Query["name"];
string requestBody =
await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(
requestBody);
name = name ?? data?.name;
return name != null
?(ActionResult)new OkObjectResult($"Hello,{name}")
: new BadRequestObjectResult(20 "Please pass a name on the query
string or in the request body");
}
}
Запуск этой функции не равносилен простому запуску приложения .NET Core, поскольку должна быть выполнена некоторая логика Azure Functions. Шаблон, который создал проект функции, также создал конфигурацию запуска VS Code под названием “Attach to .NET Functions” в launch.json. Если вы кликнете по иконке отладки (дебага) на панели действий, вы увидите, что конфигурация отладки настроена с учетом этого. Чтобы начать отладку функции, вам достаточно кликнуть по зеленой стрелке рядом с этим раскрывающимся списком или нажать F5.
Когда вы запустите функцию, Azure Functions SDK начнет с вызова dotnet build для проекта. Затем он запустит из собственного интерфейса командной строки команду func host start. После этого вы увидите баннер Azure Functions (рисунок 4), что является признаком того, что все работает.
После нескольких статусных сообщений вы увидите текст желтым цветом:
Http Functions: WordCount: [GET,POST] http://localhost:7071/api/WordCount
SDK будет продолжать выполнять задачи и сообщать о них в терминале. Подождите, пока он завершится и отобразится последнее сообщение “Host lock lease acquired by instance ID ...”. Теперь все готово. Мы можем сделать CTRL-клик (или CMD-клик) по URL, после чего откроется наш браузер, где мы увидим сообщение “Please pass a name on the query string or in the request body”. Это потому, что нам все еще нужно предоставить либо необходимый параметр запроса, либо его тело. Изменим URL, чтобы добавить параметр с именем, например, http://localhost:7071/api/WordCount?name=Julie. Затем браузер отобразит ответ, отправленный функцией, в нашем случае это “Hello, Julie”, как вы можете видеть на рисунке 5.
Когда вы закончите тестирование этой функции, вернитесь к терминалу VS Code и нажмите CTRL-C, чтобы остановить функцию.
На этом первая часть статьи подошла к концу. Продолжение будет опубликовано в ближайшие дни, а сейчас приглашаю всех желающих на бесплатный урок по теме "Работа с исключениями в C#". Зарегистрироваться на урок можно по ссылке ниже.
build_your_web
Нельзя в обучающих примерах показывать плохие практики.
Например, называть функцию, которая возвращает имя, названием WordCount. Ученики впитывают такие примеры и потом подобный код можно увидеть в реальных проектах.