Guide för att köra funktioner på .NET 5.0 i Azure

Den här artikeln är en introduktion till att använda C# för att utveckla .NET-isolerade processfunktioner som tar slut i processen i Azure Functions. När processen tar slut kan du frikoppla funktionskoden från den Azure Functions körningen. Det är också ett sätt för dig att skapa och köra funktioner som riktar sig mot den aktuella .NET 5.0-versionen.

Komma igång Begrepp Exempel

Om du inte behöver stödja .NET 5.0 eller köra dina funktioner utanför processen kan du i stället utveckla C#-klassbiblioteksfunktioner.

Varför är .NET isolerad process?

Tidigare Azure Functions endast stöd för ett nära integrerat läge för .NET-funktioner, som körs som ett klassbibliotek i samma process som värden. Det här läget ger djupgående integrering mellan värdprocessen och funktionerna. Till exempel kan .NET-klassbiblioteksfunktioner dela bindnings-API:er och -typer. Den här integreringen kräver dock även en striktare koppling mellan värdprocessen och .NET-funktionen. Till exempel krävs .NET-funktioner som körs i processen för att köras på samma version av .NET som Functions-körningen. Om du vill köra utanför dessa begränsningar kan du nu välja att köra i en isolerad process. Med den här processisoleringen kan du även utveckla funktioner som använder aktuella .NET-versioner (till exempel .NET 5.0), som inte stöds inbyggt av Functions-körningen.

Eftersom dessa funktioner körs i en separat process finns det vissa funktionsskillnader mellan .NET-isolerade funktionsappar och .NET-klassbiblioteksfunktionsappar.

Fördelar med att processen tar slut

När processen tar slut kan dina .NET-funktioner dra nytta av följande fördelar:

  • Färre konflikter: eftersom funktionerna körs i en separat process står sammansättningar som används i din app inte i konflikt med olika versioner av samma sammansättningar som används av värdprocessen.
  • Fullständig kontroll över processen: du styr start av appen och kan styra de konfigurationer som används och mellanprogrammet startas.
  • Beroendeinjektion: Eftersom du har fullständig kontroll över processen kan du använda aktuella .NET-beteenden för beroendeinjektion och införliva mellanprogram i funktionsappen.

Versioner som stöds

Versioner av Functions-körningen fungerar med specifika versioner av .NET. Mer information om Functions-versioner finns i Azure Functions översikt över körningsversioner. Versionsstöd beror på om dina funktioner körs i process eller utanför processen (isolerade).

I följande tabell visas den högsta nivån av .NET Core eller .NET Framework som kan användas med en specifik version av Functions.

Körningsversion av Functions Pågår
(.NET-klassbibliotek)
In-of-process (In-of-process)
(.NET Isolerad)
Functions 4.x (förhandsversion) .NET 6.0 (förhandsversion) .NET 6.0 (förhandsversion)2
Functions 3.x .NET Core 3.1 .NET 5.0
Functions 2.x .NET Core 2.11 saknas
Functions 1.x .NET Framework 4.8 saknas

1 Mer information finns i Functions v2.x-överväganden.
2 Du kan för närvarande bara skapa isolerade processfunktioner med hjälp av Azure Functions Core Tools. Mer information finns i Snabbstart: Skapa en C#-funktion i Azure från kommandoraden.

För de senaste nyheterna Azure Functions versioner, inklusive borttagning av specifika äldre mindre versioner, kan du övervaka Azure App Service meddelanden.

.NET-isolerat projekt

Ett .NET-isolerat funktionsprojekt är i princip ett .NET-konsolappsprojekt som riktar sig mot .NET 5.0. Följande är de grundläggande filer som krävs i alla .NET-isolerade projekt:

  • host.jspå filen.
  • local.settings.jspå filen.
  • C#-projektfil (.csproj) som definierar projektet och beroenden.
  • Program.cs-fil som är startpunkten för appen.

Paketreferenser

När processen tar slut använder .NET-projektet en unik uppsättning paket som implementerar både grundläggande funktioner och bindningstillägg.

Kärnpaket

Följande paket krävs för att köra dina .NET-funktioner i en isolerad process:

Tilläggspaket

Eftersom funktioner som körs i en .NET-isolerad process använder olika bindningstyper kräver de en unik uppsättning bindningstilläggspaket.

Du hittar dessa tilläggspaket under Microsoft.Azure.Functions.Worker.Extensions.

Start och konfiguration

När du använder isolerade .NET-funktioner har du åtkomst till start av funktionsappen, som vanligtvis finns i Program.cs. Du ansvarar för att skapa och starta en egen värdinstans. Därför har du också direkt åtkomst till konfigurationspipelinen för din app. När processen tar slut kan du mycket enklare lägga till konfigurationer, mata in beroenden och köra ditt eget mellanprogram.

Följande kod visar ett exempel på en [HostBuilder-pipeline:]

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
    })
    .Build();

Den här koden kräver using Microsoft.Extensions.DependencyInjection; .

En [HostBuilder används] för att skapa och returnera en fullständigt initierad [IHost-instans] som du kör asynkront för att starta funktionsappen.

await host.RunAsync();

Konfiguration

Metoden ConfigureFunctionsWorkerDefaults används för att lägga till de inställningar som krävs för att funktionsappen ska ta slut, vilket omfattar följande funktioner:

  • Standarduppsättning med konverterare.
  • Ange [JsonSerializerOptions som standard för att] ignorera höljet för egenskapsnamn.
  • Integrera med Azure Functions loggning.
  • Mellanprogram och funktioner för utdatabindning.
  • Mellanprogram för funktionskörning.
  • Standardstöd för gRPC.
.ConfigureFunctionsWorkerDefaults()

Om du har åtkomst till pipelinen för värdbyggaren kan du även ange appspecifika konfigurationer under initieringen. Du kan anropa [metoden ConfigureAppConfiguration] på HostBuilder en eller flera gånger för att lägga till de konfigurationer som krävs av funktionsappen. Mer information om appkonfiguration finns i Konfiguration i ASP.NET Core.

Dessa konfigurationer gäller för funktionsappen som körs i en separat process. Om du vill göra ändringar i functions-värden eller utlösaren och bindningskonfigurationen måste du fortfarande användahost.jspå filen.

Beroendeinmatning

Beroendeinjektion är förenklad jämfört med .NET-klassbibliotek. I stället för att behöva skapa en startklass för att registrera tjänster behöver du bara anropa [ConfigureServices] på värdbyggaren och använda tilläggsmetoderna på IServiceCollection för att mata in specifika tjänster.

I följande exempel matas ett singleton-tjänstberoende in:

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

Den här koden kräver using Microsoft.Extensions.DependencyInjection; . Mer information finns i Dependency injection in ASP.NET Core.

Mellanprogram

.NET isolerad stöder också registrering av mellanprogram, återigen med hjälp av en modell som liknar det som finns i ASP.NET. Den här modellen ger dig möjlighet att mata in logik i anropspipelinen och före och efter att funktioner körs.

Tilläggsmetoden ConfigureFunctionsWorkerDefaults har en överlagring där du kan registrera ditt eget mellanprogram, som du kan se i följande exempel.

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
        // Register our custom middleware with the worker
        workerApplication.UseMiddleware<MyCustomMiddleware>();
    })
    .Build();

Ett mer komplett exempel på hur du använder anpassat mellanprogram i funktionsappen finns i referensexempel för anpassade mellanprogram.

Körningskontext

.NET isolerad skickar ett [FunctionContext-objekt] till dina funktionsmetoder. Med det här objektet kan du få [en ILogger-instans] att skriva till loggarna genom att anropa [metoden GetLogger] och ange en categoryName sträng. Mer information finns i Logga.

Bindningar

Bindningar definieras med hjälp av attribut för metoder, parametrar och returtyper. En funktionsmetod är en metod med ett Function attribut och ett utlösarattribut som tillämpas på en indataparameter, som du ser i följande exempel:

[Function("QueueFunction")]
[QueueOutput("myqueue-output")]
public static string Run([QueueTrigger("myqueue-items")] Book myQueueItem,
    FunctionContext context)

Utlösarattributet anger utlösartypen och binder indata till en metodparameter. Föregående exempelfunktion utlöses av ett kömeddelande och kömeddelandet skickas till metoden i myQueueItem parametern .

Attributet Function markerar metoden som en startpunkt för funktionen. Namnet måste vara unikt inom ett projekt, börja med en bokstav och endast innehålla bokstäver, siffror, och , upp _ - till 127 tecken. Project skapar ofta en metod med namnet Run , men metodnamnet kan vara val annat giltigt C#-metodnamn.

Eftersom .NET-isolerade projekt körs i en separat arbetsprocess kan bindningar inte dra nytta av omfattande bindningsklasser, till exempel ICollector<T> , IAsyncCollector<T> och CloudBlockBlob . Det finns heller inget direkt stöd för typer som ärvts från underliggande tjänst-SDK:er, till exempel DocumentClient och [BrokeredMessage.] I stället förlitar sig bindningar på strängar, matriser och serialiserbara typer, till exempel vanliga gamla klassobjekt (POPO:er).

För HTTP-utlösare måste du använda [HttpRequestData och] [HttpResponseData för] att få åtkomst till begärande- och svarsdata. Det beror på att du inte har åtkomst till de ursprungliga HTTP-begärande- och svarsobjekten när processen tar slut.

En fullständig uppsättning referensexempel för att använda utlösare och bindningar när processen tar slut finns i referensexempel för bindningstillägg.

Indatabindningar

En funktion kan ha noll eller flera indatabindningar som kan skicka data till en funktion. Precis som utlösare definieras indatabindningar genom att ett bindningsattribut tillämpas på en indataparameter. När funktionen körs försöker körningen hämta data som anges i bindningen. De data som begärs är ofta beroende av information som tillhandahålls av utlösaren med hjälp av bindningsparametrar.

Utdatabindningar

Om du vill skriva till en utdatabindning måste du använda ett utdatabindningsattribut för funktionsmetoden, som definierar hur du skriver till den bundna tjänsten. Värdet som returneras av metoden skrivs till utdatabindningen. Följande exempel skriver till exempel ett strängvärde till en meddelandekö med namnet med myqueue-output hjälp av en utdatabindning:

[Function("QueueFunction")]
[QueueOutput("myqueue-output")]
public static string Run([QueueTrigger("myqueue-items")] Book myQueueItem,
    FunctionContext context)
{
    var logger = context.GetLogger("QueueFunction");
    logger.LogInformation($"Book name = {myQueueItem.Name}");

    // Queue Output
    return "queue message";
}

Flera utdatabindningar

Data som skrivs till en utdatabindning är alltid funktionens returvärde. Om du behöver skriva till mer än en utdatabindning måste du skapa en anpassad returtyp. Den här returtypen måste ha utdatabindningsattributet tillämpat på en eller flera egenskaper för klassen. Följande exempel från en HTTP-utlösare skriver till både HTTP-svaret och en köutdatabindning:

public static class MultiOutput
{
    [Function("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; }
}

Svaret från en HTTP-utlösare betraktas alltid som utdata, så ett returvärdesattribut krävs inte.

HTTP-utlösare

HTTP-utlösare översätter det inkommande HTTP-begärandemeddelandet till ett [HttpRequestData-objekt] som skickas till funktionen. Det här objektet tillhandahåller data från begäran, inklusive Headers , , , och Cookies Identities URL valfritt ett meddelande Body . Det här objektet är en representation av HTTP-begärandeobjektet och inte själva begäran.

På samma sätt returnerar funktionen ett [HttpResponseData-objekt] som tillhandahåller data som används för att skapa HTTP-svaret, inklusive meddelandet StatusCode , och Headers eventuellt ett meddelande Body .

Följande kod är en HTTP-utlösare

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

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Date", "Mon, 18 Jul 2016 16:06:00 GMT");
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    
    response.WriteString("Welcome to .NET 5!!");

    return response;
}

Loggning

I .NET isolerad kan du skriva till loggar med hjälp av [en ILogger-instans som] hämtas från ett [FunctionContext-objekt] som skickas till din funktion. Anropa [metoden GetLogger] och skicka ett strängvärde som är namnet på den kategori där loggarna skrivs. Kategorin är vanligtvis namnet på den specifika funktion som loggarna skrivs från. Mer information om kategorier finns i övervakningsartikeln.

I följande exempel visas hur du hämtar en ILogger och skriver loggar i en funktion:

var logger = executionContext.GetLogger("HttpFunction");
logger.LogInformation("message logged");

Använd olika metoder för [ILogger för] att skriva olika loggnivåer, till exempel LogWarning eller LogError . Mer information om loggnivåer finns i övervakningsartikeln.

En [ILogger tillhandahålls] också när du använder beroendeinjektion.

Skillnader med .NET-klassbiblioteksfunktioner

I det här avsnittet beskrivs det aktuella tillståndet för funktionella och beteendemässiga skillnader som körs på .NET 5.0 utanför processen jämfört med .NET-klassbiblioteksfunktioner som körs i processen:

Funktion/beteende Pågår (.NET Core 3.1) Out-of-process (.NET 5.0)
.NET-versioner LTS (.NET Core 3.1) Aktuell (.NET 5.0)
Kärnpaket Microsoft .NET.Sdk.Functions Microsoft.Azure.Functions.Worker
Microsoft.Azure.Functions.Worker.Sdk
Paket för bindningstillägg Microsoft.Azure.WebJobs.Extensions.* Under Microsoft.Azure.Functions.Worker.Extensions.*
Loggning ILogger skickades till funktionen [ILogger hämtas] från FunctionContext
Annulleringstoken Stöds Stöds inte
Utdatabindningar Out-parametrar Returvärden
Typer av utdatabindningar IAsyncCollector, [DocumentClient,] BrokeredMessageoch andra klientspecifika typer Enkla typer, JSON-serialiserbara typer och matriser.
Flera utdatabindningar Stöds Stöds
HTTP-utlösare HttpRequest / ObjectResult HttpRequestData / HttpResponseData
Bestående funktioner Stöds Stöds inte
Imperativ bindning Stöds Stöds inte
function.jspå artefakt Genereras Genereras inte
Konfiguration host.jspå host.jspå och anpassad initiering
Beroendeinmatning Stöds Stöds
Mellanprogram Stöds inte Stöds
Kallstartstider Typiska Längre på grund av just-in-time-start. Kör i Linux i stället för Windows för att minska eventuella fördröjningar.
ReadyToRun Stöds TBD

Kända problem

Information om lösningar för att få information om problem med att köra .NET-isolerade processfunktioner finns på den här sidan med kända problem. Om du vill rapportera problem skapar du ett problem i den här GitHub lagringsplatsen.

Nästa steg