Freigeben über


Leitfaden zum Ausführen von Azure Functions (C#) in einem isolierten Workermodell

Dieser Artikel enthält eine Einführung in die Arbeit mit Azure Functions in .NET mithilfe des isolierten Workermodells. Mit diesem Modell kann Ihr Projekt unabhängig von anderen Runtimekomponenten auf Versionen von .NET ausgerichtet werden. Informationen zu bestimmten unterstützten .NET-Versionen finden Sie unter Unterstützte Versionen.

Über die folgenden Links können Sie sofort mit der Erstellung von .NET-Funktionen in isolierten Workermodellen beginnen.

Erste Schritte Konzepte Beispiele

Informationen zum Bereitstellen eines Projekts mit isoliertem Workermodell in Azure finden Sie unter Bereitstellen in Azure Functions.

Vorteile des isolierten Workermodells

Es gibt zwei Modi, in denen Sie die .NET-Klassenbibliotheksfunktionen ausführen können: entweder im gleichen Prozess wie die Functions-Hostruntime (In-Process) oder in einem isolierten Workerprozess. Die Ausführung von .NET-Funktionen in einem isolierten Workerprozess bietet folgende Vorteile:

  • Weniger Konflikte: Da Ihre Funktionen in einem separaten Prozess ausgeführt werden, geraten die Assemblys Ihrer App nicht mit unterschiedlichen Versionen der gleichen Assemblys in Konflikt, die vom Hostprozess verwendet werden.
  • Vollständige Kontrolle über den Prozess: Sie steuern den Start der App, können also die verwendeten Konfigurationen und die gestartete Middleware verwalten.
  • Standardmäßige Abhängigkeitsinjektion: Da Sie die vollständige Kontrolle über den Prozess haben, können Sie aktuelle .NET-Verhaltensweisen für die Abhängigkeitsinjektion und die Einbindung von Middleware in Ihre Funktions-App nutzen.
  • .NET-Versionsflexibilität: Dank der Ausführung außerhalb des Hostprozesses können Ihre Funktionen in .NET-Versionen ausgeführt werden, die nicht nativ von der Functions-Runtime unterstützt werden. Dies schließt auch .NET Framework ein.

Wenn Sie bereits über eine C#-Funktions-App mit In-Process-Ausführung verfügen, müssen Sie Ihre App migrieren, um diese Vorteile nutzen zu können. Weitere Informationen finden Sie unter Migrieren von .NET-Apps vom In-Process-Modell zum isolierten Workermodell.

Einen umfassenden Vergleich zwischen den beiden Modellen finden Sie unter Unterschiede zwischen einem In-Process- und einem isolierten Workerprozess in .NET-Azure Functions.

Unterstützte Versionen

Versionen der Functions-Laufzeit unterstützen bestimmte Versionen von .NET. Weitere Informationen zu den Functions-Versionen finden Sie unter Übersicht über die Runtimeversionen von Azure Functions. Die Versionsunterstützung hängt auch davon ab, ob Ihre Funktionen prozessintern oder in einem isolierten Workerprozess ausgeführt werden.

Hinweis

Informationen zum Ändern der von Ihrer Funktions-App verwendeten Functions-Runtimeversion finden Sie unter Anzeigen und Aktualisieren der aktuellen Runtimeversion.

In der folgenden Tabelle sind die höchsten .NET- bzw. .NET Framework-Versionen aufgeführt, die mit einer bestimmten Version von Functions verwendet werden können.

Version der Functions-Laufzeit Isoliertes Workermodell In-Process-Modell4
Functions 4.x1 .NET 9.0
.NET 8.0
.NET Framework 4.82
.NET 8.0
Functions 1.x3 Nicht zutreffend .NET Framework 4.8

1 .NET 6 wurde zuvor in beiden Modellen unterstützt, hat aber am 12. November 2024 das Ende der offiziellen Unterstützung erreicht. .NET 7 wurde zuvor beim isolierten Workermodell unterstützt, hat aber am 14. Mai 2024 das Ende der offiziellen Unterstützung erreicht.

2 Für den Buildprozess ist auch das .NET SDK erforderlich.

3 Der Support für die Version 1.x der Azure Functions-Runtime endet am 14. September 2026. Weitere Informationen finden Sie in dieser Supportankündigung. Um weiterhin uneingeschränkten Support zu erhalten, müssen Sie Ihre Apps zur Version  4.x migrieren.

4 Die Unterstützung für das In-Process-Modell endet am 10. November 2026. Weitere Informationen finden Sie in dieser Supportankündigung. Um weiterhin uneingeschränkten Support zu erhalten, müssen Sie Ihre Apps zum Modell mit isolierten Workern migrieren.

Aktuelle Informationen zu Azure Functions-Releases (einschließlich Informationen zur Entfernung bestimmter älterer Nebenversionen) finden Sie unter Azure App Service-Ankündigungen.

Projektstruktur

Ein .NET-Projekt für Azure Functions mit dem isolierten Workermodell ist im Grunde ein Projekt für eine .NET-Konsolen-App mit einer unterstützten .NET-Runtime als Ziel. Die folgenden Dateien werden in jedem isolierten .NET-Projekt benötigt:

  • C#-Projektdatei (.csproj), definiert das Projekt und die Abhängigkeiten
  • Program.cs, der Einstiegspunkt für die App
  • Alle Codedateien, die Ihre Funktionen definieren.
  • Die Datei host.json, die die Konfiguration definiert, die von Funktionen in Ihrem Projekt gemeinsam genutzt wird.
  • Die Datei local.settings.json, die Umgebungsvariablen definiert, die von Ihrem Projekt verwendet werden, wenn es lokal auf Ihrem Computer ausgeführt werden.

Vollständige Beispiele finden Sie im Beispielprojekt für .NET 8 sowie im Beispielprojekt für .NET Framework 4.8.

Paketverweise

Ein .NET-Projekt für Azure Functions mit dem isolierten Workermodell verwendet individuelle Pakete für Kernfunktionen und Bindungserweiterungen.

Erforderliche Pakete

Die folgenden Pakete werden benötigt, damit Ihre .NET-Funktionen in einem isolierten Workerprozess ausgeführt werden können:

Version 2.x

In Version 2.x der Kernpakete wurden die unterstützten Frameworks geändert. Außerdem bieten sie Unterstützung für neue .NET-APIs aus diesen späteren Versionen. Wenn Sie .NET 9 oder höher verwenden, muss Ihre App bei beiden Paketen auf die Version 2.0.0 oder höher verweisen.

Beachten Sie beim Aktualisieren auf die 2.x-Versionen die folgenden Änderungen:

  • Ab Version 2.0.0 von Microsoft.Azure.Functions.Worker.Sdk:
  • Ab Version 2.0.0 von Microsoft.Azure.Functions.Worker:
    • Diese Version bietet Unterstützung für IHostApplicationBuilder. Einige Beispiele in diesem Leitfaden enthalten Registerkarten mit Alternativen, die IHostApplicationBuilder verwenden. Für diese Beispiele sind 2.x-Versionen erforderlich.
    • Die Gültigkeitsprüfung des Dienstanbieterbereichs ist standardmäßig enthalten, wenn die Ausführung in einer Entwicklungsumgebung erfolgt. Dieses Verhalten entspricht dem von ASP.NET Core.
    • Die EnableUserCodeException-Option ist standardmäßig aktiviert. Die Eigenschaft ist jetzt als veraltet markiert.
    • Die IncludeEmptyEntriesInMessagePayload-Option ist standardmäßig aktiviert. Wenn diese Option aktiviert ist, löst sie Nutzdaten aus, die Sammlungen mit stets leeren Einträge darstellen. Wenn beispielsweise eine Nachricht ohne Text gesendet wird, ist für die Triggerdaten trotzdem ein leerer string[] enthalten. Der Einschluss leerer Einträge vereinfacht Querverweise mit Metadatenarrays, auf die die Funktion ebenfalls verweisen kann. Sie können dieses Verhalten deaktivieren, indem Sie in der WorkerOptions-Dienstkonfiguration IncludeEmptyEntriesInMessagePayload auf false festlegen.
    • Die ILoggerExtensions-Klasse wurde in FunctionsLoggerExtensions umbenannt. Die Umbenennung verhindert einen Fehler durch einen mehrdeutigen Aufruf bei Verwendung von LogMetric() in einer ILogger-Instanz.
    • Bei Apps, die HttpResponseData verwenden, legt die WriteAsJsonAsync()-Methode den Statuscode nicht mehr auf 200 OK fest. In 1.x überschreiben dies andere Fehlercodes, die festgelegt wurden.
  • Die 2.x-Versionen unterstützen .NET 5 TFM nicht mehr.

Erweiterungspakete

Da .NET-Funktionen in einem isolierten Workerprozess andere Bindungstypen verwenden, benötigen sie spezifische Pakete mit Bindungserweiterungen.

Diese Erweiterungspakete finden Sie unter Microsoft.Azure.Functions.Worker.Extensions.

Start und Konfiguration

Wenn Sie das isolierte Workermodell verwenden, haben Sie Zugriff auf die Startfunktion Ihrer Funktions-App, die sich in der Regel in Program.cs befindet. Sie sind dafür verantwortlich, eine eigene Hostinstanz zu erstellen und zu starten. Sie haben daher auch direkten Zugriff auf die Konfigurationspipeline für Ihre App. Mit .NET-Funktionen in einem isolierten Workerprozess können Sie viel einfacher Konfigurationen und Abhängigkeiten hinzufügen sowie Ihre eigene Middleware ausführen.

Im Folgenden sehen Sie ein Beispiel für eine HostBuilder-Pipeline:

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

Für diesen Code ist using Microsoft.Extensions.DependencyInjection; erforderlich.

Bevor Sie Build() für IHostBuilderaufrufen, sollten Sie:

  • Entweder ConfigureFunctionsWebApplication() aufrufen, wenn Sie ASP.NET Core-Integration verwenden, oder andernfalls ConfigureFunctionsWorkerDefaults(). Einzelheiten zu diesen Optionen finden Sie unter HTTP-Trigger.
    Wenn Sie Ihre Anwendung mit F# schreiben, benötigen einige Trigger- und Bindungserweiterungen eine zusätzliche Konfiguration. Lesen Sie die Setupdokumentation für die Blobs-Erweiterung, die Tables-Erweiterung und die Cosmos DB-Erweiterung, wenn Sie diese Erweiterungen in einer F#-App verwenden möchten.
  • Konfigurieren Sie Dienste oder App-Konfigurationen, die für Ihr Projekt erforderlich sind. Ausführliche Informationen finden Sie unter Konfiguration.
    Wenn Sie die Verwendung von Application Insights planen, müssen Sie AddApplicationInsightsTelemetryWorkerService() und ConfigureFunctionsApplicationInsights() im Delegaten ConfigureServices() aufrufen. Weitere Informationen finden Sie unter Application Insights.

Wenn Ihr Projekt auf .NET Framework 4.8 ausgerichtet ist, müssen Sie auch FunctionsDebugger.Enable(); hinzufügen, bevor Sie den HostBuilder erstellen. Es sollte die erste Zeile Ihrer Main()-Methode sein. Weitere Informationen finden Sie unter Debuggen für .NET Framework.

Der HostBuilder wird zur Erstellung und Rückgabe einer vollständig initialisierten IHost-Instanz verwendet. Diese führen Sie asynchron aus, um Ihre Funktions-App zu starten.

await host.RunAsync();

Konfiguration

Der Typ des verwendeten Generators bestimmt, wie Sie die Anwendung konfigurieren können.

Die ConfigureFunctionsWorkerDefaults-Methode dient dazu, die für die Ausführung der Funktions-App erforderlichen Einstellungen hinzuzufügen. Die Methode enthält die folgenden Funktionen:

  • Standardsatz von Konvertern.
  • Legen Sie die Standard-JsonSerializerOptions fest, um die Groß- und Kleinschreibung von Eigenschaftsnamen zu übergehen.
  • Integration in Azure Functions-Protokollierung.
  • Ausgabe verbindlicher Middleware und Funktionen.
  • Middleware für die Funktionsausführung.
  • Standardmäßige gRPC-Unterstützung.
.ConfigureFunctionsWorkerDefaults()

Da Sie Zugriff auf die HostBuilder-Pipeline haben, können Sie auch App-spezifische Konfigurationen während der Initialisierung festlegen. Zum Hinzufügen der Konfigurationsquellen, die für Ihren Code erforderlich sind, können Sie die ConfigureAppConfiguration-Methode (auch mehrmals) für HostBuilder aufrufen. Weitere Informationen zur App-Konfiguration finden Sie unter Konfiguration in ASP.NET Core.

Diese Konfigurationen gelten nur für den Workercode, den Sie erstellen. Sie beeinflussen nicht direkt die Konfiguration des Functions-Hosts oder der Trigger und Bindungen. Wenn Sie Änderungen am Funktionshost oder -trigger und an der Bindungskonfiguration vornehmen möchten, müssen Sie weiterhin die Datei host.json verwenden.

Hinweis

Benutzerdefinierte Konfigurationsquellen können nicht für die Konfiguration von Auslösern und Bindungen verwendet werden. Die Auslöser- und Bindungskonfiguration muss für die Funktionenplattform und nicht nur für Ihren Anwendungscode verfügbar sein. Sie können diese Konfiguration über die Anwendungseinstellungen, Key Vault-Verweise oder App Configuration-Verweise bereitstellen.

Abhängigkeitsinjektion

Beim isolierte Workermodell werden standardmäßige .NET-Mechanismen zum Einfügen von Diensten verwendet.

Wenn Sie einen HostBuilder verwenden, rufen Sie ConfigureServices im Host-Generator auf und verwenden die Erweiterungsmethoden in IServiceCollection, um bestimmte Dienste einzufügen. Im folgenden Beispiel wird eine Dependency Injection für einen Singletondienst durchgeführt:

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

Für diesen Code ist using Microsoft.Extensions.DependencyInjection; erforderlich. Weitere Informationen finden Sie unter Dependency Injection in ASP.NET Core.

Registrieren von Azure-Clients

Die Abhängigkeitsinjektion kann für die Interaktion mit anderen Azure-Diensten verwendet werden. Sie können Clients aus dem Azure SDK für .NET mithilfe des Pakets Microsoft.Extensions.Azure einfügen. Nach der Installation des Pakets registrieren Sie die Clients, indem Sie AddAzureClients() für die Dienstsammlung in Program.cs aufrufen. Im folgenden Beispiel wird ein benannter Client für Azure-Blobs konfiguriert:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection;
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();

Das folgende Beispiel zeigt, wie wir diese Registrierung und SDK-Typen verwenden können, um Blobinhalte mithilfe eines eingefügten Clients als Stream aus einem Container in einen anderen zu kopieren:

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> in diesem Beispiel wurde ebenfalls durch Abhängigkeitsinjektion abgerufen und somit automatisch registriert. Weitere Informationen zu den Konfigurationsoptionen für die Protokollierung finden Sie unter Protokollierung.

Tipp

Im Beispiel wurde eine Literalzeichenfolge für den Namen des Clients in Program.cs und der Funktion verwendet. Erwägen Sie stattdessen die Verwendung einer gemeinsamen konstanten Zeichenfolge, die für die Funktionsklasse definiert ist. Sie können z. B. beiden Speicherorten public const string CopyStorageClientName = nameof(_copyContainerClient); hinzufügen und dann an beiden Speicherorten auf BlobCopier.CopyStorageClientName verweisen. In ähnlicher Weise können Sie den Namen des Konfigurationsabschnitts mit der Funktion statt in Program.cs definieren.

Middleware

Das isolierte Workermodell unterstützt auch die Middleware-Registrierung mit einem Modell, das dem in ASP.NET vorhandenen Modell ähnelt. Dieses Modell bietet Ihnen die Möglichkeit, Logik in die Aufrufpipeline einzufügen, und vorher und nachher Funktionen auszuführen.

Die Erweiterungsmethode ConfigureFunctionsWorkerDefaults weist eine Überladung auf, mit der Sie Ihre eigene Middleware registrieren können, wie im folgenden Beispiel zu sehen ist.

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

Die Erweiterungsmethode UseWhen kann verwendet werden, um bedingt ausgeführte Middleware zu registrieren. An diese Methode muss ein Prädikat übergeben werden, das einen booleschen Wert zurückgibt, und die Middleware nimmt an der Aufrufverarbeitungspipeline teil, wenn der Rückgabewert des Prädikats true ist.

Die folgenden Erweiterungsmethoden für FunctionContext erleichtern das Arbeiten mit Middleware im isolierten Modell.

Methode BESCHREIBUNG
GetHttpRequestDataAsync Ruft die HttpRequestData-Instanz ab, wenn der Aufruf durch einen HTTP-Trigger erfolgt. Diese Methode gibt eine Instanz von ValueTask<HttpRequestData?> zurück, die nützlich ist, wenn Sie Nachrichtendaten lesen möchten, z. B. Anforderungsheader und Cookies.
GetHttpResponseData Ruft die HttpResponseData-Instanz ab, wenn der Aufruf durch einen HTTP-Trigger erfolgt.
GetInvocationResult Ruft eine Instanz von InvocationResult ab, die das Ergebnis der aktuellen Funktionsausführung darstellt. Verwenden Sie die Value-Eigenschaft, um den Wert nach Bedarf abzurufen oder festzulegen.
GetOutputBindings Ruft die Ausgabebindungseinträge für die aktuelle Funktionsausführung ab. Jeder Eintrag im Ergebnis dieser Methode ist vom Typ OutputBindingData. Sie können die Value-Eigenschaft verwenden, um den Wert nach Bedarf abzurufen oder festzulegen.
BindInputAsync Bindet ein Eingabebindungselement für die angeforderte BindingMetadata-Instanz. Sie können diese Methode beispielsweise verwenden, wenn Sie über eine Funktion mit einer BlobInput-Eingabebindung verfügen, die von Ihrer Middleware verwendet werden muss.

Hier sehen Sie ein Beispiel für eine Middlewareimplementierung, die die Instanz HttpRequestData liest und die Instanz HttpResponseData während der Funktionsausführung aktualisiert:

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

Diese Middleware überprüft, ob ein bestimmter Anforderungsheader (x-correlationId) vorhanden ist. Wenn dies der Fall ist, verwendet sie den Headerwert, um einen Antwortheader zu stempeln. Andernfalls generiert sie einen neuen GUID-Wert und verwendet diesen zum Stempeln des Antwortheaders. Ein ausführlicheres Beispiel für die Verwendung von benutzerdefinierter Middleware in ihrer Funktions-APP finden Sie im Beispiel für eine benutzerdefinierte Middleware-Referenz.

Anpassen der JSON-Serialisierung

Das isolierte Arbeitsmodell verwendet System.Text.Json standardmäßig. Sie können das Verhalten des Serialisierungsmoduls anpassen, indem Sie Dienste als Teil Ihrer Program.cs Datei konfigurieren. In diesem Abschnitt wird die allgemeine Serialisierung behandelt, die keinen Einfluss auf die HTTP-Trigger JSON-Serialisierung mit ASP.NET Core-Integration hat, die separat konfiguriert werden muss.

Das folgende Beispiel zeigt diese Verwendung ConfigureFunctionsWebApplication, funktioniert aber auch für ConfigureFunctionsWorkerDefaults:

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

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

host.Run();

Sie können stattdessen JSON.NET (Newtonsoft.Json) für die Serialisierung verwenden. Dazu installieren Sie das Microsoft.Azure.Core.NewtonsoftJson Paket. Anschließend würden Sie in Ihrer Dienstregistrierung die Serializer Eigenschaft für die WorkerOptions Konfiguration neu zuweisen. Das folgende Beispiel zeigt diese Verwendung ConfigureFunctionsWebApplication, funktioniert aber auch für ConfigureFunctionsWorkerDefaults:

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

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

host.Run();

Methoden, die als Funktionen erkannt werden

Eine Funktionsmethode ist eine öffentliche Methode einer öffentlichen Klasse mit einem Function-Attribut, das auf die Methode angewendet wird, und einem Trigger-Attribut, das auf einen Ausgabeparameter angewendet wird. Dies wird im folgenden Beispiel veranschaulicht:

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

Das Trigger-Attribut gibt den Triggertyp an und bindet die Eingabedaten an einen Methodenparameter. Die zuvor gezeigte Beispielfunktion wird durch eine Warteschlangennachricht ausgelöst, und die Warteschlangennachricht wird im Parameter myQueueItem an die Methode übergeben.

Das Attribut Function kennzeichnet die Methode als Funktionseinstiegspunkt. Der Name muss innerhalb eines Projekts eindeutig sein, mit einem Buchstaben beginnen und darf nur Buchstaben, Ziffern, _ und - enthalten. Bis zu 127 Zeichen sind zulässig. Projektvorlagen erstellen oft eine Methode namens Run, aber der Name der Methode kann ein beliebiger gültiger C#-Methodennamen sein. Die Methode muss ein öffentliches Element einer öffentlichen Klasse sein. Es sollte im Allgemeinen eine Instanzmethode sein, damit Dienste über Abhängigkeitsinjektion übergeben werden können.

Funktionsparameter

Hier sind Sie einige der Parameter, die Sie in eine Funktionsmethodensignatur einschließen können:

  • Bindungen, die entsprechend gekennzeichnet werden, indem die Parameter als Attribute dargestellt werden. Die Funktion muss genau einen Triggerparameter enthalten.
  • Ein Ausführungskontextobjekt, das Informationen zum aktuellen Aufruf bereitstellt.
  • Ein Abbruchtoken zum ordnungsgemäßen Herunterfahren.

Ausführungskontext

Der isolierte .NET-Prozess übergibt ein FunctionContext-Objekt an Ihre Funktionsmethoden. Mit diesem Objekt erhalten Sie eine ILogger-Instanz, um in die Protokolle zu schreiben, indem Sie die GetLogger-Methode aufrufen und eine categoryName Zeichenfolge anbieten. Sie können diesen Kontext verwenden, um eine ILogger-Instanz zu erhalten, ohne die Abhängigkeitsinjektion verwenden zu müssen. Weitere Informationen finden Sie unter Protokollierung.

Abbruchtoken

Eine Funktion kann einen CancellationToken-Parameter annehmen, der es dem Betriebssystem ermöglicht, den Code vor dem Beenden der Funktion zu benachrichtigen. Sie können diese Benachrichtigung verwenden, um sicherzustellen, dass die Funktion nicht auf eine Weise unerwartet beendet wird, die die Daten in einem inkonsistenten Zustand hinterlässt.

Abbruchtoken werden in .NET-Funktionen unterstützt, wenn sie in einem isolierten Workerprozess ausgeführt werden. Im folgenden Beispiel wird eine Ausnahme ausgelöst, wenn eine Abbruchanforderung empfangen wird:

[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);
    }
}

Im folgenden Beispiel werden Bereinigungsaktionen ausgeführt, wenn eine Abbruchanforderung empfangen wird:

[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);
    }
}

Bindungen

Bindungen werden mithilfe von Attributen in Methoden, Parametern und Rückgabetypen definiert. Bindungen können Daten in Form von Zeichenfolgen, Arrays und serialisierbare Typen, beispielsweise Plain Old CLR Objects (POCOs) bieten. Bei einigen Bindungserweiterungen können Sie auch eine Bindung an dienstspezifische Typen vornehmen, die in Dienst-SDKs definiert sind.

Informationen zu HTTP-Triggern finden Sie im Abschnitt HTTP-Trigger.

Umfassende Referenzbeispiele zur Verwendung von Triggern und Bindungen mit Funktionen in isolierten Workerprozessen finden Sie im Referenzbeispiel für Bindungserweiterungen.

Eingabebindungen

Eine Funktion kann über null oder mehr Eingabebindungen verfügen, die Daten an eine andere Funktion übergeben können. Genau wie Trigger werden Eingabebindungen definiert, indem ein Bindungsattribut auf einen Eingabeparameter angewendet wird. Wenn die Funktion ausgeführt wird, versucht die Runtime, die in der Bindung angegebenen Daten abzurufen. Die angeforderten Daten sind häufig von den Informationen abhängig, die vom Triggern mithilfe von Bindungsparametern bereitgestellt werden.

Ausgabebindungen

Wenn Sie eine Ausgabebindung schreiben möchten, müssen Sie ein Ausgabebindungsattribut an die Funktionsmethode anfügen. Dadurch wird definiert, wie in den gebundenen Dienst geschrieben werden soll. Der von der Methode zurückgegebene Wert wird in die Ausgabebindung geschrieben. Im folgenden Beispiel wird ein Zeichenfolgenwert mithilfe einer Ausgabebindung in die Nachrichtenwarteschlange output-queue geschrieben:

[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}"};

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

    // Queue Output messages
    return messages;
}

Mehrere Ausgabebindungen

Die Daten, die in eine Ausgabebindung geschrieben werden, sind immer der Rückgabewert der Funktion. Wenn Sie in mehr als eine Ausgabebindung schreiben müssen, müssen Sie einen benutzerdefinierten Rückgabetyp erstellen. Bei diesem Rückgabetyp muss das Ausgabebindungsattribut auf eine oder mehrere Eigenschaften der Klasse angewendet werden. Das folgende Beispiel ist eine HTTP-ausgelöste Funktion mit ASP.NET Core-Integration, die sowohl in die HTTP-Antwort als auch auf eine Warteschlangenausgabebindung schreibt:

public class MultipleOutputBindings
{
    private readonly ILogger<MultipleOutputBindings> _logger;

    public MultipleOutputBindings(ILogger<MultipleOutputBindings> logger)
    {
        _logger = logger;
    }

    [Function("MultipleOutputBindings")]
    public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");
        var myObject = new MyOutputType
        {
            Result = new OkObjectResult("C# HTTP trigger function processed a request."),
            MessageText = "some output"
        };
        return myObject;
    }

    public class MyOutputType
    {
        [HttpResult]
        public IActionResult Result { get; set; }

        [QueueOutput("myQueue")]
        public string MessageText { get; set; }
    }
}

Wenn Sie benutzerdefinierte Rückgabetypen für mehrere Ausgabebindungen mit ASP.NET Core-Integration verwenden, müssen Sie der Eigenschaft, die das Ergebnis bereitstellt, das [HttpResult] Attribut hinzufügen. Das HttpResult-Attribut ist verfügbar, wenn Sie SDK 1.17.3-preview2 oder höher mit der HTTP-Erweiterung, Version 3.2.0 oder höher, und der ASP.NET Core-Erweiterung, Version 1.3.0 oder höher verwenden.

SDK-Typen

Bei einigen dienstspezifischen Bindungstypen können Bindungsdaten mithilfe von Typen aus Dienst-SDKs und Frameworks bereitgestellt werden. Sie bieten zusätzliche Funktionen, die über das hinausgehen, was eine serialisierte Zeichenfolge oder ein POCO-Objekt (Plain Old CLR Object) bieten kann. Damit die neueren Typen genutzt werden können, muss Ihr Projekt aktualisiert werden, um neuere Versionen von Kernabhängigkeiten zu verwenden.

Abhängigkeit Versionsanforderung
Microsoft.Azure.Functions.Worker 1.18.0 oder höher
Microsoft.Azure.Functions.Worker.Sdk 1.13.0 oder höher

Wenn Sie SDK-Typen lokal auf Ihrem Computer testen, müssen Sie auch Azure Functions Core Tools (ab Version 4.0.5000) verwenden. Sie können Ihre aktuelle Version mithilfe des Befehls func version überprüfen.

Für jede Trigger- und Bindungserweiterung gilt zusätzlich eine gesonderte Anforderung an die Mindestversion, wie in den Referenzartikeln zur jeweiligen Erweiterung beschrieben. Folgende dienstspezifische Bindungen bieten SDK-Typen:

Dienst Trigger Eingabebindung Ausgabebindung
Azure-Blobs Allgemein verfügbar Allgemein verfügbar SDK-Typen nicht empfohlen1
Azure-Warteschlangen Allgemein verfügbar Keine Eingabebindung vorhanden SDK-Typen nicht empfohlen1
Azure Service Bus Allgemein verfügbar Keine Eingabebindung vorhanden SDK-Typen nicht empfohlen1
Azure Event Hubs Allgemein verfügbar Keine Eingabebindung vorhanden SDK-Typen nicht empfohlen1
Azure Cosmos DB Nicht verwendete SDK-Typen2 Allgemein verfügbar SDK-Typen nicht empfohlen1
Azure-Tabellen Kein Trigger vorhanden Allgemein verfügbar SDK-Typen nicht empfohlen1
Azure Event Grid Allgemein verfügbar Keine Eingabebindung vorhanden SDK-Typen nicht empfohlen1

1 Bei Ausgabeszenarien, in denen Sie einen SDK-Typ verwenden würden, sollten Sie SDK-Clients direkt erstellen und mit ihnen arbeiten, anstatt eine Ausgabebindung zu verwenden. Ein Beispiel für die Abhängigkeitsinjektion finden Sie unter Registrieren von Azure-Clients.

2 Der Cosmos DB-Trigger verwendet den Azure Cosmos DB-Änderungsfeed und macht Änderungsfeedelemente als von JSON serialisierbare Typen verfügbar. Für dieses Szenario ist das Fehlen von SDK-Typen beabsichtigt.

Hinweis

Bei Verwendung von Bindungsausdrücken, die auf Triggerdaten basieren, können SDK-Typen für den Trigger selbst nicht verwendet werden.

HTTP-Trigger

HTTP-Trigger ermöglichen das Aufrufen einer Funktion durch eine HTTP-Anforderung. Es gibt zwei verschiedene Ansätze, die verwendet werden können:

  • Ein ASP.NET Core-Integrationsmodell, das Konzepte verwendet, die ASP.NET Core-Entwickler*innen vertraut sind
  • Ein integriertes Modell, das keine zusätzlichen Abhängigkeiten erfordert und benutzerdefinierte Typen für HTTP-Anforderungen und -Antworten verwendet. Dieser Ansatz ist weiterhin verfügbar, um Abwärtskompatibilität mit früheren isolierten .NET-Worker-Apps zu gewährleisten.

ASP.NET Core-Integration

In diesem Abschnitt wird gezeigt, wie Sie mit den zugrunde liegenden HTTP-Anforderungs- und Antwortobjekten mithilfe von Typen aus ASP.NET Core wie HttpRequest, HttpResponse und IActionResult arbeiten. Dieses Modell ist für Apps, die auf .NET Framework ausgerichtet sind, nicht verfügbar. Stattdessen muss das integrierte Modell verwendet werden.

Hinweis

Nicht alle Features von ASP.NET Core werden von diesem Modell verfügbar gemacht. Insbesondere sind die ASP.NET Core-Middlewarepipeline und Routingfunktionen nicht verfügbar. Für die ASP.NET Core-Integration müssen aktualisierte Pakete verwendet werden.

So aktivieren Sie die ASP.NET Core-Integration für HTTP

  1. Fügen Sie in Ihrem Projekt einen Verweis auf das Paket Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore (ab Version 1.0.0) hinzu.

  2. Aktualisieren Sie Ihr Projekt so, dass die folgenden spezifischen Paketversionen verwendet werden:

  3. Aktualisieren Sie in Ihrer Datei Program.cs die Konfiguration des Host-Generators, um ConfigureFunctionsWebApplication() aufzurufen. Damit wird ConfigureFunctionsWorkerDefaults() ersetzt, wenn Sie diese Methode anderweitig verwenden. Das folgende Beispiel zeigt ein minimales Setup ohne weitere Anpassungen:

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Hosting;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .Build();
    
    host.Run();
    
  4. Aktualisieren Sie ggf. vorhandene Funktionen mit HTTP-Trigger für die Verwendung der ASP.NET Core-Typen. Im folgenden Beispiel werden die standardmäßige HTTP-Anforderung (HttpRequest) sowie IActionResult für eine einfache Funktion vom Typ „hello, world“ verwendet:

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

JSON-Serialisierung mit ASP.NET Core-Integration

ASP.NET Core verfügt über eine eigene Serialisierungsebene und ist nicht von Anpassung der allgemeinen Serialisierungskonfigurationbetroffen. Um das für Ihre HTTP-Trigger verwendete Serialisierungsverhalten anzupassen, müssen Sie einen .AddMvc()-Aufruf als Teil der Dienstregistrierung einschließen. Die zurückgegebenen IMvcBuilder können verwendet werden, um die JSON-Serialisierungseinstellungen von ASP.NET Core zu ändern. Das folgende Beispiel zeigt, wie Sie JSON.NET (Newtonsoft.Json) für die Serialisierung mit diesem Ansatz konfigurieren:

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

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddMvc().AddNewtonsoftJson();
    })
    .Build();
host.Run();

Integriertes HTTP-Modell

HTTP-Trigger übersetzen eingehende HTTP-Anforderungsnachrichten in ein HttpRequestData-Objekt, das an die Funktion übergeben wird. Dieses Objekt liefert die Anforderungsdaten wie Headers, Cookies, Identities, URL und optional eine Nachricht Body. Dieses Objekt ist eine Darstellung der HTTP-Anforderung, aber nicht direkt mit dem zugrunde liegenden HTTP-Listener oder der empfangenen Nachricht verbunden.

Entsprechend gibt die Funktion ein HttpResponseData-Objekt zurück, das die Daten zur Erstellung der HTTP-Antwort enthält, zum Beispiel Nachricht StatusCode, Headers, und optional Nachricht Body.

Das folgende Beispiel veranschaulicht die Verwendung von HttpRequestData und 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;
}

Logging

Sie können Protokolle mithilfe einer ILogger<T>- oder ILogger-Instanz schreiben. Die Protokollierung kann durch Abhängigkeitsinjektion eines ILogger<T>- oder ILoggerFactory-Elements abgerufen werden:

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}");
    }

}

Die Protokollierung kann auch aus einem FunctionContext-Objekt abgerufen werden, das an Ihre Funktion übergeben wird. Rufen Sie die Methode GetLogger<T> oder die Methode GetLoggerauf, und übergeben Sie dabei einen Zeichenfolgenwert, der den Namen der Kategorie darstellt, in welche die Protokolle geschrieben werden. Die Kategorie ist normalerweise der Name der spezifischen Funktion, aus der die Protokolle geschrieben werden. Weitere Informationen zu Kategorien finden Sie im Artikel zur Überwachung.

Verwenden Sie die Methoden von ILogger<T> und ILogger, um verschiedene Protokolliergrade wie LogWarning oder LogError zu schreiben. Weitere Informationen zu den Protokolliergraden finden Sie im Artikel zur Überwachung. Sie können die Protokolliergrade für Ihrem Code hinzugefügte Komponenten anpassen, indem Sie Filter registrieren:

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

Im Rahmen der Konfiguration Ihrer App in Program.cs können Sie auch definieren, auf welche Weise Fehler in Ihren Protokollen vermerkt werden. Das Standardverhalten hängt vom Typ des verwendeten Generators ab.

Bei Verwendung von HostBuilder können standardmäßig Ausnahmen, die von Ihrem Code ausgelöst werden, von RpcException umschlossen werden. Um diese gesonderte Ebene zu entfernen, legen Sie beim Konfigurieren des Generators die EnableUserCodeException-Eigenschaft auf „true“ fest:

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

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

host.Run();

Application Insights

Sie können Ihre Anwendung mit isolierten Prozessen so konfigurieren, dass Protokolle direkt an Application Insights ausgegeben werden. Dieses Verhalten ersetzt das Standardverhalten, die Weiterleitung von Protokollen durch den Host. Sofern Sie nicht .NET Aspire verwenden, wird das Konfigurieren einer direkten Integration von Application Insights empfohlen, da sie dadurch die Kontrolle darüber erhalten, wie diese Protokolle ausgegeben werden.

Die Integration von Application Insights ist nicht in allen Setup-Umgebungen standardmäßig aktiviert. Einige Vorlagen erstellen Functions-Projekte mit den erforderlichen Paketen und auskommentiertem Startcode. Wenn Sie Application Insights integrieren möchten, können Sie die Auskommentierung dieser Zeilen in der Program.cs- und .csproj-Datei des Projekts aufheben. Im restlichen Abschnitt der Anleitung wird außerdem beschrieben, wie Sie die Integration aktivieren.

Wenn Ihr Projekt Teil einer .NET Aspire-Orchestrierung ist, wird stattdessen OpenTelemetry für die Überwachung verwendet. In .NET Aspire-Projekten sollten Sie keine direkte Application Insights-Integration aktivieren. Konfigurieren Sie stattdessen den Azure Monitor OpenTelemetry-Exporter als Teil der Dienststandardeinstellungen des Projekts. Wenn Ihr Functions-Projekt eine Application Insights-Integration in einem .NET Aspire-Kontext verwendet, tritt beim Starten der Anwendung ein Fehler auf.

Installieren von Paketen

Um Protokolle direkt über Ihren Code in Application Insights zu schreiben, können Sie Verweise auf die folgenden Pakete in Ihrem Projekt hinzufügen:

Sie können die folgenden Befehle ausführen, um diese Verweise Ihrem Projekt hinzuzufügen:

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

Konfigurieren des Starts

Wenn die Pakete installiert sind, müssen Sie AddApplicationInsightsTelemetryWorkerService() und ConfigureFunctionsApplicationInsights() während der Dienstkonfiguration in der Datei Program.cs aufrufen, wie im folgenden Beispiel gezeigt:

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

Der Aufruf von ConfigureFunctionsApplicationInsights() fügt ein ITelemetryModule hinzu, das an einer von Functions definierten ActivitySource lauscht. Dadurch werden die Abhängigkeitstelemetriedaten erstellt, die zur Unterstützung der verteilten Ablaufverfolgung erforderlich sind. Informationen zu AddApplicationInsightsTelemetryWorkerService() und dessen Verwendung finden Sie unter Application Insights für Workerdienstanwendungen.

Verwalten von Protokollebenen

Wichtig

Der Functions-Host und der Worker des isolierten Prozesses verfügen über unterschiedliche Konfigurationen für Protokolliergrade usw. Eine Application Insights-Konfiguration in host.json wirkt sich nicht auf die Protokollierung durch den Worker aus, ebenso wirkt sich eine Konfiguration in Ihrem Workercode nicht auf die Protokollierung durch den Host aus. Wenn Ihr Szenario eine Anpassung auf beiden Ebenen erfordert, müssen Sie an beiden Stellen Änderungen vornehmen.

Der Rest der Anwendung funktioniert weiterhin mit ILogger und ILogger<T>. Standardmäßig fügt das Application Insights SDK jedoch einen Protokollierungsfilter hinzu, der die Protokollierung anweist, nur Warnungen und schwerwiegendere Protokolliergrade zu erfassen. Wenn Sie dieses Verhalten deaktivieren möchten, entfernen Sie die Filterregel, die zur Dienstkonfiguration gehört:

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

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

Leistungsoptimierungen

In diesem Abschnitt werden Optionen beschrieben, die Sie zum Verbessern der Leistung beim Kaltstart aktivieren können.

Im Allgemeinen sollte Ihre App die neuesten Versionen ihrer Kernabhängigkeiten verwenden. Ihr Projekt sollte mindestens wie folgt aktualisiert werden:

  1. Führen Sie für Microsoft.Azure.Functions.Worker mindestens ein Upgrade auf die Version 1.19.0 durch.
  2. Führen Sie für Microsoft.Azure.Functions.Worker.Sdk mindestens ein Upgrade auf die Version 1.16.4 durch.
  3. Fügen Sie einen Frameworkverweis auf Microsoft.AspNetCore.App hinzu, es sei denn, Ihre App ist auf .NET Framework ausgerichtet.

Der folgende Codeschnipsel zeigt diese Konfiguration im Kontext einer Projektdatei:

  <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>

Platzhalter

Platzhalter sind eine Plattformfunktion, die den Kaltstart für Apps verbessert, die auf .NET 6 oder auf eine höhere Version ausgerichtet sind. Um diese Optimierung verwenden zu können, müssen mithilfe der folgenden Schritte explizit Platzhalter aktiviert werden:

  1. Aktualisieren Sie die Projektkonfiguration so, dass sie die neuesten Abhängigkeitsversionen verwendet, wie im vorherigen Abschnitt beschrieben.

  2. Legen Sie die Anwendungseinstellung WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED auf 1 fest. Hierzu können Sie den folgenden Befehl vom Typ az functionapp config appsettings set verwenden:

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

    Ersetzen Sie in diesem Beispiel <groupName> durch den Namen der Ressourcengruppe und <appName> durch den Namen Ihrer Funktions-App.

  3. Achten Sie darauf, dass die Eigenschaft netFrameworkVersion der Funktions-App dem Zielframework Ihres Projekts entspricht (.NET 6 oder höher). Hierzu können Sie den folgenden Befehl vom Typ az functionapp config set verwenden:

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

    Ersetzen Sie in diesem Beispiel auch <framework> durch die entsprechende Versionszeichenfolge für Ihre .NET-Zielversion (beispielsweise v8.0).

  4. Stellen Sie sicher, dass Ihre Funktions-App für die Verwendung eines 64-Bit-Prozesses konfiguriert ist. Hierzu können Sie den folgenden Befehl vom Typ az functionapp config set verwenden:

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

Wichtig

Wenn Sie WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED auf 1 festlegen, müssen alle anderen Funktions-App-Konfigurationen ordnungsgemäß festgelegt werden. Andernfalls kann die Funktions-App möglicherweise nicht gestartet werden.

Optimierter Executor

Der Funktions-Executor ist eine Komponente der Plattform, die die Ausführung von Aufrufen auslöst. Ab der Version 1.16.2 des SDK ist standardmäßig eine optimierte Version dieser Komponente aktiviert. Es ist keine weitere Konfiguration erforderlich.

ReadyToRun

Sie können ihre Funktions-App als ReadyToRun-Binärdateien kompilieren. ReadyToRun ist eine Form der Vorabkompilierung, die zur Optimierung der Startleistung beitragen und die Auswirkungen von Kaltstarts bei Ausführung in einem Verbrauchstarif reduzieren kann. ReadyToRun ist in .NET 6 und höher verfügbar und setzt mindestens Version 4.0 der Azure Functions-Runtime voraus.

ReadyToRun erfordert, dass Sie das Projekt für die Runtimearchitektur der Hosting-App erstellen. Wenn diese nicht aufeinander abgestimmt sind, tritt bei der App beim Start ein Fehler auf. Wählen Sie Ihren Runtimebezeichner aus der folgenden Tabelle aus:

Betriebssystem Die App ist 32-Bi1 Runtimebezeichner
Windows True win-x86
Windows False win-x64
Linux True N/V (nicht unterstützt)
Linux False linux-x64

1 Einige andere Leistungsoptimierungen sind 64-Bit-Apps vorbehalten.

Um zu überprüfen, ob Ihre Windows-App eine 32-Bit- oder 64-Bit-App ist, können Sie den folgenden CLI-Befehl ausführen. Ersetzen Sie dabei <group_name> durch den Namen Ihrer Ressourcengruppe und <app_name> durch den Namen Ihrer Anwendung. Die Ausgabe „true“ gibt an, dass die App eine 32-Bit-App ist, und „false“ gibt an, dass es sich um eine 64-Bit-App handelt.

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

Sie können Ihre Anwendung mit dem folgenden Befehl mit den gleichen Ersetzungen in 64-Bit ändern:

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

Um Ihr Projekt als „ReadyToRun“ zu kompilieren, aktualisieren Sie die Projektdatei, indem Sie die Elemente <PublishReadyToRun> und <RuntimeIdentifier> hinzufügen. Das folgende Beispiel zeigt eine Konfiguration für die Veröffentlichung in einer Windows-64-Bit-Funktions-App.

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

Wenn Sie den Runtimebezeichner (<RuntimeIdentifier>) nicht als Teil der Projektdatei festlegen möchten, können Sie ihn auch als Teil des Veröffentlichungsvorgangs selbst konfigurieren. Bei einer Windows 64-Bit-Funktions-App lautet der .NET-CLI-Befehl beispielsweise wie folgt:

dotnet publish --runtime win-x64

In Visual Studio muss die Option Zielruntime im Veröffentlichungsprofil auf den korrekten Runtimebezeichner festgelegt werden. Bei Verwendung des Standardwerts Portierbar wird ReadyToRun nicht verwendet.

Bereitstellen in Azure Functions

Bei Ausführung Ihres Funktionscodeprojekt in Azure muss es entweder in einer Funktions-App oder in einem Linux-Container ausgeführt werden. Die Funktions-App und andere erforderliche Azure-Ressourcen müssen vorhanden sein, bevor Sie Ihren Code bereitstellen.

Sie können Ihre Funktions-App auch in einem Linux-Container bereitstellen. Weitere Informationen finden Sie unter Arbeiten mit Containern und Azure Functions.

Erstellen von Azure-Ressourcen

Sie können Ihre Funktions-App und andere erforderliche Ressourcen in Azure mithilfe einer der folgenden Methoden erstellen:

  • Visual Studio: Visual Studio kann während des Codeveröffentlichungsprozesses Ressourcen für Sie erstellen.
  • Visual Studio Code: Visual Studio Code kann eine Verbindung mit Ihrem Abonnement herstellen, die von Ihrer App benötigten Ressourcen erstellen und dann Ihren Code veröffentlichen.
  • Azure CLI: Sie können die Azure CLI verwenden, um die erforderlichen Ressourcen in Azure zu erstellen.
  • Azure PowerShell: Sie können Azure PowerShell verwenden, um die erforderlichen Ressourcen in Azure zu erstellen.
  • Bereitstellungsvorlagen: Sie können ARM-Vorlagen und Bicep-Dateien verwenden, um die Bereitstellung der erforderlichen Ressourcen in Azure zu automatisieren. Achten Sie darauf, dass Ihre Vorlage alle erforderlichen Einstellungen enthält.
  • Azure-Portal: Sie können die erforderlichen Ressourcen im Azure-Portal erstellen.

Veröffentlichen der Anwendung

Nach Erstellung Ihrer Funktions-App und anderer erforderlicher Ressourcen in Azure können Sie das Codeprojekt mithilfe einer der folgenden Methoden für Azure bereitstellen:

Weitere Informationen finden Sie unter Bereitstellungstechnologien in Azure Functions.

Payload der Bereitstellung

Viele Bereitstellungsmethoden verwenden ein ZIP-Archiv. Wenn Sie das ZIP-Archiv selbst erstellen, muss es die in diesem Abschnitt beschriebene Struktur aufweisen. Andernfalls treten beim Starten der App möglicherweise Fehler auf.

Die Payload der Bereitstellung sollte mit der Ausgabe eines dotnet publish-Befehls übereinstimmen, jedoch ohne den einschließenden übergeordneten Ordner. Das ZIP-Archiv sollte aus den folgenden Dateien erstellt werden:

  • .azurefunctions/
  • extensions.json
  • functions.metadata
  • host.json
  • worker.config.json
  • Ausführbare Datei Ihres Projekts (eine Konsolen-App)
  • Andere unterstützende Dateien und Verzeichnisse in Peer-Konfiguration für diese ausführbare Datei

Diese Dateien werden vom Buildprozess generiert. Sie sollten nicht direkt bearbeitet werden.

Beim Vorbereiten eines ZIP-Archivs für die Bereitstellung sollten Sie nur den Inhalt des Ausgabeverzeichnisses und nicht das einschließende Verzeichnis selbst komprimieren. Wenn das Archiv in das aktuelle Arbeitsverzeichnis extrahiert wird, müssen die oben aufgeführten Dateien sofort sichtbar sein.

Anforderungen für die Bereitstellung

Je nach Betriebssystem müssen gewisse Anforderungen erfüllt werden, um .NET-Funktionen im isolierten Workermodell in Azure ausführen zu können:

Wenn Sie Ihre Funktions-App in Azure mithilfe der Methoden aus dem vorherigen Abschnitt erstellen, werden diese erforderlichen Einstellungen für Sie hinzugefügt. Wenn Sie diese Ressourcen mithilfe von ARM-Vorlagen oder Bicep-Dateien für die Automatisierung erstellen, müssen Sie sie in der Vorlage festlegen.

.NET Aspire (Vorschau)

.NET Aspire ist ein Stapel, der einen festen Ansatz verfolgt und die Entwicklung verteilter Anwendungen in der Cloud vereinfacht. Sie können isolierte .NET 8- und .NET 9-Workermodellprojekte in Aspire 9.0-Orchestrierungen mithilfe der Vorschauunterstützung eintragen. Der Abschnitt beschreibt die wichtigsten Anforderungen für die Eintragung.

Für diese Integration ist ein spezifisches Setup erforderlich:

  • Verwenden Sie Aspire 9.0 oder höher und das .NET 9 SDK. Aspire 9.0 unterstützt die .NET 8- und .NET 9-Frameworks.
  • Wenn Sie Visual Studio verwenden, aktualisieren Sie auf Version 17.12 oder höher. Sie müssen auch über die neueste Version der Functions-Tools für Visual Studio verfügen. Um nach Updates zu suchen, navigieren Sie zu Tools>Optionen, und wählen Sie unter Projekte und Projektmappen die Option Azure Functions aus. Wählen Sie Nach Updates suchen aus, und installieren Sie Updates, wenn Sie dazu aufgefordert werden.
  • Im Aspire-App-Hostprojekt ist Folgendes zu tun:
    • Sie müssen auf Aspire.Hosting.Azure.Functionsverweisen.
    • Sie müssen über einen Projektverweis auf Ihr Functions-Projekt verfügen.
    • Sie müssen auch in der Program.cs des App-Hosts das Projekt einschließen, indem Sie AddAzureFunctionsProject<TProject>() in Ihrem IDistributedApplicationBuilder aufrufen. Diese Methode wird anstelle der AddProject<TProject>()-Methode verwendet, die Sie für andere Projekttypen verwenden. Wenn Sie nur AddProject<TProject>() verwenden, wird das Functions-Projekt nicht ordnungsgemäß gestartet.
  • Im Functions-Project ist Folgendes zu tun:
    • Sie müssen auf die 2.x-Versionen vonMicrosoft.Azure.Functions.Worker and Microsoft.Azure.Functions.Worker.Sdk verweisen. Sie müssen außerdem sämtliche Verweise auf Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore auf die 2.x-Version aktualisieren.
    • Ihre Program.cs sollte die IHostApplicationBuilder-Version des Hostinstanzstartsverwenden.
    • Wenn Sie die Standardeinstellungen Ihres Aspire-Diensts verwenden möchten, sollten Sie einen Projektverweis auf die Dienststandardeinstellungen des Projekts einfügen. Bevor Sie Ihren IHostApplicationBuilder in der Program.cserstellen, sollten Sie auch einen Aufruf der builder.AddServiceDefaults()einschließen.
    • Sie dürfen die Konfiguration in local.settings.json, abgesehen von der FUNCTIONS_WORKER_RUNTIME-Einstellung, die „dotnet-isoliert“ bleiben soll, nicht beibehalten. Eine andere Konfiguration muss über das App-Hostprojekt festgelegt werden.
    • Sie müssen alle direkten Application Insights-Integrationen entfernen. Die Überwachung in Aspire wird stattdessen über die OpenTelemetry-Unterstützung abgewickelt.

Das folgende Beispiel zeigt das Minimum für eine Program.cs für ein App-Hostprojekt:

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");

builder.Build().Run();

Das folgende Beispiel zeigt das Minimum für eine Program.cs für ein App-Hostprojekt in Aspire:

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

var builder = FunctionsApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.ConfigureFunctionsWebApplication();

builder.Build().Run();

Die Beispiele umfassen nicht die standardmäßige Application Insights-Konfiguration, die in vielen anderen Program.cs-Beispielen in diesem Artikel dargestellt wird. Stattdessen wird die OpenTelemetry-Integration von Aspire über den builder.AddServiceDefaults()-Aufruf konfiguriert.

Überlegungen und bewährte Methoden für die Integration von .NET Aspire

Berücksichtigen Sie bei Ihrer Bewertung von .NET Aspire mit Azure Functions die folgenden Punkte:

  • Die Unterstützung für Azure Functions mit .NET Aspire befindet sich derzeit in der Vorschau. Während des Vorschauzeitraums werden Functions-Projekte als Azure-Container Apps-Ressourcen ohne ereignisgesteuerte Skalierung bereitgestellt, wenn Sie die Aspire-Lösung in Azure veröffentlichen. Die Unterstützung von Azure Functions ist für Apps, die in diesem Modus bereitgestellt werden, nicht verfügbar.
  • Trigger- und Bindungskonfiguration über Aspire ist derzeit auf bestimmte Integrationen beschränkt. Details finden Sie unter Verbindungskonfiguration mit Aspire.
  • Ihre Program.cs sollte die IHostApplicationBuilder-Version des Hostinstanzstartsverwenden. Auf diese Weise können Sie builder.AddServiceDefaults() aufrufen, um die Standardeinstellungen des .NET Aspire-Diensts zu Ihrem Functions-Projekt hinzuzufügen.
  • Aspire verwendet zur Überwachung OpenTelemetry. Sie können Aspire so konfigurieren, dass Telemetrie mithilfe der Dienststandardeinstellungen des Projekts nach Azure Monitor exportiert wird. In vielen anderen Azure Functions-Kontexten können Sie die direkte Integration in Application Insights einschließen, indem Sie den Telemetrie-Workerdienst registrieren. Dies wird in Aspire nicht empfohlen und kann bei der Version 2.22.0 von Microsoft.ApplicationInsights.WorkerService zu Laufzeitfehlern führen. Wenn Sie Aspire verwenden, müssen Sie alle direkten Application Insights-Integrationen aus Ihrem Functions-Projekt entfernen.
  • Bei Funktionen-Projekten, die in eine Aspire-Orchestrierung eingetragen wurden, sollte der Großteil der Anwendungskonfiguration aus dem Aspire-App-Hostprojekt stammen. In der Regel sollten Sie abgesehen von der FUNCTIONS_WORKER_RUNTIME-Einstellung das Festlegen von Einstellungen in local.settings.json vermeiden. Wenn dieselbe Umgebungsvariable durch local.settings.json und Aspire festgelegt wird, verwendet das System die Aspire-Version.
  • Konfigurieren Sie den Speicher-Emulator nicht für Verbindungen in local.settings.json. Viele Functions-Startvorlagen enthalten den Emulator als Standard für AzureWebJobsStorage. Die Konfiguration des Emulators kann jedoch manche IDEs auffordern, eine Version des Emulators zu starten, die mit der von Aspire verwendeten Version in Konflikt stehen kann.

Verbindungskonfiguration in Aspire

Azure Functions erfordert für mehrere seiner wichtigsten Funktionalitäten eine Hostspeicherverbindung (AzureWebJobsStorage). Wenn Sie AddAzureFunctionsProject<TProject>() in Ihrem App-Hostprojekt aufrufen, wird eine standardmäßige AzureWebJobsStorage-Verbindung erstellt und für das Functions-Projekt bereitgestellt. Diese Standardverbindung verwendet den Speicheremulator für die lokale Entwicklungsaufsführungen und stellt bei ihrer Bereitstellung automatisch ein Speicherkonto bereit. Für zusätzliche Steuerungsmöglichkeiten können Sie diese Verbindung ersetzen, indem Sie in der Functions-Projektressource .WithHostStorage() aufrufen.

Im folgenden Beispiel wird das Minimum für eine Program.cs für ein App-Hostprojekt gezeigt, das den Hostspeicher ersetzt:

var builder = DistributedApplication.CreateBuilder(args);

var myHostStorage = builder.AddAzureStorage("myHostStorage");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithHostStorage(myHostStorage);

builder.Build().Run();

Hinweis

Wenn Aspire den Hostspeicher im Veröffentlichungsmodus bereitstellt, erstellt er standardmäßig Rollenzuweisungen für folgende Rollen: Mitwirkender an Speicherkonten, Mitwirkender an Storage-Blobaten, Mitwirkender an Storage-Warteschlangendatenund Mitwirkender an Storage-Tabellendaten.

Ihre Trigger und Bindungen verweisen mithilfe des Namens auf Verbindungen. Einige Aspire-Integrationen sind in der Lage, diese über einen Aufruf von WithReference() für die Projektressource bereitzustellen:

Aspire-Integration Hinweise
Azure-Blobs Wenn Aspire den Hostspeicher bereitstellt, erstellt er standardmäßig Rollenzuweisungen für folgende Rollen: Mitwirkender an Storage-Blobaten, Mitwirkender an Storage-Warteschlangendaten und Mitwirkender an Storage-Tabellendaten.
Azure-Warteschlangen Wenn Aspire den Hostspeicher bereitstellt, erstellt er standardmäßig Rollenzuweisungen für folgende Rollen: Mitwirkender an Storage-Blobaten, Mitwirkender an Storage-Warteschlangendaten und Mitwirkender an Storage-Tabellendaten.
Azure Event Hubs Wenn Aspire die Ressource bereitstellt, wird standardmäßig eine Rollenzuweisung mithilfe der Rolle Azure Event Hubs-Datenbesitzer erstellt.
Azure Service Bus Wenn Aspire die Ressource bereitstellt, wird standardmäßig eine Rollenzuweisung mithilfe der Rolle Azure Service Bus-Datenbesitzer erstellt.

Im folgenden Beispiel wird das Minimum für eine Program.cs für ein App-Hostprojekt gezeigt, das einen Warteschlangentrigger konfiguriert. In diesem Beispiel wurde für den entsprechende Warteschlangentrigger die Connection-Eigenschaft auf „MyQueueTriggerConnection“ festgelegt.

var builder = DistributedApplication.CreateBuilder(args);

var myAppStorage = builder.AddAzureStorage("myAppStorage").RunAsEmulator();
var queues = myAppStorage.AddQueues("queues");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithReference(queues, "MyQueueTriggerConnection");

builder.Build().Run();

Für andere Integrationen legen Aufrufe von WithReference die Konfiguration auf eine andere Weise fest und stellen sie Aspire-Clientintegrationen zur Verfügung, allerdings nicht für Trigger und Bindungen. Für diese Integrationen müssen Sie WithEnvironment() aufrufen, um die Verbindungsinformationen zum Auflösen des Triggers oder der Bindung zu übergeben. Das folgende Beispiel zeigt, wie die Umgebungsvariable „MyBindingConnection“ für eine Ressource festgelegt wird, die einen Verbindungszeichenfolgenausdruck verfügbar macht:

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);

Sie können sowohl WithReference() als auch WithEnvironment() konfigurieren, wenn Sie möchten, dass eine Verbindung sowohl von Aspire-Clientintegrationen als auch vom Trigger- und Bindungssystem verwendet wird.

Bei einigen Ressourcen kann sich die Struktur einer Verbindung zwischen der lokalen Ausführung und der Veröffentlichung in Azure möglicherweise unterscheiden. Im vorherigen Beispiel könnte otherIntegration eine Ressource sein, die als Emulator ausgeführt wird, sodass ConnectionStringExpression eine Emulatorverbindungszeichenfolge zurückgeben würde. Wenn die Ressource veröffentlicht wird, kann Aspire jedoch eine identitätsbasierte Verbindung einrichten, und ConnectionStringExpression würde den URI des Diensts zurückgeben. In diesem Fall müssen Sie möglicherweise einen anderen Umgebungsvariablennamen angeben, um identitätsbasierte Verbindungen für Azure Functions einzurichten. Im folgenden Beispiel wird builder.ExecutionContext.IsPublishMode verwendet, um das erforderliche Suffix bedingt hinzuzufügen:

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);

Je nach Szenario müssen Sie möglicherweise auch die Berechtigungen anpassen, die für eine identitätsbasierte Verbindung zugewiesen werden. Sie können die ConfigureConstruct<T>()-Methode verwenden, um anzupassen, wie Aspire die Infrastruktur konfiguriert, wenn es Ihr Projekt veröffentlicht.

Weitere Informationen zu den unterstützten Verbindungsformaten und den erforderlichen Berechtigungen für diese Formate finden Sie auf den Referenzseiten der einzelnen Bindungen.

Debuggen

Bei lokaler Ausführung mit Visual Studio oder Visual Studio Code können Sie Ihr Projekt mit isoliertem .NET-Worker wie gewohnt debuggen. Es gibt jedoch zwei Debugszenarien, die nicht wie erwartet funktionieren.

Remotedebuggen mit Visual Studio

Da Ihre App mit isoliertem Workerprozess außerhalb der Functions-Runtime ausgeführt wird, müssen Sie den Remotedebugger an einen separaten Prozess anfügen. Weitere Informationen zum Debuggen mithilfe von Visual Studio finden Sie unter Remotedebugging.

Debuggen für .NET Framework

Wenn Ihr isoliertes Projekt für .NET Framework 4.8 konzipiert ist, müssen Sie manuelle Schritte zur Aktivierung des Debuggen vornehmen. Diese Schritte sind nicht erforderlich, wenn Sie ein anderes Zielframework verwenden.

Ihre App sollte mit einem Aufruf von FunctionsDebugger.Enable(); als erster Vorgang beginnen. Dieser erfolgt in der Main()-Methode, bevor Sie einen HostBuilder initialisieren. Die Datei Program.cs sollte in etwa wie folgt aussehen:

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

Nun müssen Sie das Anfügen an den Prozess mithilfe eines .NET Framework-Debuggers manuell ausführen. Visual Studio führt diesen Schritt nicht automatisch für .NET Framework-Apps in isolierten Workerprozessen aus, und der Vorgang „Debuggen starten“ sollte vermieden werden.

Führen Sie in Ihrem Projektverzeichnis (oder dem Buildausgabeverzeichnis) Folgendes aus:

func host start --dotnet-isolated-debug

Dadurch wird Ihr Worker gestartet, und der Prozess wird mit der folgenden Meldung beendet:

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

Dabei ist <process id> die ID für Ihren Workerprozess. Sie können jetzt Visual Studio zum manuellen Anfügen an den Prozess verwenden. Anweisungen zu diesem Vorgang finden Sie unter Anfügen an einen ausgeführten Prozess.

Nachdem der Debugger angefügt wurde, wird die Prozessausführung fortgesetzt, und Sie können mit dem Debuggen beginnen.

.NET-Vorschauversionen

Vor einer allgemein verfügbaren Version kann eine .NET-Version mit dem Status Vorschauversion oder Go-live veröffentlicht werden. Einzelheiten zu diesen Zuständen finden Sie in der offiziellen .NET-Supportrichtlinie .

Es kann zwar möglich sein, eine bestimmte Version aus einem lokalen Functions-Projekt als Ziel zu verwenden, aber Funktions-Apps, die in Azure gehostet werden, sind möglicherweise nicht über diese Version verfügbar. Azure Functions kann nur mit Releases vom Typ „Vorschauversion“ oder „Go-live“ verwendet werden, die in diesem Abschnitt angegeben sind.

Azure Functions funktioniert derzeit mit keinen .NET-Releases vom Typ „Vorschauversion“ oder „Go-live“. Eine Liste der allgemein verfügbaren Versionen, die Sie verwenden können, finden Sie unter unterstützten Versionen .

Verwenden eines .NET-Vorschau-SDK

Um Azure Functions mit einer .NET-Vorschauversion zu verwenden, müssen Sie Ihr Projekt wie folgt aktualisieren:

  1. Installieren der relevanten .NET SDK-Version in Ihrer Entwicklungsumgebung
  2. Ändern der TargetFramework-Einstellung in Ihrer .csproj-Datei

Bei der Bereitstellung in einer Funktions-App in Azure müssen Sie auch sicherstellen, dass das Framework für die App verfügbar gemacht wird. Während des Vorschauzeitraums werden die neuen Vorschauversion in einigen Tools und Umgebungen möglicherweise nicht als Option angezeigt. Wenn die im Azure-Portal enthaltene Vorschauversion nicht angezeigt wird, können Sie beispielsweise die REST-API, Bicep-Vorlagen oder die Azure-Befehlszeilenschnittstelle verwenden, um die Version manuell zu konfigurieren.

Verwenden Sie für Apps, die unter Windows gehostet werden, den folgenden Azure CLI-Befehl. Ersetzen Sie <groupName> durch den Namen der Ressourcengruppe, und ersetzen Sie <appName> durch den Namen Ihrer Funktions-App. Ersetzen Sie <framework> durch die entsprechende Versionszeichenfolge (z. B. v8.0).

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

Überlegungen zur Verwendung von .NET-Vorschauversionen

Berücksichtigen Sie Folgendes, wenn Sie Functions mit Vorschauversionen von .NET verwenden:

  • Wenn Sie Ihre Funktionen in Visual Studio erstellen, müssen Sie die Version Visual Studio Preview verwenden, die das Erstellen von Azure Functions-Projekten mit .NET-Vorschau-SDKs unterstützt.

  • Achten Sie darauf, dass Sie über die neuesten Functions-Tools und -Vorlagen verfügen. So aktualisieren Sie Ihre Tools

    1. Navigieren Sie zu Tools>Optionen, und wählen Sie unter Projekte und Projektmappen die Option Azure Functions aus.
    2. Wählen Sie Nach Updates suchen aus, und installieren Sie Updates, wenn Sie dazu aufgefordert werden.
  • Während eines Vorschauzeitraums verfügt Ihre Entwicklungsumgebung möglicherweise über eine neuere .NET-Vorschauversion als der gehostete Dienst. Dies kann dazu führen, dass Ihre Funktions-App nicht funktioniert, wenn sie bereitgestellt wird. Um dieses Problem zu beheben, können Sie in global.json die zu verwendende SDK-Version angeben.

    1. Führen Sie den Befehl dotnet --list-sdks aus, und notieren Sie sich die Vorschauversion, die Sie derzeit bei der lokalen Entwicklung verwenden.
    2. Führen Sie den Befehl dotnet new globaljson --sdk-version <SDK_VERSION> --force aus. <SDK_VERSION> ist hierbei die lokal verwendete Version. dotnet new globaljson --sdk-version dotnet-sdk-8.0.100-preview.7.23376.3 --force führt beispielsweise dazu, dass das System beim Erstellen Ihres Projekts das .NET 8 Preview 7 SDK verwendet.

Hinweis

Aufgrund des Just-In-Time-Ladens von Vorschauframeworks können die Kaltstartzeiten bei Funktions-Apps, die unter Windows ausgeführt werden, im Vergleich zu früheren allgemein verfügbaren Versionen länger sein.

Nächste Schritte