Persistência de dados e serialização na Durable Functions (Azure Functions)
O tempo de execução do Durable Functions persiste automaticamente os parâmetros da função, os valores de retorno e outros estados para o hub de tarefas para fornecer uma execução confiável. No entanto, a quantidade e a frequência dos dados persistidos para o armazenamento durável podem afetar o desempenho do aplicativo e os custos de transação de armazenamento. Dependendo do tipo de dados que seu aplicativo armazena, a retenção de dados e as políticas de privacidade também podem precisar ser consideradas.
Conteúdo do Hub de Tarefas
Os hubs de tarefas armazenam o estado atual das instâncias e todas as mensagens pendentes:
- Os estados da instância armazenam o status atual e o histórico de uma instância. Para instâncias de orquestração, esse estado inclui o estado de runtime, o histórico de orquestração, as entradas, as saídas e o status personalizado. Para instâncias de entidade, inclui o estado da entidade.
- As mensagens armazenam as entradas ou as saídas da função, as cargas dos eventos e os metadados que são usados para fins internos, como roteamento e correlação de ponta a ponta.
As mensagens serão excluídas após processadas, mas os estados de instância persistirão, a menos que sejam excluídos explicitamente pelo aplicativo ou por um operador. Em particular, um histórico de orquestração permanece armazenado mesmo após a conclusão da orquestração.
Para obter um exemplo de como os estados e as mensagens representam o progresso de uma orquestração, consulte o exemplo de execução do hub de tarefas.
Onde e como os estados e as mensagens serão representados no armazenamento dependem do provedor de armazenamento. O provedor padrão das Durable Functions usa o Armazenamento do Azure que persiste os dados em filas, tabelas e blobs em uma conta do Armazenamento do Azure especificada por você.
Tipos de dados que são serializados e persistentes
A seguinte lista mostra os diferentes tipos de dados que serão serializados e persistidos quando os recursos das Durable Functions forem usados:
- Todas as entradas e saídas de orquestrador, atividade e funções de entidade, incluindo quaisquer IDs e exceções sem tratamento
- Nomes de funções do Orchestrator, da atividade e da entidade
- Nomes e cargas de eventos externos
- Conteúdos de status de orquestração personalizados
- Mensagens de encerramento de orquestração
- Conteúdos de temporizador duráveis
- URLs de solicitação e resposta de HTTP duráveis, cabeçalhos e conteúdos
- Conteúdos de chamada de entidade e de sinal
- Conteúdos de estado de entidade
Trabalhando com dados confidenciais
Quando o provedor do Armazenamento do Azure é usado, todos os dados são criptografados automaticamente em repouso. No entanto, qualquer pessoa com acesso à conta de armazenamento pode ler os dados em sua forma descriptografada. Caso você precise obter uma proteção mais forte para os dados confidenciais, considere, primeiro, a criptografia dos dados usando suas chaves de criptografia para que os dados sejam persistidos no respectivo formato previamente criptografado.
Como alternativa, os usuários do .NET têm a opção de implementar provedores de serialização personalizados que fornecem criptografia automática. Um exemplo de serialização personalizada com criptografia pode ser encontrado neste exemplo do GitHub.
Observação
Se você decidir implementar a criptografia no nível do aplicativo, lembre-se de que as orquestrações e entidades podem existir por períodos indefinidos de tempo. Isso é importante quando se trata de girar suas chaves de criptografia porque uma orquestração ou entidades podem ser executadas por mais tempo do que a política de rotação de chaves. Se ocorrer uma rotação de chaves, a chave usada para criptografar seus dados poderá não estar mais disponível para descriptografá-la na próxima vez que sua orquestração ou entidade for executada. A criptografia do cliente é, portanto, recomendada somente quando as orquestrações e entidades são esperadas para serem executadas por períodos de tempo relativamente curtos.
Personalizando a serialização e desserialização
Lógica de serialização padrão
O Durable Functions para .NET em processo usa internamente o Json.NET para serializar dados de orquestração e entidade para JSON. As configurações padrão do Json.NET usadas são:
Entradas, saídas e estado:
JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
DateParseHandling = DateParseHandling.None,
}
Exceções:
JsonSerializerSettings
{
ContractResolver = new ExceptionResolver(),
TypeNameHandling = TypeNameHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
}
Ler a documentação mais detalhada sobre JsonSerializerSettings
aqui.
Personalizando a serialização com atributos .NET
Durante a serialização, o Json.NET procura vários atributos em classes e propriedades que controlam como os dados são serializados e desserializados no JSON. Se você possui o código-fonte para o tipo de dados passados para as APIs da Durable Functions, considere adicionar esses atributos ao tipo para personalizar a serialização e desserialização.
Personalizando a serialização com Injeção de Dependência
Os aplicativos de funções direcionados ao .NET e executados no tempo de execução do Functions V3 podem usar Injeção de Dependência (DI) para personalizar como os dados e as exceções são serializados. O código de exemplo a seguir demonstra como usar a DI para substituir as configurações padrão de serialização do Json.NET usando implementações personalizadas das interfaces de serviço IMessageSerializerSettingsFactory
e 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
}
}
}
}