Simultaneidade no Azure Functions

Este artigo descreve os comportamentos de simultaneidade de gatilhos conduzidos por eventos no Azure Functions. Ele também compara os modelos de simultaneidade estáticos e dinâmicos.

Importante

O plano de Consumo Flex está atualmente em versão preliminar.

No Functions, você pode ter vários processos de execução de uma determinada função em execução simultaneamente em uma única instância de computação. Por exemplo, considere um caso em que você tem três funções diferentes em seu aplicativo de funções que são dimensionadas para várias instâncias para lidar com uma carga aumentada. Nesse cenário, cada função está sendo executada em resposta a invocações individuais em todas as três instâncias, e uma determinada instância pode lidar com várias invocações do mesmo tipo. Tenha em mente que as execuções de função em uma única instância compartilham os mesmos recursos de memória, CPU e conexão. Como várias execuções de função podem ser executadas em cada instância simultaneamente, cada função precisa ter uma maneira de gerenciar o número de execuções simultâneas.

Quando seu aplicativo está hospedado em um plano de escala dinâmica (Consumo, Consumo Flex ou Premium), o host dimensiona o número de instâncias do aplicativo de funções para cima ou para baixo com base no número de eventos de entrada. Para saber mais, consulte dimensionamento controlado por eventos. Quando hospeda funções em um plano dedicado (Serviço de Aplicativo), você configura manualmente as instâncias ou configura um esquema de dimensionamento automático.

Essas decisões de escala também são diretamente afetadas pela simultaneidade das execuções em uma determinada instância. Quando um aplicativo em um plano de escala dinâmica atinge um limite de simultaneidade, talvez seja necessário dimensionar para acompanhar a demanda de entrada.

O Functions fornece duas maneiras principais de gerenciar a simultaneidade:

  • Simultaneidade estática: você pode configurar limites de nível de host na simultaneidade, que são específicos para gatilhos individuais. Esse é o comportamento de simultaneidade padrão para o Functions.

  • Simultaneidade dinâmica: para determinados tipos de gatilho, o host do Functions pode determinar automaticamente o melhor nível de simultaneidade para esse gatilho em seu aplicativo. Você deve aceitar esse modelo de simultaneidade.

Simultaneidade estática

Por padrão, a maioria dos gatilhos dá suporte a um modelo de configuração estática no nível do host. Nesse modelo, cada tipo de gatilho tem um limite de simultaneidade por instância. No entanto, para a maioria dos gatilhos, você também pode solicitar uma simultaneidade específica por instância para esse tipo de gatilho. Por exemplo, o gatilho do Barramento de Serviço oferece uma configuração MaxConcurrentCalls e MaxConcurrentSessions no arquivo host.json. Essas configurações juntas controlam o número máximo de mensagens que cada função processa simultaneamente em cada instância. Outros tipos de gatilho têm mecanismos integrados para invocações de balanceamento de carga entre instâncias. Por exemplo, os Hubs de Eventos e o Azure Cosmos DB usam um esquema baseado em partição.

Para tipos de gatilho que dão suporte à configuração de simultaneidade, as configurações escolhidas são aplicadas a todas as instâncias em execução. Isso permite que você controle a simultaneidade máxima para suas funções em cada instância. Por exemplo, quando sua função é de CPU ou com uso intensivo de recursos, você pode optar por limitar a simultaneidade para manter as instâncias íntegras e depender do dimensionamento para lidar com o aumento de cargas. Da mesma forma, quando a função faz solicitações para um serviço downstream que está sendo limitado, você também deve considerar limitar a simultaneidade.

Simultaneidade do gatilho HTTP

aplica-se somente ao plano de Consumo Flex (versão prévia)

O plano Consumo Flex dimensiona todas as funções de gatilho HTTP juntas como um grupo. Para obter mais informações, consulte dimensionamento por função. A tabela a seguir indica a configuração de simultaneidade padrão para gatilhos HTTP em uma determinada instância, com base no tamanho de memória da instância de configurado.

Tamanho da instância (MB) * simultaneidade padrão
2048 16
4096 32

*Para aplicativos Python, a simultaneidade de gatilho HTTP padrão para todos os tamanhos de instâncias é 1.

Esses padrões devem funcionar bem para a maioria dos casos e você começa com eles. Considere que, em um determinado número de solicitações HTTP, aumentar o valor de simultaneidade HTTP reduz o número de instâncias necessárias para lidar com solicitações HTTP. Da mesma forma, diminuir o valor de simultaneidade HTTP requer mais instâncias para lidar com a mesma carga.

Se você precisar ajustar a simultaneidade HTTP, poderá fazer isso usando a CLI do Azure. Para obter mais informações, consulte Definir limites de simultaneidade HTTP.

Os valores de simultaneidade padrão na tabela anterior só se aplicam quando você não definiu sua própria configuração de simultaneidade HTTP. Quando você não definiu explicitamente uma configuração de simultaneidade HTTP, a simultaneidade padrão aumenta conforme mostrado na tabela quando você altera o tamanho da instância. Depois de definir especificamente um valor de simultaneidade HTTP, esse valor será mantido apesar das alterações no tamanho da instância.

Determinar a simultaneidade estática ideal

Embora as configurações de simultaneidade estática forneçam controle de determinados comportamentos de gatilho, como a limitação de suas funções, pode ser difícil determinar os valores ideais para essas configurações. Em geral, você precisa chegar a valores aceitáveis por um processo iterativo de teste de carga. Mesmo depois de determinar um conjunto de valores que estão funcionando para um perfil de carga específico, o número de eventos que chegam de seus serviços conectados pode mudar de dia para dia. Devido a essa variabilidade, é possível que o aplicativo seja executado com valores abaixo do ideal. Por exemplo, talvez o aplicativo de funções processe cargas de mensagens particularmente exigentes no último dia da semana, o que exige a limitação da simultaneidade. No entanto, durante o restante da semana, os payloads de mensagem são mais simples, o que significa que você pode usar um nível de simultaneidade mais alto no restante da semana.

O ideal é que o sistema permita que as instâncias processem o máximo de trabalho possível, mantendo cada instância íntegra e latências baixas, que é a função da simultaneidade dinâmica.

Simultaneidade dinâmica

O Functions agora oferece um modelo de simultaneidade dinâmica que simplifica a configuração da simultaneidade para todos os aplicativos de funções em execução no mesmo plano.

Observação

Atualmente, a simultaneidade dinâmica só tem suporte para os gatilhos Blob do Azure, Fila do Azure e Barramento de Serviço e exige que você use as versões listadas na seção de suporte à extensão abaixo.

Benefícios

O uso da simultaneidade dinâmica oferece os seguintes benefícios:

  • Configuração simplificada: você não precisa mais determinar manualmente as configurações de simultaneidade por gatilho. O sistema aprende os valores ideais para a carga de trabalho ao longo do tempo.
  • Ajustes dinâmicos: a simultaneidade é ajustada dinamicamente em tempo real, o que permite que o sistema se adapte a padrões de carga alterados ao longo do tempo.
  • Proteção de integridade da instância: o runtime limita a simultaneidade aos níveis que uma instância do aplicativo de funções pode manipular de maneira confortável. Isso impede que o aplicativo se sobrecarregue assumindo mais trabalho do que deve.
  • Taxa de transferência aprimorada: a taxa de transferência geral foi aprimorada porque as instâncias individuais não estão assumindo mais trabalho do que podem processar rapidamente. Isso permite o balanceamento mais efetivo da carga entre instâncias. Para funções que podem lidar com cargas mais altas, uma taxa de transferência mais alta pode ser obtida aumentando a simultaneidade para valores acima da configuração padrão.

Configuração de simultaneidade dinâmica

A simultaneidade dinâmica pode ser habilitada no nível do host no arquivo host.json. Quando habilitado, os níveis de simultaneidade de todas as extensões de associação que dão suporte a esse recurso são ajustados automaticamente conforme necessário. Nesses casos, as configurações de simultaneidade dinâmica substituem as configurações de simultaneidade configuradas manualmente.

Por padrão, a simultaneidade dinâmica está desabilitada. Com a simultaneidade dinâmica habilitada, a simultaneidade começa em 1 para cada função e é ajustada até um valor ideal, que é determinado pelo host.

Para habilitar a simultaneidade dinâmica em um aplicativo de funções, adicione as seguintes configurações ao arquivo host.json:

    { 
        "version": "2.0", 
        "concurrency": { 
            "dynamicConcurrencyEnabled": true, 
            "snapshotPersistenceEnabled": true 
        } 
    } 

Quando SnapshotPersistenceEnabled é true, que é o padrão, os valores de simultaneidade aprendidos são gravados periodicamente no armazenamento, de modo que novas instâncias começam com esses valores em vez de começar de 1 e refazer o aprendizado.

Gerenciador de simultaneidade

Nos bastidores, quando a simultaneidade dinâmica está habilitada, há um processo gerenciador de simultaneidade em execução em segundo plano. Esse gerente monitora constantemente as métricas de integridade da instância, como a utilização da CPU e de threads, e altera as limitações conforme necessário. Quando uma ou mais limitações estão habilitadas, a simultaneidade de função é reduzida até que o host esteja íntegro novamente. Quando as limitações estão desabilitadas, a simultaneidade pode aumentar. Várias heurísticas são usadas para aumentar ou reduzir a simultaneidade, de maneira inteligente, com base nessas limitações. Ao longo do tempo, a simultaneidade de cada função se estabiliza em um nível específico.

Os níveis de simultaneidade são gerenciados para cada função individual. Assim, o sistema balanceia funções com uso intensivo de recursos, que exigem um nível baixo de simultaneidade, e funções mais leves, que podem lidar com simultaneidade mais alta. O equilíbrio de simultaneidade para cada função ajuda a manter a integridade geral da instância do aplicativo de funções.

Quando a simultaneidade dinâmica está habilitada, as decisões correspondentes aparecem nos logs. Por exemplo, os logs mostram a habilitação de várias limitações, bem como o aumento ou a redução da simultaneidade de cada função. Os logs são gravados na categoria de log Host.Concurrency da tabela de rastreamentos.

Suporte de extensão

A simultaneidade dinâmica é habilitada para um aplicativo de funções no nível do host, e todas as extensões que dão suporte para a simultaneidade dinâmica são executadas nesse modo. A simultaneidade dinâmica requer colaboração entre o host e as extensões de gatilho individuais. Apenas as versões listadas das extensões a seguir dão suporte para a simultaneidade dinâmica.

Extensão Versão Descrição
Armazenamento de filas versão 5.x (extensão de armazenamento) O gatilho de armazenamento de Filas do Azure tem o próprio loop de sondagem de mensagens. Ao usar a configuração estática, a simultaneidade é regida pelas opções de configuração BatchSize/NewBatchThreshold. Ao usar a simultaneidade dinâmica, esses valores de configuração são ignorados. A simultaneidade dinâmica é integrada ao loop de mensagem, portanto, o número de mensagens buscadas por iteração é ajustado dinamicamente. Quando as acelerações são habilitadas (o host está sobrecarregado), o processamento de mensagens será colocado em pausa até que as acelerações sejam desabilitadas. Quando as limitações estão desabilitadas, a simultaneidade aumentará.
Armazenamento de Blobs versão 5.x (extensão de armazenamento) Internamente, o gatilho de armazenamento de Blobs do Azure usa a mesma infraestrutura que o Gatilho de Fila do Azure. Quando blobs novos/atualizados precisam ser processados, as mensagens são escritas em uma fila de controle gerenciado de plataforma e essa fila é processada usando a mesma lógica usada para QueueTrigger. Quando a simultaneidade dinâmica estiver habilitada, a simultaneidade para o processamento dessa fila de controle será gerenciada dinamicamente.
Barramento de Serviço versão 5.x O gatilho do Barramento de Serviço atualmente dá suporte para três modelos de execução. A simultaneidade dinâmica afeta esses modelos de execução da seguinte forma:

Processamento de fila/tópico de expedição único: cada invocação da função processa uma única mensagem. Ao usar a configuração estática, a simultaneidade é governada pela opção MaxConcurrentCalls de configuração. Quando a simultaneidade dinâmica é usada, esse valor de configuração é ignorado e a simultaneidade é ajustada dinamicamente.
Processamento de fila/tópico de expedição única baseado em sessão: cada invocação da função processa uma só mensagem. Dependendo do número de sessões ativas no tópico/fila, cada instância recebe uma ou mais sessões como concessão. As mensagens em cada sessão são processadas em série para garantir a ordenação. Quando a simultaneidade dinâmica não é usada, a simultaneidade é governada pela configuração de MaxConcurrentSessions. Com a simultaneidade dinâmica habilitada, MaxConcurrentSessions é ignorado e o número de sessões que cada instância processa é ajustado dinamicamente.
Processamento em lotes: cada invocação da função processa um lote de mensagens, regido pela configuração MaxMessageCount. Como as invocações em lote são seriais, a simultaneidade da função disparada em lote é sempre uma e a simultaneidade dinâmica não se aplica.

Próximas etapas

Para saber mais, consulte os recursos a seguir: