Compartir a través de


Azure Functions con .NET Aspire (versión preliminar)

.NET Aspire es una pila con opiniones que simplifica el desarrollo de aplicaciones distribuidas en la nube. La integración de .NET Aspire con Azure Functions le permite desarrollar, depurar y organizar un proyecto de .NET de Azure Functions como parte del host de la aplicación Aspire de .NET.

Importante

La integración de .NET Aspire con Azure Functions está actualmente en versión preliminar y está sujeta a cambios.

Prerrequisitos

Configure el entorno de desarrollo para usar Azure Functions con .NET Aspire:

  • Instale el SDK de .NET 9 y .NET Aspire 9.0 o posterior. Aunque se requiere el SDK de .NET 9, .NET Aspire 9.0 admite los marcos .NET 8 y .NET 9.
  • Si usa Visual Studio, actualice a la versión 17.12 o posterior. También debe tener la versión más reciente de las herramientas de Azure Functions para Visual Studio. Para buscar actualizaciones:
    1. Vaya a Tools>Options (Herramientas > Opciones).
    2. En Proyectos y soluciones, seleccione Azure Functions.
    3. Seleccione Buscar actualizaciones e instale las actualizaciones según se le solicite.

Estructura de las soluciones

Una solución que usa Azure Functions y .NET Aspire tiene varios proyectos, incluido un proyecto host de aplicación y uno o varios proyectos de Functions.

El proyecto de host de aplicaciones es el punto de entrada de la aplicación. Organiza la configuración de los componentes de la aplicación, incluido el proyecto de Functions.

Normalmente, la solución también incluye un proyecto configuración predeterminada del servicio. Este proyecto proporciona un conjunto de servicios y configuraciones predeterminados que se usarán en los proyectos de la aplicación.

Proyecto de host de aplicación

Para configurar correctamente la integración, asegúrese de que el proyecto host de la aplicación cumple los siguientes requisitos:

  • El proyecto host de la aplicación debe hacer referencia a Aspire.Hosting.Azure.Functions. Este paquete define la lógica necesaria para la integración.
  • El proyecto host de la aplicación debe tener una referencia de proyecto para cada proyecto de Functions que quiera incluir en la orquestación.
  • En el archivo Program.cs del host de aplicaciones, debe incluir el proyecto llamando a AddAzureFunctionsProject<TProject>() en la instancia IDistributedApplicationBuilder. Este método se usa en lugar de usar el AddProject<TProject>() método que se usa para otros tipos de proyecto en .NET Aspire. Si usa AddProject<TProject>(), el proyecto de Functions no se puede iniciar correctamente.

En el ejemplo siguiente se muestra un archivo mínimo Program.cs para un proyecto host de aplicación:

var builder = DistributedApplication.CreateBuilder(args);

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

builder.Build().Run();

Proyecto de Azure Functions

Para configurar correctamente la integración, asegúrese de que el proyecto de Azure Functions cumple los siguientes requisitos:

En el ejemplo siguiente se muestra un archivo mínimo Program.cs para un proyecto de Functions usado en .NET Aspire:

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

var builder = FunctionsApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.ConfigureFunctionsWebApplication();

builder.Build().Run();

En este ejemplo no se incluye la configuración predeterminada de Application Insights que aparece en muchos otros Program.cs ejemplos y en las plantillas de Azure Functions. En su lugar, configure la integración de OpenTelemetry en .NET Aspire llamando al método builder.AddServiceDefaults.

Para sacar el máximo partido de la integración, tenga en cuenta las siguientes directrices:

  • No incluya ninguna integración directa de Application Insights en el proyecto de Functions. La supervisión en .NET Aspire, en cambio, se gestiona a través de su compatibilidad con OpenTelemetry. Puede configurar .NET Aspire para exportar datos a Azure Monitor a través del proyecto predeterminado del servicio.
  • No defina configuraciones personalizadas de la aplicación en el archivo local.settings.json para el proyecto de Functions. La única configuración que debe estar en local.settings.json es "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated". Establezca todas las demás configuraciones de aplicación a través del proyecto host de la aplicación.

Configuración de conexión con .NET Aspire

El proyecto host de la aplicación define recursos y le ayuda a crear conexiones entre ellos mediante código. En esta sección se muestra cómo configurar y personalizar las conexiones que usa el proyecto de Azure Functions.

.NET Aspire incluye permisos de conexión predeterminados que pueden ayudarle a empezar. Sin embargo, es posible que estos permisos no sean adecuados o suficientes para la aplicación.

En escenarios que usan el control de acceso basado en rol (RBAC) de Azure, puede personalizar los permisos llamando al WithRoleAssignments() método en el recurso del proyecto. Al llamar a WithRoleAssignments(), se eliminan todas las asignaciones de roles predeterminadas y debe definir explícitamente el conjunto completo de asignaciones de roles que desee. Si hospeda la aplicación en Azure Container Apps, el uso de WithRoleAssignments() también requiere que llame a AddAzureContainerAppEnvironment() en DistributedApplicationBuilder.

Almacenamiento de host de Azure Functions

Azure Functions requiere una conexión de almacenamiento de host (AzureWebJobsStorage) para varios de sus comportamientos principales. Cuando llamas a AddAzureFunctionsProject<TProject>() en el proyecto host de tu aplicación, se crea una conexión AzureWebJobsStorage por defecto y se proporciona al proyecto de Funciones. Esta conexión predeterminada usa el emulador de Azure Storage para las ejecuciones de desarrollo local y aprovisiona automáticamente una cuenta de almacenamiento cuando se implementa. Para obtener más control, puede reemplazar esta conexión llamando .WithHostStorage() al recurso del proyecto de Functions.

Los permisos predeterminados que .NET Aspire establece para la conexión de almacenamiento del host dependen de si se llama WithHostStorage() o no. Agregar WithHostStorage() quita una asignación de colaborador de la cuenta de almacenamiento. En la tabla siguiente se enumeran los permisos predeterminados que .NET Aspire establece para la conexión de almacenamiento del host:

Conexión de almacenamiento del servidor Roles predeterminados
Sin llamada a WithHostStorage() Colaborador de datos de Storage Blob,
Colaborador de datos de la cola de Storage,
Colaborador de datos de tabla de Storage,
Colaborador de la cuenta de almacenamiento
Profesión WithHostStorage() Colaborador de datos de Storage Blob,
Colaborador de datos de la cola de Storage,
Colaborador de datos de tabla de Storage

En el ejemplo siguiente se muestra un archivo mínimo Program.cs para un proyecto host de aplicación que reemplaza el almacenamiento de host y especifica una asignación de roles:

using Azure.Provisioning.Storage;

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureContainerAppEnvironment("myEnv");

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

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithHostStorage(myHostStorage)
    .WithRoleAssignments(myHostStorage, StorageBuiltInRole.StorageBlobDataOwner);

builder.Build().Run();

Nota:

El propietario de datos de blobs de almacenamiento es el rol que se recomienda para las necesidades básicas de la conexión de almacenamiento de host. Es posible que la aplicación encuentre problemas si la conexión con Blob service solo tiene el valor predeterminado de .NET Aspire de colaborador de datos de blobs de almacenamiento.

En escenarios de producción, incluya llamadas a WithHostStorage() y WithRoleAssignments(). A continuación, puede establecer este rol explícitamente, junto con cualquier otro que necesite.

Conexiones de desencadenador y enlace

Los desencadenadores y enlaces hacen referencia a las conexiones por nombre. Las siguientes integraciones de .NET Aspire proporcionan estas conexiones a través de una llamada a WithReference() en el recurso del proyecto:

Integración de .NET Aspire Roles predeterminados
Azure Blob Storage Colaborador de datos de Storage Blob,
Colaborador de datos de la cola de Storage,
Colaborador de datos de tabla de Storage
de Azure Queue Storage Colaborador de datos de Storage Blob,
Colaborador de datos de la cola de Storage,
Colaborador de datos de tabla de Storage
Azure Event Hubs Propietario de los datos de Azure Event Hubs
Azure Service Bus Propietario de los datos de Azure Service Bus

En el ejemplo siguiente se muestra un archivo mínimo Program.cs para un proyecto host de aplicación que configura un desencadenador de cola. En este ejemplo, el desencadenador de cola correspondiente tiene su propiedad Connection establecida en MyQueueTriggerConnection, por lo que la llamada a WithReference() especifica el nombre.

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

Para otras integraciones, las llamadas a WithReference establecen la configuración de otra manera. Hacen que la configuración esté disponible para las integraciones de cliente de .NET Aspire, pero no para desencadenadores y enlaces. Para estas integraciones, llame a WithEnvironment() para pasar la información de conexión para que el desencadenador o el enlace se resuelvan.

En el ejemplo siguiente se muestra cómo establecer la variable MyBindingConnection de entorno para un recurso que expone una expresión de cadena de conexión:

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

Si quiere que las integraciones de cliente de .NET Aspire y el sistema de desencadenadores y enlaces usen una conexión, puede configurar tanto WithReference() como WithEnvironment().

Para algunos recursos, la estructura de una conexión puede ser diferente entre la ejecución local y la publicación en Azure. En el ejemplo anterior, otherIntegration podría ser un recurso que se ejecuta como un emulador, por lo que ConnectionStringExpression devolvería una cadena de conexión del emulador. Sin embargo, cuando se publica el recurso, .NET Aspire podría configurar una conexión basada en identidades y ConnectionStringExpression devolvería el URI del servicio. En este caso, para configurar conexiones basadas en identidades para Azure Functions, es posible que tenga que proporcionar un nombre de variable de entorno diferente.

En el ejemplo siguiente se usa builder.ExecutionContext.IsPublishMode para agregar condicionalmente el sufijo necesario:

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

Para obtener más información sobre los formatos de conexión que admite cada enlace y los permisos que requieren esos formatos, consulte las páginas de referencia del enlace.

Hospedaje de la aplicación

De forma predeterminada, al publicar un proyecto de Azure Functions en Azure, se implementa en Azure Container Apps.

Durante el período de versión preliminar, los recursos de la aplicación contenedora no admiten el escalado controlado por eventos. La compatibilidad con Azure Functions no está disponible para las aplicaciones implementadas en este modo. Si necesita abrir una incidencia de soporte técnico, seleccione el tipo de recurso Azure Container Apps.

Consideraciones y procedimientos recomendados

Tenga en cuenta los siguientes puntos al evaluar la integración de Azure Functions con .NET Aspire:

  • La compatibilidad con la integración está actualmente en versión preliminar.

  • La configuración de desencadenador y enlace a través de .NET Aspire se limita actualmente a integraciones específicas. Para obtener más información, consulte Configuración de conexión con .NET Aspire en este artículo.

  • El archivo Program.cs debe utilizar la versión IHostApplicationBuilder de inicio de instancia de host. IHostApplicationBuilder permite llamar a builder.AddServiceDefaults() para agregar valores predeterminados del servicio .NET Aspire al proyecto de funciones.

  • .NET Aspire usa OpenTelemetry para la supervisión. Puede configurar .NET Aspire para exportar datos a Azure Monitor a través del proyecto predeterminado del servicio.

    En muchos otros contextos de Azure Functions, puede incluir la integración directa con Application Insights mediante el registro del servicio de trabajo. No se recomienda este tipo de integración en .NET Aspire. Puede provocar errores en tiempo de ejecución con la versión 2.22.0 de Microsoft.ApplicationInsights.WorkerService, aunque la versión 2.23.0 soluciona este problema. Cuando uses .NET Aspire, quita cualquier integración directa de Application Insights del proyecto de funciones.

  • En el caso de los proyectos de Functions inscritos en una orquestación de .NET Aspire, la mayoría de la configuración de la aplicación debe provenir del proyecto host de aplicación de .NET Aspire. Evite establecer configuraciones en local.settings.json, aparte de la configuración de FUNCTIONS_WORKER_RUNTIME. Si establece la misma variable de entorno en local.settings.json y .NET Aspire, el sistema usa la versión de .NET Aspire.

  • No configure el emulador de Azure Storage para ninguna conexión de local.settings.json. Muchas plantillas de inicio de Functions incluyen el emulador como valor predeterminado para AzureWebJobsStorage. Sin embargo, la configuración del emulador puede pedir a algunos desarrolladores herramientas para iniciar una versión del emulador que pueda entrar en conflicto con la versión que usa .NET Aspire.