HardТеория2 min

Azure Functions

Триггеры, привязки, Durable Functions и паттерны для AZ-204

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();

Проверь себя

Какой CRON-выражение означает 'каждый день в 8:00 UTC'?

Какой паттерн Durable Functions используется для параллельного выполнения задач с ожиданием завершения всех?

Что произойдет с сообщением Service Bus, если функция выбросит исключение?

Какой план Azure Functions устраняет проблему cold start?

Сколько триггеров может иметь одна Azure Function?