Azure Functions -- бессерверная платформа для запуска кода по событиям. На экзамене AZ-204 необходимо знать триггеры, привязки (bindings), Durable Functions и их паттерны.
Триггеры и привязки
Триггер определяет, что вызывает функцию. У каждой функции ровно один триггер.
Привязка (Binding) -- декларативное подключение к ресурсу. Input binding -- для чтения данных, Output binding -- для записи. У функции может быть несколько привязок.
Таблица триггеров
| Триггер | Описание | Типичный сценарий |
|---|---|---|
| HTTP | Вызов по HTTP-запросу | REST API endpoints |
| Timer | Выполнение по расписанию (CRON) | Отчеты, batch-задачи |
| Blob | Реакция на изменение файла в Blob Storage | Обработка загрузок |
| Queue | Сообщение в Queue Storage | Фоновая обработка |
| Service Bus | Сообщение в очереди или топике | Интеграция сервисов |
| Cosmos DB | Изменение документа (Change Feed) | Event-driven обработка |
| Event Grid | Событие Azure | Реакция на события инфраструктуры |
Пример: HTTP-триггер
public class OrderFunction
{
private readonly IOrderService _orderService;
public OrderFunction(IOrderService orderService)
{
_orderService = orderService;
}
[Function("ProcessOrder")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
{
var command = await req.ReadFromJsonAsync<CreateOrderCommand>();
var result = await _orderService.CreateOrderAsync(command);
return new OkObjectResult(result);
}
}
Уровни авторизации HTTP-триггера:
Anonymous-- без ключаFunction-- требуется ключ функцииAdmin-- требуется master-ключ
Пример: Timer-триггер
[Function("DailyOrderReport")]
public async Task RunReport(
[TimerTrigger("0 0 8 * * *")] TimerInfo timer)
{
// Выполняется каждый день в 8:00 UTC
// CRON формат: {секунды} {минуты} {часы} {день} {месяц} {день недели}
_logger.LogInformation("Generating daily report at {Time}", DateTime.UtcNow);
}
Пример: Service Bus-триггер
[Function("OrderConfirmedHandler")]
public async Task Run(
[ServiceBusTrigger("order-confirmed", Connection = "ServiceBus")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
var order = message.Body.ToObjectFromJson<OrderConfirmedMessage>();
try
{
await _emailService.SendConfirmationAsync(order.CustomerEmail, order.OrderId);
await messageActions.CompleteMessageAsync(message);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process {MessageId}", message.MessageId);
throw; // Message returns to queue for retry
}
}
Пример: Blob-триггер
[Function("ProcessUploadedFile")]
public async Task RunBlobTrigger(
[BlobTrigger("uploads/{name}", Connection = "Storage")]
Stream stream,
string name)
{
_logger.LogInformation("Processing uploaded file: {Name}", name);
if (name.EndsWith(".csv"))
{
using var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync();
// Parse and process CSV...
}
}
Hosting Plans
| План | Масштабирование | Cold Start | Оплата |
|---|---|---|---|
| Consumption | Авто (до 200 экз.) | Да (до нескольких секунд) | За выполнение |
| Premium | Прогретые экземпляры | Нет | За vCPU + память |
| Dedicated | На базе App Service Plan | Нет | За план |
Consumption -- по умолчанию. 1 миллион выполнений и 400 000 GB-s бесплатно в месяц. Недостаток: cold start при первом вызове после простоя.
Premium -- для production-критичных функций. Всегда прогретые экземпляры, VNet-интеграция, неограниченное время выполнения.
Durable Functions
Durable Functions -- расширение для создания stateful workflow в бессерверной среде. Оркестратор управляет последовательностью вызовов activity-функций.
Паттерн 1: Function Chaining
Последовательное выполнение шагов, где результат одного шага передается в следующий.
[Function("OrderOrchestrator")]
public static async Task<OrderResult> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var order = context.GetInput<Order>();
// Step 1: Validate
var isValid = await context.CallActivityAsync<bool>("ValidateOrder", order);
// Step 2: Reserve inventory
await context.CallActivityAsync("ReserveInventory", order);
// Step 3: Process payment (with retry)
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(3, TimeSpan.FromSeconds(5))));
var payment = await context.CallActivityAsync<PaymentResult>(
"ProcessPayment", order, retryOptions);
// Step 4: Send notification
await context.CallActivityAsync("SendNotification", order);
return new OrderResult { Success = true, PaymentId = payment.Id };
}
Паттерн 2: Fan-out / Fan-in
Параллельное выполнение нескольких задач с ожиданием завершения всех.
// Send notifications to multiple channels in parallel
var emailTask = context.CallActivityAsync("SendEmail", orderId);
var smsTask = context.CallActivityAsync("SendSms", orderId);
var pushTask = context.CallActivityAsync("SendPush", orderId);
await Task.WhenAll(emailTask, smsTask, pushTask);
Паттерн 3: Async HTTP API
Запуск долгой операции с возвратом URL для проверки статуса (polling).
Паттерн 4: Monitor
Периодическая проверка условия до его выполнения (polling с интервалом).
Паттерн 5: Human Interaction
Ожидание внешнего события (подтверждение пользователя, одобрение менеджера).
Program.cs для Azure Functions
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices((context, services) =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
// Register application services
services.AddApplication();
services.AddInfrastructure(context.Configuration);
})
.Build();
host.Run();