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 Prozessinternes Modell5
Functions 4.x .NET 8.0
.NET 7.01
.NET 6.02
.NET Framework 4.83
.NET 6.02
Functions 1.x4 .NET Framework 4.8

1 .NET 7 wird ab dem 14. Mai 2024 nicht mehr offiziell unterstützt.
2 .NET 6 wird ab dem 12. November 2024 nicht mehr offiziell unterstützt.
3 Für den Buildprozess ist auch das .NET SDK erforderlich. 4 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.
5 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:

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 isolierte .NET-Funktionen verwenden, haben Sie Zugriff auf den Start Ihrer Funktions-App, die sich üblicherweise 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 HostBuilderaufrufen, 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

Die Methode ConfigureFunctionsWorkerDefaults wird verwendet, um die Einstellungen hinzuzufügen, die für die Ausführung der Funktions-App in einem isolierten Workerprozess erforderlich sind. Hierzu zählen 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 Konfigurationen, die für ihre Funktions-APP erforderlich sind, können Sie die MethodeConfigureAppConfiguration mindestens einmal für HostBuilder aufrufen. Weitere Informationen zur App-Konfiguration finden Sie unter Konfiguration in ASP.NET Core.

Diese Konfigurationen gelten für die in einem separaten Prozess ausgeführte Funktions-App. 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

Die Abhängigkeitsinjektion wird im Vergleich zu .NET-In-Process-Funktionen vereinfacht, was die Erstellung einer Startklasse zum Registrieren von Diensten erfordert.

Bei einer .NET-App mit isoliertem Prozess verwenden Sie die Standardmethode zum Aufrufen von ConfigureServices im Hostgenerator und 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.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();

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

Die isolierte .NET-Unterstützung 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. Das folgende Beispiel zeigt diese Verwendung ConfigureFunctionsWebApplication, funktioniert aber auch für 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();

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:

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

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

    _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. Im folgenden Beispiel von einem HTTP-Trigger wird sowohl in eine HTTP-Antwort als auch in eine Ausgabebindung für eine Warteschlange geschrieben:

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

Die Antwort eines HTTP-Triggers wird immer als Ausgabe angesehen, daher ist ein Ergebnis-Attribut nicht erforderlich.

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() anstelle von ConfigureFunctionsWorkerDefaults() zu verwenden. Das folgende Beispiel zeigt ein minimales Setup ohne weitere Anpassungen:

    using Microsoft.Extensions.Hosting;
    using Microsoft.Azure.Functions.Worker;
    
    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"]}!");
    }
    

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

Protokollierung

In isolierten .NET-Projekten können Sie mithilfe einer ILogger<T>- oder ILogger-Instanz in Protokolle 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 im Rahmen der HostBuilder-Konfiguration 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. Standardmäßig können 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:

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

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 der Weiterleitung benutzerdefinierter Protokolle über den Host und wird empfohlen, da Sie so die Ausgabe dieser Protokolle steuern können.

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:

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, v7.0 oder v6.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 eines Code-Projekts

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.

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.

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, erfordert der aktuelle Vorschaubereich manuelle Schritte zum Aktivieren von Debuggen. 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. Verwenden Sie dazu unter Windows den folgenden 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