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

El entorno de ejecución de Durable Functions persiste automáticamente los parámetros de una función, los valores devueltos y otros estados a una central de tareas para proporcionar una ejecución de confianza. 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 conserva los datos en colas, tablas y blobs en la cuenta de Azure Storage que especifique.

Tipos de datos que se serializan y persisten

En la lista siguiente se muestran los diferentes tipos de datos que se serializarán y conservarán al usar las 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, encabezados y cargas de solicitud y respuesta HTTP duraderas
  • Cargas de llamadas y señales de entidades
  • Cargas de estado de entidades

Trabajo con datos confidenciales

Al usar el proveedor 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, los usuarios de .NET 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 ejemplo de GitHub.

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 a la hora de rotar las claves de cifrado, ya que una orquestación o las entidades pueden ejecutarse durante más tiempo que la directiva 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

Durable Functions para . NET en proceso usa internamente Json.NET para serializar los datos de orquestación y entidad a JSON. La configuración de Json.NET predeterminada que se usa es la siguiente:

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 JsonSerializerSettingsaquí.

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

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

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

Las aplicaciones de funciones que tienen como destino .NET y que se ejecutan en el entorno en tiempo de ejecución de Functions V3 pueden usar la inserción de dependencias para personalizar cómo se serializan los datos y las excepciones. En el código de ejemplo siguiente se muestra cómo usar la inserción de dependencias para invalidar los valores de serialización de Json.NET predeterminados mediante implementaciones personalizadas de las interfaces de servicio 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
            }
        }
    }
}