Руководство по запуску Функции Azure C# в изолированной рабочей модели

В этой статье приведены общие сведения о работе с Функции Azure в .NET с помощью изолированной рабочей модели. Эта модель позволяет проекту использовать версии .NET независимо от других компонентов среды выполнения. Сведения о конкретных поддерживаемых версиях .NET см . в поддерживаемой версии.

Чтобы приступить к созданию функций изолированной рабочей модели .NET, воспользуйтесь приведенными ниже ссылками.

Начало работы Основные понятия Примеры

Сведения о развертывании изолированного проекта рабочей модели в Azure см. в статье "Развертывание в Функции Azure".

Преимущества изолированной рабочей модели

Существует два режима, в которых можно запускать функции библиотеки классов .NET: либо в том же процессе , что и среда выполнения узла Функций (внутри процесса) или изолированный рабочий процесс. Если функции .NET выполняются в изолированном рабочем процессе, вы можете воспользоваться следующими преимуществами:

  • Меньше конфликтов: поскольку функции выполняются в отдельном процессе, сборки, используемые в приложении, не конфликтуют с разными версиями одинаковых сборок, используемых узлом.
  • Полный контроль над процессом: вы управляете запуском приложения, что означает, что вы можете управлять конфигурациями, используемыми и запущенным ПО промежуточного слоя.
  • Стандартная внедрение зависимостей. Так как у вас есть полный контроль над процессом, можно использовать текущее поведение .NET для внедрения зависимостей и включения ПО промежуточного слоя в приложение-функцию.
  • Гибкость версии .NET. Выполнение вне процесса узла означает, что функции могут выполняться в версиях .NET, не поддерживаемых средой выполнения Функций, включая платформа .NET Framework.

Если у вас есть существующее приложение-функция C#, которое выполняется в процессе, необходимо перенести приложение, чтобы воспользоваться преимуществами этих преимуществ. Дополнительные сведения см. в статье "Миграция приложений .NET из модели в процессе" в изолированную рабочую модель.

Полное сравнение двух режимов см. в разделе "Различия между внутрипроцессным процессом и изоляцией рабочего процесса .NET Функции Azure".

Поддерживаемые версии

Версии среды выполнения функций поддерживают определенные версии .NET. Дополнительные сведения о версиях службы "Функции Azure" см. в разделе Обзор версий среды выполнения службы "Функции Azure". Поддержка версий также зависит от того, выполняются ли функции в процессе или изолированном рабочем процессе.

Примечание.

Чтобы узнать, как изменить версию среды выполнения Функций, используемую приложением-функцией, обратитесь к разделу Просмотр и обновление текущей версии среды выполнения.

В следующей таблице показан самый высокий уровень .NET или платформа .NET Framework, который можно использовать с определенной версией Функций.

Версия среды выполнения службы "Функции Azure" Изолированная рабочая модель Модель в процессе5
Функции 4.x .NET 8.0
.NET 7.01
.NET 6.02
платформа .NET Framework 4.83
.NET 6.02
Функции 1.x4 Н/Д .NET Framework 4.8

1 .NET 7 достигает окончания официальной поддержки 14 мая 2024 года.
2 .NET 6 достигает окончания официальной поддержки 12 ноября 2024 года.
3 Процесс сборки также требует пакета SDK для .NET. 4 Поддержка заканчивается для версии 1.x среды выполнения Функции Azure 14 сентября 2026 года. Дополнительные сведения см . в этом объявлении о поддержке. Для дальнейшей полной поддержки следует перенести приложения в версию 4.x.
5 Поддержка заканчивается для модели в процессе 10 ноября 2026 года. Дополнительные сведения см . в этом объявлении о поддержке. Для непрерывной поддержки следует перенести приложения в изолированную рабочую модель.

Последние новости о выпусках службы "Функции Azure", включая удаление отдельных устаревших промежуточных версий, см. в статье Анонсы для службы приложений Azure.

Структура проекта

Проект .NET для Функции Azure с использованием изолированной рабочей модели — это в основном проект консольного приложения .NET, предназначенный для поддерживаемой среды выполнения .NET. Ниже приведены основные файлы, требуемые в любом изолированном проекте .NET.

  • Файл проекта C# (.csproj), определяющий проект и зависимости.
  • Файл Program.cs, который служит в качестве точки входа в приложение.
  • Все файлы кода, определяющие функции.
  • host.json файл, определяющий конфигурацию, доступную функциям в проекте.
  • local.settings.json файл, определяющий переменные среды, используемые проектом при локальном запуске на компьютере.

Полные примеры см. в примере проекта .NET 8 и примера проекта платформа .NET Framework 4.8.

Ссылки на пакеты

Проект .NET для Функции Azure с помощью изолированной рабочей модели использует уникальный набор пакетов для основных функций и расширений привязки.

Основные пакеты

Для выполнения функций .NET в изолированном рабочем процессе требуются следующие пакеты:

Пакеты расширений

Так как функции изолированного рабочего процесса .NET используют различные типы привязки, они требуют уникального набора пакетов расширений привязки.

Эти пакеты расширений находятся в разделе Microsoft.Azure.Functions.Worker.Extensions.

Запуск и настройка

При использовании изолированных функций .NET у вас есть доступ к запуску приложения-функции, который обычно находится в Program.cs. Вам предстоит самостоятельно создавать и запускать собственный экземпляр узла. Для этого у вас также есть прямой доступ к конвейеру конфигурации приложения. Благодаря изолированному рабочему процессу функций .NET можно гораздо проще добавлять конфигурации, внедрять зависимости и запускать собственное ПО промежуточного слоя.

В коде ниже приведен пример конвейера HostBuilder:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.AddApplicationInsightsTelemetryWorkerService();
        s.ConfigureFunctionsApplicationInsights();
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
        s.Configure<LoggerFilterOptions>(options =>
        {
            // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override.
            // Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
            LoggerFilterRule toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .Build();

Для этого кода требуется using Microsoft.Extensions.DependencyInjection;.

Перед вызовом HostBuilderнеобходимо выполнить следующие действияBuild().

  • Вызовите либо ConfigureFunctionsWebApplication() при использовании интеграции ASP.NET Core, либо в ConfigureFunctionsWorkerDefaults() противном случае. Дополнительные сведения об этих параметрах см . в триггере HTTP.
    Если вы пишете приложение с помощью F#, для некоторых расширений триггеров и привязок требуется дополнительная настройка. См. документацию по настройке расширения BLOB-объектов, расширения таблиц и расширения Cosmos DB при планировании использования этих расширений в приложении F#.
  • Настройте все службы или конфигурацию приложения, необходимые для проекта. Дополнительные сведения см. в разделе "Конфигурация ".
    Если вы планируете использовать приложение Аналитика, необходимо вызвать AddApplicationInsightsTelemetryWorkerService() и ConfigureFunctionsApplicationInsights() в делегатеConfigureServices(). Дополнительные сведения см. в Аналитика приложения.

Если проект предназначен для .NET Framework 4.8, необходимо также добавить FunctionsDebugger.Enable(); перед созданием HostBuilder. Это должна быть первая строка метода Main(). Дополнительные сведения см. в статье Отладка при выборе платформа .NET Framework.

HostBuilder используется для сборки и возврата полностью инициализированного IHost экземпляра, который выполняется асинхронно для запуска приложения-функции.

await host.RunAsync();

Настройка

Метод ConfigureFunctionsWorkerDefaults используется для добавления параметров, необходимых для запуска приложения-функции в изолированном рабочем процессе, который включает следующие функции:

  • Набор преобразователей по умолчанию.
  • Настройте параметр JsonSerializerOptions по умолчанию таким образом, чтобы он игнорировал регистр в собственных именах.
  • Интеграция с ведением журнала Функций Azure.
  • ПО промежуточного слоя и функции для выходной привязки.
  • ПО промежуточного слоя для выполнения функции.
  • Поддержка gRPC по умолчанию.
.ConfigureFunctionsWorkerDefaults()

Поскольку у вас есть доступ к конвейеру сборки узла, во время инициализации вы также можете настроить особые конфигурации для приложения. Вы можете один или несколько раз вызвать метод ConfigureAppConfiguration в HostBuilder, чтобы добавить конфигурации, необходимые вашему приложению-функции. Подробнее о конфигурации приложения см. в разделе Конфигурация в ASP.NET Core.

Эти конфигурации касаются только приложения-функции, выполняемого в отдельном процессе. Чтобы внести изменения в узел функций или конфигурацию триггера и привязки, необходимо использовать файл host.json.

Примечание.

Пользовательские источники конфигурации нельзя использовать для настройки триггеров и привязок. Конфигурация триггера и привязки должна быть доступна для платформы Функций, а не только для кода приложения. Эту конфигурацию можно предоставить с помощью параметров приложения, ссылок на Key Vault или Конфигурация приложений ссылок на функции.

Внедрение зависимостей

Внедрение зависимостей упрощается при сравнении с функциями в процессе .NET, что требует создания класса запуска для регистрации служб.

Для приложения изолированного процесса .NET используется стандартный способ вызова ConfigureServices в построителе узлов и использование методов расширения в IServiceCollection для внедрения определенных служб.

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

.ConfigureServices(services =>
{
    services.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
})

Для этого кода требуется using Microsoft.Extensions.DependencyInjection;. Подробнее см. в разделе Внедрение зависимости в ASP.NET Core.

Регистрация клиентов Azure

Внедрение зависимостей можно использовать для взаимодействия с другими службами Azure. Клиенты из пакета Azure SDK для .NET можно внедрить с помощью пакета Microsoft.Extensions.Azure. После установки пакета зарегистрируйте клиентов, вызвав AddAzureClients() коллекцию служб в Program.cs. В следующем примере настраивается именованный клиент для БОЛЬШИХ двоичных объектов Azure:

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices((hostContext, services) =>
    {
        services.AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(hostContext.Configuration.GetSection("MyStorageConnection"))
                .WithName("copierOutputBlob");
        });
    })
    .Build();

host.Run();

В следующем примере показано, как использовать эту регистрацию и типы SDK для копирования содержимого BLOB-объектов в виде потока из одного контейнера в другой с помощью внедренного клиента:

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Logging;

namespace MyFunctionApp
{
    public class BlobCopier
    {
        private readonly ILogger<BlobCopier> _logger;
        private readonly BlobContainerClient _copyContainerClient;

        public BlobCopier(ILogger<BlobCopier> logger, IAzureClientFactory<BlobServiceClient> blobClientFactory)
        {
            _logger = logger;
            _copyContainerClient = blobClientFactory.CreateClient("copierOutputBlob").GetBlobContainerClient("samples-workitems-copy");
            _copyContainerClient.CreateIfNotExists();
        }

        [Function("BlobCopier")]
        public async Task Run([BlobTrigger("samples-workitems/{name}", Connection = "MyStorageConnection")] Stream myBlob, string name)
        {
            await _copyContainerClient.UploadBlobAsync(name, myBlob);
            _logger.LogInformation($"Blob {name} copied!");
        }

    }
}

В ILogger<T> этом примере также был получен путем внедрения зависимостей, поэтому он регистрируется автоматически. Дополнительные сведения о параметрах конфигурации для ведения журнала см. в разделе "Ведение журнала".

Совет

В примере используется литеральная строка для имени клиента в обоих Program.cs и функциях. Вместо этого следует использовать общую строку констант, определенную в классе функции. Например, можно добавить public const string CopyStorageClientName = nameof(_copyContainerClient); и ссылаться BlobCopier.CopyStorageClientName в обоих расположениях. Можно также определить имя раздела конфигурации с функцией, а не в Program.cs.

ПО промежуточного слоя

При изоляции .NET также поддерживает регистрацию ПО промежуточного слоя, используя такую же модель, как в ASP.NET. Эта модель позволяет внедрить логику в конвейер вызова, а также до и после выполнения функций.

Как мы видим на примере ниже, метод расширения ConfigureFunctionsWorkerDefaults имеет перегрузку, позволяющую регистрировать собственное ПО промежуточного слоя.

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
        // Register our custom middlewares with the worker

        workerApplication.UseMiddleware<ExceptionHandlingMiddleware>();

        workerApplication.UseMiddleware<MyCustomMiddleware>();

        workerApplication.UseWhen<StampHttpHeaderMiddleware>((context) =>
        {
            // We want to use this middleware only for http trigger invocations.
            return context.FunctionDefinition.InputBindings.Values
                          .First(a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
        });
    })
    .Build();

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

Следующие методы расширения в FunctionContext упрощают работу с ПО промежуточного слоя в изолированной модели.

Метод Description
GetHttpRequestDataAsync Возвращает экземпляр HttpRequestData при вызове триггером HTTP. Этот метод возвращает экземпляр ValueTask<HttpRequestData?>, который полезен при чтении данных сообщения, таких как заголовки запросов и файлы cookie.
GetHttpResponseData Возвращает экземпляр HttpResponseData при вызове триггером HTTP.
GetInvocationResult Возвращает экземпляр InvocationResult, представляющий результат выполнения текущей функции. Используйте свойство Value, чтобы получить или задать значение по мере необходимости.
GetOutputBindings Возвращает записи выходной привязки для текущего выполнения функции. Каждая запись в результате этого метода относится к типу OutputBindingData. Вы можете использовать свойство Value, чтобы получить или задать значение по мере необходимости.
BindInputAsync Привязывает элемент входной привязки для запрошенного экземпляра BindingMetadata. Например, этот метод можно использовать при наличии функции с входной BlobInput привязкой, которая должна использоваться ПО промежуточного слоя.

Это пример реализации ПО промежуточного слоя, которая считывает HttpRequestData экземпляр и обновляет HttpResponseData экземпляр во время выполнения функции:

internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var requestData = await context.GetHttpRequestDataAsync();

        string correlationId;
        if (requestData!.Headers.TryGetValues("x-correlationId", out var values))
        {
            correlationId = values.First();
        }
        else
        {
            correlationId = Guid.NewGuid().ToString();
        }

        await next(context);

        context.GetHttpResponseData()?.Headers.Add("x-correlationId", correlationId);
    }
}

Это ПО промежуточного слоя проверяет наличие определенного заголовка запроса (x-correlationId) и, если он есть, использует его значение для пометки заголовка ответа. В противном случае оно создает новое значение GUID и использует его для пометки заголовка ответа. Более подробный пример пользовательского ПО промежуточного слоя в приложении-функции см. в эталонном образце.

Настройка сериализации JSON

Изолированная рабочая модель используется System.Text.Json по умолчанию. Вы можете настроить поведение сериализатора, настроив службы в составе Program.cs файла. В следующем примере показано использование ConfigureFunctionsWebApplication, но оно также будет работать для ConfigureFunctionsWorkerDefaults:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
        {
            jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;

            // override the default value
            jsonSerializerOptions.PropertyNameCaseInsensitive = false;
        });
    })
    .Build();

Вместо этого можно использовать JSON.NET (Newtonsoft.Json) для сериализации. Для этого необходимо установить Microsoft.Azure.Core.NewtonsoftJson пакет. Затем в регистрации службы вы переназначите Serializer свойство в WorkerOptions конфигурации. В следующем примере показано использование ConfigureFunctionsWebApplication, но оно также будет работать для ConfigureFunctionsWorkerDefaults:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<WorkerOptions>(workerOptions =>
        {
            var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
            settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            settings.NullValueHandling = NullValueHandling.Ignore;

            workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
        });
    })
    .Build();

Методы, распознаваемые как функции

Метод функции — это открытый метод общедоступного класса с атрибутом Function , примененным к методу, и атрибут триггера, примененный к входным параметру, как показано в следующем примере:

[Function(nameof(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)

Атрибут триггера указывает тип триггера и привязывает входные данные к параметру метода. В предыдущем примере функция активируется посредством сообщения очереди, которое передается методу в параметре myQueueItem.

Атрибут Function помечает метод как точку входа функции. Имя в проекте должно быть уникальным, начинаться с буквы и содержать только буквы, цифры, _ и -, а его длина не должна превышать 127 знаков. Шаблоны проектов часто создают метод Run, но метод может иметь любое допустимое имя для метода C#. Метод должен быть общедоступным членом общедоступного класса. Как правило, это метод экземпляра, чтобы службы могли передаваться через внедрение зависимостей.

Параметры функции

Ниже приведены некоторые параметры, которые можно включить в сигнатуру метода функции:

  • Привязки, которые помечены как такие, декорируя параметры как атрибуты. Функция должна содержать ровно один параметр триггера.
  • Объект контекста выполнения, предоставляющий сведения о текущем вызове.
  • Маркер отмены, используемый для корректного завершения работы.

Контекст выполнения

При изоляции .NET передает объект FunctionContext вашим методам функций. Этот объект позволяет получить ILogger экземпляр для записи в журналы, вызвав метод GetLogger и предоставив categoryName строку. Этот контекст можно использовать для получения ILogger без необходимости внедрения зависимостей. Подробнее см. в разделе Ведение журнала.

Токены отмены

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

Маркеры отмены поддерживаются в функциях .NET при выполнении в изолированном рабочем процессе. В следующем примере возникает исключение при получении запроса на отмену:

[Function(nameof(ThrowOnCancellation))]
public async Task ThrowOnCancellation(
    [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation));

    foreach (var message in messages)
    {
        cancellationToken.ThrowIfCancellationRequested();
        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

В следующем примере выполняются действия очистки при получении запроса на отмену:

[Function(nameof(HandleCancellationCleanup))]
public async Task HandleCancellationCleanup(
    [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup));

    foreach (var message in messages)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            _logger.LogInformation("A cancellation token was received, taking precautionary actions.");
            // Take precautions like noting how far along you are with processing the batch
            _logger.LogInformation("Precautionary activities complete.");
            break;
        }

        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

Привязки

Привязки определяются по атрибутам методов, параметров и типов возвращаемого значения. Привязки могут предоставлять данные в виде строк, массивов и сериализуемых типов, таких как обычные объекты класса (POC). Для некоторых расширений привязки можно также привязать к типам , определенным в пакетах SDK службы.

Сведения о триггерах HTTP см. в разделе триггеров HTTP.

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

Входные привязки

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

Выходные привязки

Чтобы записать в выходную привязку, необходимо применить атрибут выходной привязки к методу функции, который определяет, как записывать в связанную службу. Значение, возвращаемое методом, записывается в выходную привязку. Например, в следующем примере строковое значение записывается в очередь сообщений output-queue с помощью выходной привязки:

[Function(nameof(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)
{
    // Use a string array to return more than one message.
    string[] messages = {
        $"Album name = {myQueueItem.Name}",
        $"Album songs = {myQueueItem.Songs.ToString()}"};

    _logger.LogInformation("{msg1},{msg2}", messages[0], messages[1]);

    // Queue Output messages
    return messages;
}

Несколько выходных привязок

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

public static class MultiOutput
{
    [Function(nameof(MultiOutput))]
    public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req,
        FunctionContext context)
    {
        var response = req.CreateResponse(HttpStatusCode.OK);
        response.WriteString("Success!");

        string myQueueOutput = "some output";

        return new MyOutputType()
        {
            Name = myQueueOutput,
            HttpResponse = response
        };
    }
}

public class MyOutputType
{
    [QueueOutput("myQueue")]
    public string Name { get; set; }

    public HttpResponseData HttpResponse { get; set; }
}

Ответ от HTTP-триггера всегда считается выходным, поэтому атрибут возвращаемого значения не требуется.

Типы пакетов SDK

Для некоторых типов привязки для конкретной службы данные привязки можно предоставить с помощью типов пакетов SDK и платформ службы. Они предоставляют больше возможностей, помимо того, что может предложить сериализованная строка или обычный объект CLR (POCO). Чтобы использовать новые типы, проект необходимо обновить для использования более новых версий основных зависимостей.

Dependency Требование к версии
Microsoft.Azure.Functions.Worker 1.18.0 или более поздней версии
Microsoft.Azure.Functions.Worker.Sdk 1.13.0 или более поздней версии

При локальном тестировании типов SDK на компьютере также необходимо использовать Функции Azure Core Tools версии 4.0.5000 или более поздней. Текущую версию можно проверка с помощью func version команды.

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

Service Триггер Входные привязки Выходные привязки
Большие двоичные объекты Azure Общедоступная версия Общедоступная версия Типы пакетов SDK не рекомендуется.1
Azure Queues Общедоступная версия Входная привязка не существует Типы пакетов SDK не рекомендуется.1
Служебная шина Azure Общедоступная версия Входная привязка не существует Типы пакетов SDK не рекомендуется.1
Центры событий Azure Общедоступная версия Входная привязка не существует Типы пакетов SDK не рекомендуется.1
Azure Cosmos DB Типы пакетов SDK не используются2 Общедоступная версия Типы пакетов SDK не рекомендуется.1
Таблицы Azure Триггер не существует Общедоступная версия Типы пакетов SDK не рекомендуется.1
Сетка событий Azure Общедоступная версия Входная привязка не существует Типы пакетов SDK не рекомендуется.1

1 Для выходных сценариев, в которых используется тип пакета SDK, следует создавать и работать с клиентами SDK непосредственно вместо использования выходной привязки. Пример внедрения зависимостей см. в разделе "Регистрация клиентов Azure".

2 Триггер Cosmos DB использует веб-канал изменений Azure Cosmos DB и предоставляет элементы канала изменений в виде сериализуемых типов JSON. Отсутствие типов SDK выполняется путем разработки для этого сценария.

Примечание.

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

Триггер HTTP

Триггеры HTTP позволяют вызывать функцию с помощью HTTP-запроса. Существует два различных подхода, которые можно использовать:

  • Модель интеграции ASP.NET Core, использующая понятия, знакомые для разработчиков ASP.NET Core
  • Встроенная модель, которая не требует дополнительных зависимостей и использует пользовательские типы для HTTP-запросов и ответов. Этот подход поддерживается для обратной совместимости с предыдущими изолированными рабочими приложениями .NET.

интеграция ASP.NET Core

В этом разделе показано, как работать с базовыми объектами HTTP-запроса и ответа, используя типы из ASP.NET Core, включая HttpRequest, HttpResponse и IActionResult. Эта модель недоступна для приложений, предназначенных для платформа .NET Framework, которые вместо этого должны использовать встроенную модель.

Примечание.

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

Чтобы включить интеграцию ASP.NET Core для HTTP:

  1. Добавьте ссылку в проект в пакет Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore версии 1.0.0 или более поздней версии.

  2. Обновите проект, чтобы использовать следующие версии пакетов:

  3. Program.cs В файле обновите конфигурацию построителя узлов, чтобы использовать ConfigureFunctionsWebApplication() вместо нееConfigureFunctionsWorkerDefaults(). В следующем примере показана минимальная настройка без других настроек:

    using Microsoft.Extensions.Hosting;
    using Microsoft.Azure.Functions.Worker;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .Build();
    
    host.Run();
    
  4. Обновите все существующие функции, активированные HTTP, чтобы использовать типы основных ASP.NET. В этом примере показан стандарт HttpRequest и IActionResult используется для простой функции hello, world:

    [Function("HttpFunction")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
    {
        return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
    }
    

Встроенная модель HTTP

В встроенной модели система преобразует входящее сообщение HTTP-запроса в объект HttpRequestData , передаваемый функции. Этот объект предоставляет данные из запроса, включая Headers, Cookies, Identitiesи URLпри необходимости сообщение Body. Этот объект представляет HTTP-запрос, но не подключен непосредственно к базовому прослушивателю HTTP или полученному сообщению.

По этой логике функция возвращает объект HttpResponseData, который предоставляет данные, используемые для создания HTTP-ответа, включая сообщения StatusCode, Headers и — необязательно — сообщение Body.

В следующем примере показано использование HttpRequestData и HttpResponseData:

[Function(nameof(HttpFunction))]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger(nameof(HttpFunction));
    logger.LogInformation("message logged");

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    response.WriteString("Welcome to .NET isolated worker !!");

    return response;
}

Ведение журнала

В изолированной среде .NET можно записывать в журналы с помощью или ILogger экземпляраILogger<T>. Средство ведения журнала можно получить путем внедренияILogger<T> зависимостей или ILoggerFactory:

public class MyFunction {
    
    private readonly ILogger<MyFunction> _logger;
    
    public MyFunction(ILogger<MyFunction> logger) {
        _logger = logger;
    }
    
    [Function(nameof(MyFunction))]
    public void Run([BlobTrigger("samples-workitems/{name}", Connection = "")] string myBlob, string name)
    {
        _logger.LogInformation($"C# Blob trigger function Processed blob\n Name: {name} \n Data: {myBlob}");
    }

}

Средство ведения журнала также можно получить из объекта FunctionContext, переданного в функцию. Вызовите метод GetLogger T> или GetLogger<, передав строковое значение, которое является именем категории, в которой записываются журналы. Категория обычно совпадает с названием конкретной функции, из которой записываются журналы. Подробнее о категориях см. в статье об отслеживании.

Используйте методы и ILogger для записи различных уровней ILogger<T> журнала, таких как LogWarning илиLogError. Подробнее об уровнях журнала см. в статье об отслеживании. Уровни журнала для компонентов, добавленных в код, можно настроить, регистрируя фильтры в рамках HostBuilder конфигурации:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        // Registers IHttpClientFactory.
        // By default this sends a lot of Information-level logs.
        services.AddHttpClient();
    })
    .ConfigureLogging(logging =>
    {
        // Disable IHttpClientFactory Informational logs.
        // Note -- you can also remove the handler that does the logging: https://github.com/aspnet/HttpClientFactory/issues/196#issuecomment-432755765 
        logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
    })
    .Build();

В рамках настройки приложения Program.csможно также определить поведение для отображения ошибок в журналах. По умолчанию исключения, создаваемые кодом, могут быть заключены в оболочку RpcException. Чтобы удалить этот дополнительный слой, задайте EnableUserCodeException для свойства значение true в рамках настройки построителя:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder => {}, options =>
    {
        options.EnableUserCodeException = true;
    })
    .Build();

Application Insights

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

Установка пакетов

Чтобы записывать журналы непосредственно в приложение Аналитика из кода, добавьте ссылки на эти пакеты в проекте:

Чтобы добавить эти ссылки в проект, можно выполнить следующие команды:

dotnet add package Microsoft.ApplicationInsights.WorkerService
dotnet add package Microsoft.Azure.Functions.Worker.ApplicationInsights

Настройка запуска

При установке пакетов необходимо вызвать AddApplicationInsightsTelemetryWorkerService() и ConfigureFunctionsApplicationInsights() во время настройки службы в Program.cs файле, как в следующем примере:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
    
var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

Вызов ConfigureFunctionsApplicationInsights() добавления , ITelemetryModuleкоторый прослушивает определяемые ActivitySourceфункциями. Это создает данные телеметрии зависимостей, необходимые для поддержки распределенной трассировки. Дополнительные сведения о том, как его использовать, см. в AddApplicationInsightsTelemetryWorkerService() разделе "Приложения Аналитика для приложений службы рабочей роли".

Управление уровнями журнала

Внимание

Узел Функций и рабочая роль изолированного процесса имеют отдельную конфигурацию для уровней журнала и т. д. Любая конфигурация приложения Аналитика в host.json не повлияет на ведение журнала из рабочей роли, а конфигурация, сделанная в рабочем коде, не будет влиять на ведение журнала с узла. Необходимо применить изменения в обоих местах, если сценарий требует настройки на обоих уровнях.

Остальная часть приложения продолжает работать с ILogger и ILogger<T>. Однако по умолчанию пакет SDK для Application Insights добавляет фильтр ведения журнала, который предписывает средству ведения журнала регистрировать только предупреждения и более серьезные ошибки. Если вы хотите отключить это поведение, удалите правило фильтра в составе конфигурации службы:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .ConfigureLogging(logging =>
    {
        logging.Services.Configure<LoggerFilterOptions>(options =>
        {
            LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
            if (defaultRule is not null)
            {
                options.Rules.Remove(defaultRule);
            }
        });
    })
    .Build();

host.Run();

Оптимизация производительности

В этом разделе описаны параметры, которые позволяют повысить производительность при холодном запуске.

В общем случае приложение должно использовать последние версии его основных зависимостей. Как минимум, необходимо обновить проект следующим образом:

  1. Обновите Microsoft.Azure.Functions.Worker до версии 1.19.0 или более поздней.
  2. Обновите Microsoft.Azure.Functions.Worker.Sdk до версии 1.16.4 или более поздней.
  3. Добавьте ссылку Microsoft.AspNetCore.Appна платформу, если приложение не предназначено для платформа .NET Framework.

В следующем фрагменте кода показана эта конфигурация в контексте файла проекта:

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
  </ItemGroup>

Заполнители

Заполнители — это возможность платформы, которая улучшает холодный запуск для приложений, предназначенных для .NET 6 или более поздней версии. Чтобы использовать эту оптимизацию, необходимо явно включить заполнители, выполнив следующие действия:

  1. Обновите конфигурацию проекта, чтобы использовать последние версии зависимостей, как описано в предыдущем разделе.

  2. WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED Задайте для параметра 1приложения значение, которое можно сделать с помощью команды az functionapp config appsettings set:

    az functionapp config appsettings set -g <groupName> -n <appName> --settings 'WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED=1'
    

    В этом примере замените <groupName> имя группы ресурсов и замените <appName> именем приложения-функции.

  3. Убедитесь, что netFrameworkVersion свойство приложения-функции соответствует целевой платформе проекта, которая должна быть .NET 6 или более поздней версии. Это можно сделать с помощью команды az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>
    

    В этом примере также замените <framework> соответствующую строку версии, например v8.0, v7.0или v6.0в соответствии с целевой версией .NET.

  4. Убедитесь, что приложение-функция настроено на использование 64-разрядного процесса, который можно сделать с помощью этой команды az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --use-32bit-worker-process false
    

Внимание

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

Оптимизированный исполнитель

Исполнитель функции — это компонент платформы, которая вызывает вызовы. Оптимизированная версия этого компонента включена по умолчанию начиная с версии 1.16.2 пакета SDK. Дальнейшая настройка не требуется.

ReadyToRun

Приложение-функцию можно скомпилировать как двоичные файлы ReadytoRun. ReadyToRun — это форма предварительной компиляции, которая может повысить производительность запуска, чтобы снизить влияние холодного запуска при выполнении в плане потребления. ReadyToRun доступен в .NET 6 и более поздних версиях и требует версии 4.0 или более поздней версии среды выполнения Функции Azure.

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

Операционная система Приложение равно 32-разрядному1 Идентификатор среды выполнения
Windows Истина win-x86
Windows False win-x64
Linux Истина Не поддерживается.
Linux False linux-x64

1 Только 64-разрядные приложения имеют право на некоторые другие оптимизации производительности.

Чтобы проверка, если приложение Windows имеет 32-разрядную или 64-разрядную версию, можно выполнить следующую команду CLI, подставив <group_name> имя группы ресурсов и <app_name> имя приложения. Выходные данные true указывают на то, что приложение имеет 32-разрядную версию, а значение false — 64-разрядную версию.

 az functionapp config show -g <group_name> -n <app_name> --query "use32BitWorkerProcess"

Вы можете изменить приложение на 64-разрядную с помощью следующей команды, используя те же подстановки:

az functionapp config set -g <group_name> -n <app_name> --use-32bit-worker-process false`

Чтобы скомпилировать проект как ReadyToRun, обновите файл проекта, добавив элементы <PublishReadyToRun> и <RuntimeIdentifier>. В следующем примере показана конфигурация публикации в приложении-функции Windows 64-разрядной версии.

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

Если вы не хотите задать <RuntimeIdentifier> в качестве части файла проекта, можно также настроить его как часть самого жеста публикации. Например, с приложением-функцией Windows 64-разрядной версии команда .NET CLI будет:

dotnet publish --runtime win-x64

В Visual Studio параметр целевой среды выполнения в профиле публикации должен иметь правильный идентификатор среды выполнения. Если задано значение по умолчанию Portable, ReadyToRun не используется.

Развертывание в Функции Azure

При развертывании проекта кода функции в Azure он должен выполняться в приложении-функции или в контейнере Linux. Приложение-функция и другие необходимые ресурсы Azure должны существовать перед развертыванием кода.

Вы также можете развернуть приложение-функцию в контейнере Linux. Дополнительные сведения см. в статье "Работа с контейнерами и Функции Azure".

Создание ресурсов Azure

Вы можете создать приложение-функцию и другие необходимые ресурсы в Azure с помощью одного из следующих методов:

Опубликовать проект кода

После создания приложения-функции и других необходимых ресурсов в Azure можно развернуть проект кода в Azure с помощью одного из следующих методов:

Дополнительные сведения см. в статье Технологии развертывания в Функциях Azure.

Требования к развертыванию

Существует несколько требований для выполнения функций .NET в изолированной рабочей модели в Azure в зависимости от операционной системы:

  • FUNCTIONS_WORKER_RUNTIME должно быть задано значение dotnet-isolated.
  • netFrameworkVersion должен иметь нужную версию.

При создании приложения-функции в Azure с помощью методов, описанных в предыдущем разделе, эти необходимые параметры добавляются для вас. При создании этих ресурсов с помощью шаблонов ARM или Bicep-файлов для автоматизации необходимо установить их в шаблоне.

Отладка

При локальном запуске с помощью Visual Studio или Visual Studio Code вы можете выполнить отладку изолированного рабочего проекта .NET как обычно. Однако существует два сценария отладки, которые не работают должным образом.

Удаленная отладка с помощью Visual Studio

Так как приложение изолированного рабочего процесса выполняется вне среды выполнения Функций, необходимо подключить удаленный отладчик к отдельному процессу. Дополнительные сведения об отладке с помощью Visual Studio см. в статье Удаленная отладка.

Отладка при ориентации на .NET Framework

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

Приложение должно начинаться с вызова FunctionsDebugger.Enable(); в качестве первой операции. Это происходит в методе Main() перед инициализацией HostBuilder. Файл Program.cs должен выглядеть следующим образом:

using System;
using System.Diagnostics;
using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker;
using NetFxWorker;

namespace MyDotnetFrameworkProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            FunctionsDebugger.Enable();

            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .Build();

            host.Run();
        }
    }
}

Затем необходимо вручную подключиться к процессу с помощью отладчика .NET Framework. Visual Studio не делает это автоматически для изолированных рабочих процессов, платформа .NET Framework приложений, и следует избежать операции "Начать отладку".

В каталоге проекта (или выходном каталоге его сборки) выполните следующую команду:

func host start --dotnet-isolated-debug

Это запускает рабочую роль, и процесс останавливается со следующим сообщением:

Azure Functions .NET Worker (PID: <process id>) initialized in debug mode. Waiting for debugger to attach...

Где <process id> — идентификатор рабочего процесса. Теперь можно использовать Visual Studio для ручного присоединения к процессу. Инструкции по этой операции см. в разделе Подключение к запущенному процессу.

После подключения отладчика выполнение процесса возобновляется, и вы сможете выполнить отладку.

Предварительная версия .NET

До общедоступного выпуска версия .NET может быть выпущена в режиме предварительной версии или в режиме go-live. Дополнительные сведения об этих состояниях см. в политике поддержки .NET.

Хотя может оказаться возможным использовать указанный выпуск из локального проекта Функций, приложения-функции, размещенные в Azure, могут не иметь этого выпуска. Функции Azure можно использовать только с предварительными версиями или выпусками Go-live, указанными в этом разделе.

Функции Azure в настоящее время не работает с выпусками .NET предварительной версии или Go-live. Список общедоступных выпусков, которые можно использовать, см. в поддерживаемых версиях .

Использование пакета SDK для .NET предварительной версии

Чтобы использовать Функции Azure с предварительной версией .NET, необходимо обновить проект следующим образом:

  1. Установка соответствующей версии пакета SDK для .NET в разработке
  2. TargetFramework Изменение параметра в .csproj файле

При развертывании в приложении-функции в Azure также необходимо убедиться, что платформа доступна приложению. Для этого в Windows можно использовать следующую команду CLI. Замените <groupName> именем группы ресурсов и замените <appName> именем приложения-функции. Замените <framework> соответствующую строку версии, например v8.0.

az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>

Рекомендации по использованию предварительных версий .NET

Учитывайте эти рекомендации при использовании функций с предварительными версиями .NET:

  • При создании функций в Visual Studio необходимо использовать Предварительную версию Visual Studio, которая поддерживает создание проектов Функции Azure с помощью пакетов SDK предварительной версии .NET.

  • Убедитесь, что у вас есть последние инструменты и шаблоны функций. Чтобы обновить средства, выполните приведенные далее действия.

    1. Перейдите к параметрам инструментов>, выберите Функции Azure в разделе "Проекты и решения".
    2. Выберите "Проверить наличие обновлений " и установить обновления по запросу.
  • В течение периода предварительной версии среда разработки может иметь более последнюю версию предварительной версии .NET, чем размещенную службу. Это может привести к сбою приложения-функции при развертывании. Для этого можно указать версию пакета SDK для использования global.json.

    1. dotnet --list-sdks Выполните команду и запишите предварительную версию, которую вы используете в настоящее время во время локальной разработки.
    2. dotnet new globaljson --sdk-version <SDK_VERSION> --force Выполните команду, где <SDK_VERSION> используется локальная версия. Например, dotnet new globaljson --sdk-version dotnet-sdk-8.0.100-preview.7.23376.3 --force система будет использовать пакет SDK для .NET 8 предварительной версии 7 при создании проекта.

Примечание.

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

Следующие шаги