Compartir a través de


Persistencia y serialización de datos en Durable Functions (Azure Functions)

El tiempo de ejecución de Durable Functions conserva automáticamente los parámetros de función, los valores devueltos y otros estados en el task hub con el fin de proporcionar una ejecución confiable. Sin embargo, la cantidad y la frecuencia de los datos que persisten en el almacenamiento duradero pueden afectar al rendimiento de las aplicaciones y a los costos de las transacciones de almacenamiento. En función del tipo de datos que almacene una aplicación, es posible que también sea necesario tener en cuenta la retención de datos y las directivas de privacidad.

Contenido de la central de tareas

Las centrales de tareas almacenan el estado actual de las instancias y los mensajes pendientes:

  • Los estados de instancia almacenan el estado actual y el historial de una instancia. En el caso de las instancias de orquestación, esto incluye el estado del runtime, el historial de orquestación, las entradas, las salidas y el estado personalizado. En el caso de las instancias de entidad, incluye el estado de la entidad.
  • Los mensajes almacenan entradas o salidas de función, cargas de eventos y metadatos que se usan con fines internos, como el enrutamiento y la correlación de un extremo a otro.

Los mensajes se eliminan después de procesarse, pero los estados de instancia se conservan a menos que la aplicación o un operador los eliminen explícitamente. En concreto, un historial de orquestaciones permanece en el almacenamiento incluso después de que se completa la orquestación.

Para obtener un ejemplo de cómo los estados y los mensajes representan el progreso de una orquestación, consulte el ejemplo de ejecución de la central de tareas.

Dónde y cómo se representan los estados y los mensajes en el almacenamiento depende del proveedor de almacenamiento. El proveedor predeterminado de Durable Functions es Azure Storage, que conserve los datos en colas, tablas y blobs en una cuenta de Azure Storage al que usted especifique.

Tipos de datos que se serializan y persisten

En la lista siguiente se muestran los distintos tipos de datos que se serializarán y se conservarán al usar características de Durable Functions:

  • Todas las entradas y salidas de las funciones de orquestador, actividad y entidad, incluidos los identificadores y las excepciones no controladas
  • Nombres de las funciones de orquestador, actividad y entidad
  • Nombres y cargas de eventos externos
  • Cargas de estado de la orquestación personalizada
  • Mensajes de finalización de orquestación
  • Cargas de temporizador duraderas
  • Direcciones URL de solicitud y respuesta HTTP duraderas, encabezados y cargas
  • Cargas de llamadas y señales de entidades
  • Cargas de estado de entidades

Mantener pequeñas entradas y salidas

Puede encontrarse con problemas de memoria si proporciona entradas y salidas grandes hacia y desde Durable Functions API. Las entradas y salidas se serializan en el historial de orquestación, lo que significa que las cargas grandes pueden, con el tiempo, contribuir considerablemente al crecimiento ilimitado del historial. Este crecimiento corre el riesgo de causar excepciones de memoria durante la reproducción.

Para mitigar el impacto de las entradas y salidas grandes, puede hacer lo siguiente:

  • Delegar el trabajo en sub-orquestadores para equilibrar la carga de la memoria del historial entre varios orquestadores, manteniendo pequeña la huella de memoria de los historiales individuales.
  • Almacene datos grandes en el almacenamiento externo (como Azure Blob Storage) y pase identificadores ligeros que le permiten recuperar esos datos dentro de las funciones de actividad cuando sea necesario.

Sugerencia

El procedimiento recomendado para tratar datos grandes es mantenerlo en el almacenamiento externo y materializar esos datos solo dentro de las actividades, cuando sea necesario.

Trabajo con datos confidenciales

Las entradas y salidas (incluidas las excepciones) a y desde las API de Durable Functions se conservan de forma duradera en el proveedor de storage que prefiera. Si esas entradas, salidas o excepciones contienen datos confidenciales (como secretos, cadenas de conexión o información de identificación personal), cualquier persona con acceso de lectura a los recursos del proveedor de almacenamiento podría obtenerlas.

Para manipular de forma segura los datos confidenciales, obtenga esos datos desde Azure Key Vault o variables de entorno dentro de las funciones de actividad, y nunca comunique esos datos directamente hacia o desde orquestadores o entidades. Este enfoque ayuda a evitar que los datos confidenciales se filtren en los recursos de almacenamiento.

Sugerencia

Esta guía también se aplica a la API de orquestador, que conserva sus cargas de solicitud y respuesta en el almacenamiento. Si los puntos de conexión HTTP de destino requieren autenticación, implemente la llamada HTTP dentro de una actividad o use la compatibilidad integrada con identidad administrada ofrecida por CallHttp, que no conserva las credenciales en el almacenamiento.

Nota

Evite registrar datos que contengan secretos, ya que cualquier persona con acceso de lectura a los registros (por ejemplo, en Application Insights) podría obtener esos secretos.

Al usar el proveedor de Azure Storage, todos los datos se cifran automáticamente en reposo. Sin embargo, cualquier usuario con acceso a la cuenta de almacenamiento puede leer los datos en su formato no cifrado. Si necesita una protección más segura para datos confidenciales, considere la posibilidad de cifrar primero los datos con sus propias claves de cifrado para que los datos se conserven en su formato previamente cifrado.

Como alternativa, .NET los usuarios tienen la opción de implementar proveedores de serialización personalizados que proporcionan cifrado automático. Puede encontrar un ejemplo de serialización personalizada con cifrado en este GitHub ejemplo.

Nota

Si decide implementar el cifrado a nivel de aplicación, tenga en cuenta que las orquestaciones y entidades pueden existir durante un período de tiempo indefinido. Esto es importante cuando llega el momento de rotar tus claves de cifrado, ya que una orquestación u otras entidades pueden operar durante más tiempo que tu política de rotación de claves. Si se produce una rotación de claves, es posible que la clave usada para cifrar los datos ya no esté disponible para descifrarlos la próxima vez que se ejecute la orquestación o entidad. Por lo tanto, se recomienda el cifrado del cliente solo cuando se espera que las orquestaciones y entidades se ejecuten durante períodos de tiempo relativamente cortos.

Personalización de la serialización y deserialización

Lógica de serialización predeterminada

Funciones duraderas para .NET en el proceso utilizan internamente Json.NET para serializar datos de orquestación y de entidades a JSON. La configuración predeterminada de Json.NET que se usa son:

Entradas, salidas y estado:

JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.None,
    DateParseHandling = DateParseHandling.None,
}

Excepciones:

JsonSerializerSettings
{
    ContractResolver = new ExceptionResolver(),
    TypeNameHandling = TypeNameHandling.Objects,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
}

Lea la documentación más detallada sobre aquí.

Personalización de la serialización con atributos de .NET

Durante la serialización, Json.NET busca atributos various en clases y propiedades que controlan cómo se serializan y deserializan los datos desde JSON. Si posee el código fuente del tipo de datos pasado a Durable Functions API, considere la posibilidad de agregar estos atributos al tipo para personalizar la serialización y la deserialización.

Personalización de la serialización con inserción de dependencias

Las aplicaciones de funciones destinadas a .NET y que se ejecutan en el entorno de ejecución de Functions V3 pueden usar Dependency Injection (DI) para personalizar cómo se serializan los datos y las excepciones. En el código de ejemplo siguiente se muestra cómo usar la inyección de dependencias para invalidar la configuración de serialización predeterminada de Json.NET mediante implementaciones personalizadas de las interfaces de servicio de IMessageSerializerSettingsFactory y IErrorSerializerSettingsFactory.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Collections.Generic;

[assembly: FunctionsStartup(typeof(MyApplication.Startup))]
namespace MyApplication
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IMessageSerializerSettingsFactory, CustomMessageSerializerSettingsFactory>();
            builder.Services.AddSingleton<IErrorSerializerSettingsFactory, CustomErrorSerializerSettingsFactory>();
        }

        /// <summary>
        /// A factory that provides the serialization for all inputs and outputs for activities and
        /// orchestrations, as well as entity state.
        /// </summary>
        internal class CustomMessageSerializerSettingsFactory : IMessageSerializerSettingsFactory
        {
            public JsonSerializerSettings CreateJsonSerializerSettings()
            {
                // Return your custom JsonSerializerSettings here
            }
        }

        /// <summary>
        /// A factory that provides the serialization for all exceptions thrown by activities
        /// and orchestrations
        /// </summary>
        internal class CustomErrorSerializerSettingsFactory : IErrorSerializerSettingsFactory
        {
            public JsonSerializerSettings CreateJsonSerializerSettings()
            {
                // Return your custom JsonSerializerSettings here
            }
        }
    }
}