Guide för att köra C# Azure Functions i en isolerad process
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. C#-funktioner för isolerad process körs på både .NET 5.0 och .NET 6.0. Processfunktioner för C#-klassbibliotek stöds inte på .NET 5.0.
| Komma igång | Begrepp | Exempel |
|---|---|---|
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 av Functions-körningen. Funktionerna för både isolerade processer och processbaserade C#-klassbibliotek körs på .NET 6.0. Mer information finns i Versioner som stöds.
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 (.NET Isolerad) |
|---|---|---|
| Functions 4.x | .NET 6.0 | .NET 6.0 |
| Functions 3.x | .NET Core 3.1 | .NET 5.01 |
| Functions 2.x | .NET Core 2.12 | saknas |
| Functions 1.x | .NET Framework 4.8 | saknas |
1 Byggprocessen kräver även .NET Core 3.1 SDK.
2 Mer information finns i Functions v2.x-överväganden.
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 en .NET-körning som stöds. Följande är de grundläggande filer som krävs i alla .NET-isolerade projekt:
- host.json-fil.
- filen local.settings.json.
- 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ända host.json-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 genom att använda en modell som liknar den 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("output-queue")]
public static string[] Run([QueueTrigger("input-queue")] 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 tillämpa ett utdatabindningsattribut på funktionsmetoden, som definierade 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("output-queue")]
public static string[] Run([QueueTrigger("input-queue")] Book myQueueItem,
FunctionContext context)
{
// Use a string array to return more than one message.
string[] messages = {
$"Book name = {myQueueItem.Name}",
$"Book ID = {myQueueItem.Id}"};
var logger = context.GetLogger("QueueFunction");
logger.LogInformation($"{messages[0]},{messages[1]}");
// Queue Output messages
return messages;
}
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. 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 beroende injection.
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å out-of-process jämfört med .NET-klassbiblioteksfunktioner som körs i processen:
| Funktion/beteende | Pågår | In-of-process (In-of-process) |
|---|---|---|
| .NET-versioner | .NET Core 3.1 .NET 6.0 |
.NET 5.0 .NET 6.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 som] 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.json-artefakt | Genereras | Genereras inte |
| Konfiguration | host.json | host.json och anpassad initiering |
| Beroendeinmatning | Stöds | Stöds |
| Mellanprogram | Stöds inte | Stöds |
| Kalla starttider | 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 |