Provedor de Armazenamento do Microsoft Azure (Azure Functions)

Este documento descreve as características do provedor de Armazenamento do Microsoft Azure do Durable Functions, com foco nos aspectos de desempenho e escalabilidade. O provedor de Armazenamento do Microsoft Azure é o provedor padrão. Ele armazena os estados de instância e filas em uma conta de Armazenamento do Microsoft Azure (clássica).

Observação

Para obter mais informações sobre os provedores de armazenamento compatíveis com Durable Functions e como eles se comparam, confira a documentação de provedores de armazenamento do Durable Functions.

No provedor de Armazenamento do Microsoft Azure, toda a execução de funções é conduzida por filas de Armazenamento do Microsoft Azure. O status e o histórico da orquestração e da entidade são armazenados nas Tabelas do Azure. Os Blobs do Azure e as concessões de blob são usados para distribuir instâncias de orquestração e entidades entre várias instâncias de aplicativo (também conhecidas como trabalhos ou simplesmente VMs). Esta seção apresenta mais detalhes sobre os vários artefatos do Armazenamento do Azure e como eles afetam o desempenho e a escalabilidade.

Representação de armazenamento

Um hub de tarefas persiste de forma durável a todos os estados de instância e a todas as mensagens. Para obter uma visão geral rápida de como eles são usados para rastrear o progresso de uma orquestração, consulte o exemplo de execução do hub de tarefas.

O provedor de Armazenamento do Microsoft Azure representa o hub de tarefas no armazenamento usando os seguintes componentes:

  • Entre duas e três Tabelas do Azure. Duas tabelas são usadas para representar históricos e estados de instância. Se o Gerenciador de Partições de Tabela estiver habilitado, uma terceira tabela será introduzida para armazenar as informações de partição.
  • Uma Fila do Azure armazena as mensagens de atividade.
  • Uma ou mais Filas do Azure armazenam as mensagens da instância. Cada uma dessas chamadas filas de controle representa uma partição que é atribuída a um subconjunto de todas as mensagens da instância, com base no hash da ID da instância.
  • Alguns contêineres de blobs adicionais usados para blobs de concessão e/ou mensagens grandes.

Por exemplo, um hub de tarefas nomeado xyz com PartitionCount = 4 contém as seguintes filas e tabelas:

Diagram showing Azure Storage provider storage storage organization for 4 control queues.

A seguir, descreveremos com mais detalhes esses componentes e a função que desempenham.

Tabela de histórico

A tabela de Histórico é uma tabela do Armazenamento do Microsoft Azure que contém eventos de histórico de todas as instâncias de orquestração com um hub de tarefas. O nome da tabela está no formato TaskHubNamehistórico. Conforme as instâncias são executadas, novas linhas são adicionadas a essa tabela. A chave de partição da tabela é derivada da ID de instância da orquestração. As IDs de instância são aleatórias por padrão, garantindo a distribuição ideal de partições internas no Armazenamento do Azure. A chave de linha para essa tabela é um número de sequência usado para ordenar os eventos de histórico.

Quando uma instância de orquestração precisa ser executada, as linhas correspondentes da tabela de histórico são carregadas na memória usando uma consulta de intervalo dentro de apenas uma partição de tabela. Esses histórico de eventos são, em seguida, copiados para o código de função do orquestrador para recuperá-lo em seu estado de ponto de verificação anteriormente. O uso do histórico de execução para recriar o estado dessa maneira é influenciado pelo padrão de Fornecimento de Evento.

Dica

Os dados de orquestração armazenados na tabela de histórico incluem cargas de saída de funções de atividade e de suborquestrador. As cargas de eventos externos também são armazenadas na tabela de Histórico. Como o histórico completo é carregado na memória toda vez que um orquestrador precisa ser executado, um histórico suficientemente grande pode resultar em uma pressão de memória significativa em uma determinada VM. O comprimento e o tamanho do histórico de orquestração podem ser reduzidos dividindo orquestrações grandes em várias suborquestrações ou reduzindo o tamanho das saídas retornadas pela atividade e as funções de suborquestrador que ela chama. Como alternativa, você pode reduzir o uso de memória reduzindo as limitações de simultaneidade por VM para limitar quantas orquestrações são carregadas na memória simultaneamente.

Tabela de instâncias

A tabela de Instâncias contém os status de todas as instâncias de orquestração e entidade dentro de um hub de tarefas. Conforme as instâncias são criadas, novas linhas são adicionadas a essa tabela. A chave de partição da tabela é a ID de instância de orquestração a chave de entidade e a chave de linha é uma cadeia de caracteres vazia. Há uma linha por instância de orquestração ou de entidade.

Esta tabela é usada para atender a solicitações de consulta de instância de código, bem como a chamadas à API HTTP de consulta de status. Isso é mantido finalmente consistente com o conteúdo da tabela Histórico mencionada anteriormente. O uso de uma tabela separada do Armazenamento do Microsoft Azure para atender com eficiência as operações de consulta de instância dessa maneira é influenciado pelo padrão de Comando e Segregação de Reponsabilidade (CQRS).

Dica

O particionamento da tabela Instâncias permite a ela armazenar milhões de instâncias de orquestração sem nenhum impacto perceptível no desempenho ou escala do runtime. No entanto, o número de instâncias pode ter um impacto significativo no desempenho da consulta de várias instâncias. Para controlar a quantidade de dados armazenados nessas tabelas, considere limpar periodicamente os dados antigos da instância.

Tabela de partições

Observação

Esta tabela é mostrada no hub de tarefas somente quando Table Partition Manager estiver habilitada. Para aplicá-lo, defina a useTablePartitionManagement configuração no host.json do seu aplicativo.

A tabela Partições armazena a status de partições do aplicativo Durable Functions e é usada para distribuir partições entre os trabalhadores do seu aplicativo. Há uma linha por partição.

Filas

As funções de orquestrador, entidade e atividade são disparadas por filas internas no hub de tarefas do aplicativo de funções. Usar filas dessa maneira fornece garantias de entrega de mensagem “pelo menos uma vez”. Há dois tipos de filas nas Funções Duráveis: a fila de controle e a fila de itens de trabalho.

A fila de item de trabalho

Há uma fila de itens de trabalho por hub de tarefas nas Funções Duráveis. Essa é uma fila básica, que se comporta da mesma forma que qualquer outra fila queueTrigger no Azure Functions. Essa fila é usada para disparar funções de atividade sem estado para remover da fila uma mensagem única por vez. Cada uma dessas mensagens contém entradas de função de atividades e metadados adicionais, como a função para executar. Quando um aplicativo do Durable Functions é expandido para várias VMs, todas essas VMs concorrem para obter tarefas da fila de itens de trabalho.

Fila(s) de controle

Há várias filas de controle por hub de tarefa em Funções Duráveis. Uma fila de controle é mais sofisticada do que as filas de itens de trabalho mais simples. As filas de controle são usadas para disparar as funções de orquestrador com estado e de entidade. Como as instâncias de função de orquestrador e de entidade são singletons com estado, é importante que cada orquestração ou entidade seja processada somente por uma função de trabalho por vez. Para ativar essa restrição, cada instância de orquestração ou entidade é atribuída a apenas uma fila de controle. Essas filas de controle têm balanceamento de carga entre os trabalhos para garantir que cada fila seja processada somente por um trabalho por vez. Para obter mais detalhes sobre esse comportamento, verifique as seções subsequentes.

Filas de controle contêm uma variedade de tipos de mensagem de ciclo de vida de orquestração. Exemplos incluem mensagens de controle de orquestrador, mensagens de resposta de função de atividade e mensagens de temporizador. Até 32 mensagens serão removidas da fila de uma fila de controle em uma única chamada seletiva. Essas mensagens contêm dados de conteúdo, bem como metadados, incluindo qual instância de orquestração é destinada. Se várias mensagens removidas da fila destinam-se à mesma instância de orquestração, será processado como um lote.

As mensagens da fila de controle são sondadas constantemente, usando um thread em segundo plano. O tamanho do lote de cada sondagem de fila é controlado pela configuração controlQueueBatchSize em host.json e tem um padrão de 32 (o valor máximo compatível com as Filas do Azure). O número máximo de mensagens de fila de controle pré-buscadas que são armazenadas em buffer na memória é controlado pela configuração controlQueueBufferThreshold em host.json. O valor padrão para controlQueueBufferThreshold varia dependendo de diversos fatores, incluindo o tipo de plano de hospedagem. Para obter mais informações sobre essas configurações, confira a documentação do esquema de host.json.

Dica

O aumento do valor de controlQueueBufferThreshold permite que uma orquestração ou entidade processe eventos mais rapidamente. No entanto, o aumento desse valor também pode resultar em maior uso de memória. O maior uso de memória se deve, em parte, ao pull de mais mensagens da fila e, em parte, à busca de mais históricos de orquestração na memória. A redução do valor para controlQueueBufferThreshold pode, portanto, ser uma forma eficaz de reduzir o uso de memória.

Sondagem de fila

A extensão de tarefa durável implementa um algoritmo exponencial aleatório de retirada para reduzir o efeito de sondagem de fila ociosa nos custos das transações de armazenamento. Quando uma mensagem é encontrada, o runtime verifica imediatamente se há outra mensagem. Quando nenhuma mensagem for encontrada, ele aguardará um período de tempo antes de tentar novamente. Após subsequentes tentativas falhas para obter uma mensagem da fila, o tempo de espera continua a aumentar até atingir o tempo de espera máximo, cujo padrão é de 30 segundos.

O atraso de sondagem máximo é configurável por meio da propriedade maxQueuePollingInterval no arquivo host.json. Configurar essa propriedade com um valor mais alto pode resultar em latências de processamento de mensagens mais altas. As latências mais altas são esperadas somente após períodos de inatividade. Configurar essa propriedade com um valor mais baixo pode resultar em custos de armazenamento mais altos devido a maiores transações de armazenamento.

Observação

Durante a execução nos planos de consumo Azure Functions e Premium, o controlador de escala do Azure Functions sondará uma vez cada controle e fila de itens de trabalho a cada 10 segundos. Essa sondagem adicional é necessária para determinar quando ativar instâncias do aplicativo de funções e tomar decisões de escala. Durante a gravação, esse intervalo de 10 segundos é constante e não pode ser configurado.

Atrasos de início da Orquestração

As instâncias de orquestrações são iniciadas ao colocar uma mensagem ExecutionStarted em uma das filas de controle do hub de tarefas. Em determinadas condições, você observará atrasos de vários segundos entre o agendamento da execução de uma orquestração e o momento em que ela realmente começa a ser executada. Durante esse intervalo de tempo, a instância de orquestração permanece no estado Pending. Há duas possíveis causas para esse atraso:

  • Filas de controle com lista de pendências: se a fila de controle dessa instância tiver um grande número de mensagens, pode levar um tempo até que a mensagem ExecutionStarted seja recebida e processada pelo runtime. As listas de pendências de mensagens podem ocorrer quando as orquestrações estão processando diversos eventos simultaneamente. Os eventos que entram para a fila de controle incluem eventos de início de orquestração, conclusões de atividade, temporizadores duráveis, encerramento e eventos externos. Se esse atraso ocorrer em circunstâncias normais, considere a criação de um novo hub de tarefas com um número maior de partições. Configurar mais partições fará com que o runtime crie outras filas de controle para a distribuição de carga. Cada partição corresponde a 1:1 com uma fila de controle, com o máximo de 16 partições.

  • Atrasos de sondagem de retirada: outra causa comum de atrasos de orquestração é o comportamento de sondagem de retirada descrito anteriormente para filas de controle. No entanto, esse atraso é esperado somente quando um aplicativo é escalado horizontalmente para duas ou mais instâncias. Se houver apenas uma instância de aplicativo, ou se a instância do aplicativo que inicia a orquestração também for a mesma instância que faz a sondagem da fila de controle de destino, não haverá um atraso de sondagem de fila. Os atrasos de sondagem de retirada podem ser reduzidos com a atualização das configurações de host.jsem, conforme descrito anteriormente.

Blobs

Na maioria dos casos, a Durable Functions não usa os Blobs de Armazenamento do Microsoft Azure para manter os dados. No entanto, filas e tabelas têm limites de tamanho que podem impedir a Durable Functions de manter todos os dados necessários em uma mensagem de fila ou linha de armazenamento. Por exemplo, quando um dado que precisa ser mantido em uma fila é maior que 45 KB quando serializado, a Durable Functions compactará os dados e os armazenará em um blob. Ao persistir dados no armazenamento de blobs dessa forma, a função durável armazena uma referência a esse blob na linha da tabela ou na mensagem da fila. Quando a Durable Functions precisa recuperar os dados, ela será obtida automaticamente no blob. Esses blobs são armazenados no contêiner de blobs <taskhub>-largemessages.

Considerações sobre o desempenho

As etapas de compactação extra e operação de blob para mensagens grandes podem ser caras em termos de custos de latência de CPU e E/S. Além disso, a Durable Functions precisa carregar dados persistentes na memória e pode fazer isso para muitas execuções de função diferentes ao mesmo tempo. Como resultado, a persistência de grandes cargas de dados pode causar um alto uso de memória também. Para minimizar a sobrecarga de memória, considere a possibilidade de manter cargas de dados grandes manualmente (por exemplo, no armazenamento de blobs) e, em vez disso, passar referências a esses dados. Dessa forma, seu código pode carregar os dados somente quando necessário para evitar cargas redundantes durante as repetições de função do orchestrator. No entanto, não é recomendável armazenar as cargas em discos locais porque o estado em disco não terá garantia de disponibilidade, já que as funções poderão executar em diferentes VMs durante o tempo de vida.

Seleção da conta de armazenamento

As filas, as tabelas e os blobs usados por Durable Functions são criados em uma conta de Armazenamento do Microsoft Azure configurada. A conta usada pode ser especificada usando a configuração durableTask/storageProvider/connectionStringName (ou a configuração durableTask/azureStorageConnectionStringName no Durable Functions 1.x) no arquivo host.json.

Durable Functions 2.x

{
  "extensions": {
    "durableTask": {
      "storageProvider": {
        "connectionStringName": "MyStorageAccountAppSetting"
      }
    }
  }
}

Durable Functions 1.x

{
  "extensions": {
    "durableTask": {
      "azureStorageConnectionStringName": "MyStorageAccountAppSetting"
    }
  }
}

Se não estiver especificado, a conta de armazenamento AzureWebJobsStorage padrão é usada. Para cargas de trabalho afetadas pelo desempenho, no entanto, configurar uma conta de armazenamento padrão não é recomendável. Funções duráveis usam o Armazenamento do Microsoft Azure intensamente e usam uma conta de armazenamento dedicado que isola o uso do armazenamento de funções duráveis com o uso interno pelo host de Funções do Microsoft Azure.

Observação

As contas de uso geral Standard do Armazenamento do Azure são necessárias ao usar o provedor do Armazenamento do Azure. Não há suporte para nenhum outro tipo de conta de armazenamento. É altamente recomendável usar contas de armazenamento de uso geral herdado v1 para Durable Functions. As contas de armazenamento v2 mais recentes podem ser significativamente mais caras para cargas de trabalho do Durable Functions. Para obter mais informações sobre os tipos de contas do Armazenamento do Azure, confira a documentação Visão geral da conta de Armazenamento.

Expansão do orquestrador

Embora as funções de atividade possam ser expandidas infinitamente adicionando mais VMs de forma elástica, as instâncias individuais do orquestrador e as entidades estão restritas a uma única partição e o número máximo de partições é limitado pela configuração partitionCount no host.json.

Observação

De modo geral, as funções de orquestrador devem ser leves e não devem precisar de muita capacidade de computação. Por esse motivo, não é necessário criar um grande número de partições de fila de controle para obter uma boa taxa de transferência para orquestrações. A maior parte do trabalho pesado será feita em funções de atividade sem monitoração de estado, que podem ser expandidas infinitamente.

O número de filas do controle é definido no arquivo host.json. O snippet do exemplo a seguir host.json define a propriedade durableTask/storageProvider/partitionCount (ou durableTask/partitionCount no Durable Functions 1.x) como 3. Observe que existem tantas filas de controle quanto partições.

Durable Functions 2.x

{
  "extensions": {
    "durableTask": {
      "storageProvider": {
        "partitionCount": 3
      }
    }
  }
}

Durable Functions 1.x

{
  "extensions": {
    "durableTask": {
      "partitionCount": 3
    }
  }
}

Um hub de tarefa pode ser configurado com entre 1 e 16 partições. Se não for especificado, a contagem de participação padrão 4 será usada.

O aplicativo será dimensionado durante cenários de tráfego baixo, de modo que as partições serão gerenciadas por um pequeno número de trabalhos. Por exemplo, considere o diagrama a seguir.

Scale-in orchestrations diagram

No diagrama anterior, vemos que os orquestradores de 1 a 6 têm balanceamento de carga entre as partições. Da mesma forma, as partições, como atividades, têm balanceamento de carga entre os trabalhos. As partições têm balanceamento de carga entre os trabalhos, independentemente do número de orquestradores que começaram.

Se estiver executando os planos de consumo do Azure Functions ou Elástico Premium ou se tiver configurado o dimensionamento automático baseado em carga, mais trabalhos serão alocados conforme o aumento do tráfego e as partições eventualmente balancearão a carga entre todos os trabalhos. Se continuarmos a escalar horizontalmente, cada partição eventualmente será gerenciada por um único trabalho. As atividades, por outro lado, continuarão com balanceamento de carga em todos os trabalhos. Isso é mostrado na imagem abaixo.

First scaled-out orchestrations diagram

O limite superior do número máximo de orquestrações ativas simultâneas em determinado momento é igual ao número de trabalhos alocados para o aplicativo, multiplicado pelo valor de maxConcurrentOrchestratorFunctions. Esse limite superior pode ser mais preciso quando as partições são totalmente dimensionadas entre os trabalhos. Quando totalmente dimensionado, e como cada trabalho terá apenas uma única instância de host do Functions, o número máximo de instâncias simultâneas do orquestrador ativo será igual ao número de partições multiplicado pelo valor de maxConcurrentOrchestratorFunctions.

Observação

Nesse contexto, ativo significa que uma orquestração ou entidade é carregada na memória e está processando novos eventos. Se a orquestração ou entidade estiver aguardando mais eventos, como o valor retornado de uma função de atividade, ela será descarregada da memória e não será mais considerada ativa. Orquestrações e entidades serão recarregadas posteriormente na memória somente quando houver novos eventos a serem processados. Não há um número máximo prático de orquestrações ou entidades totais que podem ser executadas em apenas uma VM, mesmo se estiverem todas no estado "Em execução". A única limitação é o número de instâncias de orquestração ou de entidade ativas simultaneamente.

A imagem abaixo ilustra um cenário totalmente dimensionado em que mais orquestradores são adicionados, com alguns deles inativos, mostrados em cinza.

Second scaled-out orchestrations diagram

Durante a expansão, as concessões da fila de controle podem ser redistribuídos entre instâncias de host do Functions para garantir que as partições sejam distribuídas uniformemente. Essas concessões são implementadas internamente como concessões de do Armazenamento de Blobs do Azure e garantem que uma instância de orquestração individual ou entidade seja executada em apenas uma instância de host por vez. Se um hub de tarefas estiver configurado com três partições (e, portanto, três filas de controle), as instâncias de orquestração e as entidades poderão ter balanceamento de carga entre todas as três instâncias de host que mantêm a concessão. VMs adicionais podem ser adicionadas para aumentar a capacidade de execução da função de atividade.

O diagrama a seguir ilustra como o host do Azure Functions interage com as entidades de armazenamento em um ambiente expandido.

Scale diagram

Conforme mostrado no diagrama anterior, todas as máquinas virtuais competem por mensagens na fila do item de trabalho. No entanto, apenas três VMs podem adquirir mensagens das filas de controle e cada VM bloqueia uma única fila de controle.

As instâncias de orquestração e as entidades são distribuídas em todas as instâncias de fila do controle. A distribuição é feita usando o hash da ID da instância da orquestração ou do nome da entidade e do par de chaves. As IDs de instância de orquestração são GUIDs aleatórios por padrão, o que garante que as instâncias sejam distribuídas igualmente em todas as filas de controle.

De modo geral, as funções de orquestrador devem ser leves e não devem precisar de muita capacidade de computação. Por esse motivo, não é necessário criar um grande número de partições de fila de controle para obter uma boa taxa de transferência para orquestrações. A maior parte do trabalho pesado será feita em funções de atividade sem monitoração de estado, que podem ser expandidas infinitamente.

Sessões estendidas

Sessões estendidas são um mecanismo de cache que mantêm as orquestrações e as entidades na memória mesmo após concluírem o processamento de mensagens. O efeito típico de habilitar sessões estendidas é uma redução de E/S em relação ao repositório durável subjacente e uma taxa de transferência geral aprimorada.

As sessões estendidas podem ser ativadas ao configurar durableTask/extendedSessionsEnabled para true no arquivo host.json. A configuração durableTask/extendedSessionIdleTimeoutInSeconds é usada para controlar quanto tempo uma sessão ociosa será mantida na memória:

Funções 2.0

{
  "extensions": {
    "durableTask": {
      "extendedSessionsEnabled": true,
      "extendedSessionIdleTimeoutInSeconds": 30
    }
  }
}

Funções 1.0

{
  "durableTask": {
    "extendedSessionsEnabled": true,
    "extendedSessionIdleTimeoutInSeconds": 30
  }
}

Há duas possíveis desvantagens dessa configuração que devem ser consideradas:

  1. Há um aumento geral no uso de memória do aplicativo de funções porque as instâncias ociosas não são descarregadas da memória tão rapidamente.
  2. Pode haver uma diminuição geral na taxa de transferência em caso de várias execuções de função do orquestrador ou de entidade simultâneas e distintas de curta duração.

Por exemplo, se durableTask/extendedSessionIdleTimeoutInSeconds é definido como 30 segundos, um episódio de função do orquestrador ou de entidade de curta duração que é executado em menos de 1 segundo ainda ocupará a memória por 30 segundos. Ele também afeta a cota durableTask/maxConcurrentOrchestratorFunctions mencionada anteriormente, impedindo que outras funções do orquestrador ou de entidade sejam executadas.

Os efeitos específicos das sessões estendidas nas funções do orquestrador e de entidade são descritos nas próximas seções.

Observação

No momento, há suporte para sessões estendidas apenas em linguagens .NET, como C# ou F#. A configuração de extendedSessionsEnabled para true para outras plataformas pode resultar em problemas de runtime, como falha silenciosa ao executar as funções disparadas pela orquestração e atividade.

Reprodução de função do Orchestrator

Conforme mencionado anteriormente, as funções do orquestrador são repetidas usando o conteúdo da tabela Histórico. Por padrão, o código de função do orquestrador é repetido sempre que um lote de mensagens for removido da fila de uma fila de controle. Mesmo se estiver usando o padrão fan-out e fan-in e estiver aguardando que todas as tarefas sejam concluídas (por exemplo, usando Task.WhenAll() em .NET, context.df.Task.all() em JavaScript ou context.task_all() em Python), haverá repetições que ocorrem à medida que os lotes de respostas de tarefa são processados ao longo do tempo. Quando sessões estendidas são habilitadas, instâncias de função do orquestrador são mantidas na memória por mais tempo e novas mensagens podem ser processadas sem uma reprodução do histórico completa.

A melhoria de desempenho de sessões estendidas costuma ser observada nas seguintes situações:

  • Quando há um número limitado de instâncias de orquestração em execução simultânea.
  • Quando as orquestrações têm um grande número de ações sequenciais (por exemplo, centenas de chamadas de função de atividade) que são concluídas rapidamente.
  • Quando as orquestrações fan-out e fan-in um grande número de ações concluídas ao mesmo tempo.
  • Quando as funções de orquestrador precisam processar mensagens grandes ou fazer um processamento de dados intensivo de CPU.

Em todas as outras situações, normalmente não se observa melhoria de desempenho para funções de orquestrador.

Observação

Essas configurações só devem ser usadas depois que uma função do orquestrador for totalmente desenvolvida e testada. O comportamento de reprodução agressiva padrão pode ser útil para detectar violações de restrições de código de função de orquestrador no tempo de desenvolvimento e, portanto, é desabilitado por padrão.

Destinos de desempenho

A tabela a seguir mostra os números de taxa de transferência máximos esperados para os cenários descritos na seção Metas de desempenho no artigo Desempenho e escala.

"Instância" refere-se a uma única instância de uma função do orquestrador em execução em uma única pequena VM (A1) no Serviço do Aplicativo do Azure. Todos os casos, presume-se que sessões estendidas estão habilitadas. Os resultados reais podem variar dependendo do trabalho de CPU ou E/S executado pelo código da função.

Cenário Taxa de transferência máxima
Execução da atividade sequencial 5 atividades por segundo, por instância
Execução de atividade paralela (fan-out) 100 atividades por segundo, por instância
Processamento paralelo de resposta (fan-in) 150 respostas por segunda, por instância
Processamento de evento externo 50 eventos por segunda, por instância
Processamento de operação de entidade 64 operações por segundo

Se você não estiver vendo os números de taxa de transferência esperada e a CPU e uso de memória aparece íntegra, verifique se a causa está relacionada à integridade de sua conta de armazenamento. A extensão de Funções Duráveis pode colocar carga significativa em uma conta de Armazenamento do Microsoft Azure e carga suficientemente altas podem resultar na limitação da conta de armazenamento.

Dica

Em alguns casos, você pode aumentar significativamente a taxa de transferência de eventos externos, fan-in de atividade e operações de entidade aumentando o valor da configuração controlQueueBufferThreshold em host.json. Aumentar esse valor além do padrão faz com que o provedor de armazenamento do Durable Task Framework use mais memória para pré-buscar esses eventos de modo mais agressivo, reduzindo os atrasos associados à remoção de mensagens das filas de controle do Armazenamento do Azure. Para obter mais informações, confira a documentação de referência do host.json.

Processamento de taxa de transferência alta

A arquitetura do back-end do Armazenamento do Azure estabelece determinadas limitações no desempenho e escalabilidade teóricos máximos do Durable Functions. Se o teste mostrar que Durable Functions no Armazenamento do Azure não atenderá aos seus requisitos de taxa de transferência, considere usar o provedor de armazenamento Netherite para Durable Functions.

Para comparar a taxa de transferência alcançável para vários cenários básicos, consulte a seção Cenários básicos da documentação do provedor de armazenamento Netherite.

O back-end de armazenamento do Netherite foi projetado e desenvolvido pela Microsoft Research. Ele usa os Hubs de Eventos do Azure e a tecnologia de banco de dados FASTER nos blobs de páginas do Azure. O design do Netherite permite um processamento de taxa de transferência significativamente mais alto de orquestrações e entidades em comparação com outros provedores. Em alguns cenários de parâmetros de comparação, a taxa de transferência mostrou aumentar em mais de uma ordem de magnitude quando comparada ao provedor padrão do Armazenamento do Azure.

Para obter mais informações sobre os provedores de armazenamento compatíveis com Durable Functions e como eles se comparam, confira a documentação de provedores de armazenamento do Durable Functions.

Próximas etapas