Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O runtime do Durable Functions persiste automaticamente os parâmetros de função, valores de retorno e outros estados no hub de tarefas para garantir uma execução fiá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, as políticas de retenção de dados e privacidade também podem precisar ser consideradas.
Este artigo explica que dados são mantidos, como lidar com grandes cargas úteis e dados sensíveis, e como personalizar a serialização para cada linguagem suportada.
Neste artigo:
- Conteúdo do Task Hub - Que dados são armazenados e como
- Mantenha as entradas e saídas pequenas - Estratégias para gerir o tamanho da carga útil
- Trabalhar com dados sensíveis - Proteger segredos e informações pessoais identificáveis
- Personalizar serialização e desserialização - Opções de serialização específicas por língua
Conteúdo do Task Hub
Os hubs de tarefas armazenam o estado atual das instâncias e quaisquer 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 tempo de execução, o histórico de orquestração, entradas, saídas e status personalizado. Para instâncias de entidade, inclui o estado da entidade.
- As mensagens armazenam entradas ou saídas de funções, cargas úteis de eventos e metadados que são usados para fins internos, como roteamento e correlação de ponta a ponta.
As mensagens são excluídas depois de processadas, mas os estados da instância persistem, a menos que sejam explicitamente excluídas pelo aplicativo ou por um operador. Em particular, um histórico de orquestração permanece armazenado mesmo depois que a orquestração é concluída.
Para obter um exemplo de como estados e 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 são representados no armazenamento dependem do provedor de armazenamento. O provedor padrão do Durable Functions é o Armazenamento do Azure, que persiste dados em filas, tabelas e blobs numa conta de Armazenamento do Azure que especificar.
Tipos de dados que são serializados e persistem
A lista seguinte mostra os diferentes tipos de dados que serão serializados e persistirão ao utilizar funcionalidades do Durable Functions:
- Todas as entradas e saídas das funções de orquestrador, de atividade e de entidade, incluindo quaisquer IDs e exceções não tratadas.
- Nomes de funções de orquestrador, atividade e entidade
- Nomes de eventos externos e cargas úteis
- Cargas úteis de estado de orquestração personalizadas
- Mensagens de encerramento de orquestração
- Cargas úteis duráveis do temporizador
- Solicitações e respostas HTTP duráveis: URLs, cabeçalhos e cargas úteis
- Cargas úteis de entidades para chamada e sinalização
- Cargas úteis do estado de entidade
Para orientações sobre a gestão do tamanho da carga útil e proteção de itens sensíveis nesta lista, consulte as secções seguintes.
Mantenha as entradas e saídas das Durable Functions pequenas
Você pode enfrentar problemas de memória se fornecer grandes entradas e saídas para as APIs de Funções Duráveis. As entradas e saídas são serializadas no histórico de orquestração, o que significa que grandes cargas úteis podem, ao longo do tempo, contribuir significativamente para o crescimento ilimitado do histórico. Este crescimento corre o risco de causar exceções de memória durante a repetição.
Para mitigar o impacto de grandes entradas e saídas, pode:
- Delegar trabalho aos suborquestradores para equilibrar a carga da memória histórica entre múltiplos orquestradores, mantendo a pegada de memória das histórias individuais pequena.
- Armazene grandes volumes de dados em armazenamento externo (como o Armazenamento de Blobs do Azure) e passe identificadores leves que permitem recuperar esses dados dentro das funções de atividade quando necessário.
Se usares o Durable Task Scheduler, também podes usar suporte para cargas de grandes dimensões para deslocar cargas maiores para o Armazenamento de Blobs do Azure.
Sugestão
A melhor prática para lidar com grandes volumes de dados é mantê-los em armazenamento externo e materializar esses dados apenas dentro das atividades, quando necessário.
Trabalho com dados sensíveis
As entradas e saídas (incluindo exceções) para e das APIs Durable Functions são mantidas de forma duradoura no seu fornecedor de armazenamento preferência. Se essas entradas, saídas ou exceções contiverem dados sensíveis (como segredos, cadeias de ligação ou informações pessoais identificáveis), qualquer pessoa com acesso de leitura aos recursos do seu fornecedor de armazenamento pode obtê-los.
Para lidar com dados sensíveis de forma segura, obtém esses dados dentro das funções de atividade a partir do Azure Key Vault ou de variáveis de ambiente, e nunca comuniques esses dados diretamente para ou a partir de orquestradores ou entidades. Esta abordagem ajuda a evitar que dados sensíveis escapem para os seus recursos de armazenamento.
Sugestão
Esta orientação aplica-se também à CallHttp API do orquestrador, que mantém os seus payloads de pedido e resposta em armazenamento. Se os seus endpoints HTTP de destino requerem autenticação, implemente a chamada HTTP dentro de uma atividade, ou use o suporte de identidade gerida incorporado oferecido pelo CallHttp, que não mantém as credenciais no armazenamento.
Observação
Evite registar dados que contenham segredos, pois qualquer pessoa com acesso de leitura aos seus registos (por exemplo, no Application Insights) poderia obter esses segredos.
Encriptação em repouso
Ao utilizar o fornecedor Armazenamento do Azure, todos os dados são automaticamente encriptados em repouso. No entanto, qualquer pessoa com acesso à conta de armazenamento pode ler os dados em sua forma não criptografada. Se você precisar de uma proteção mais forte para dados confidenciais, considere primeiro criptografar os dados usando suas próprias chaves de criptografia para que os dados persistam em sua forma pré-criptografada.
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, esteja ciente de que orquestrações e entidades podem existir por períodos indefinidos de tempo. Isso é importante quando for necessário rodar as suas chaves de criptografia, porque uma orquestração ou entidades podem ser executadas por mais tempo do que a sua política de rotação de chaves. Se ocorrer uma rotação de chaves, a chave usada para encriptar os seus dados pode não estar mais disponível para desencriptá-los na próxima vez que a sua orquestração ou entidade seja executada. A encriptação personalizada é, portanto, recomendada apenas quando se espera que orquestrações e entidades corram por períodos relativamente curtos.
Personalizar serialização e desserialização
As opções de personalização de serialização variam consoante a língua. Selecione o separador de idioma para ver as opções disponíveis.
Lógica de serialização padrão
Durable Functions para .NET em processo utilizam internamente o Json.NET para serializar dados de orquestração e de entidades em JSON. As definiçõ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,
}
Leia a documentação mais detalhada aqui JsonSerializerSettings.
Personalizar 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 a partir do JSON. Se for proprietário do código-fonte do tipo de dados passado para as APIs do Durable Functions, considere adicionar estes atributos ao tipo para personalizar a serialização e a desserialização.
Personalizar serialização com Injeção de Dependências
As aplicações de funções destinadas ao .NET e que funcionam no ambiente de execução do Functions V3 podem utilizar 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 DI para substituir as configurações padrão de serialização do Json.NET utilizando 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
}
}
}
}