Partilhar via


Lidar com problemas de limitação (429 - erros de "muitas solicitações") nos Aplicativos Lógicos do Azure

Aplica-se a: Aplicativos Lógicos do Azure (Consumo + Padrão)

Se o fluxo de trabalho do seu aplicativo lógico sofrer limitação, o que acontece quando o número de solicitações excede a taxa na qual o destino pode lidar durante um período de tempo específico, você receberá o erro "HTTP 429 Too many requests". A limitação pode criar problemas como processamento de dados atrasado, velocidade de desempenho reduzida e erros como exceder a política de repetição especificada.

Por exemplo, a seguinte ação do SQL Server em um fluxo de trabalho de Consumo mostra um erro 429, que relata um problema de limitação:

Captura de tela mostrando um fluxo de trabalho de Consumo com uma ação do SQL Server que tem um erro 429.

As seções a seguir descrevem os níveis comuns nos quais seu fluxo de trabalho pode sofrer limitação:

Limitação de recursos da aplicação lógica

Os Aplicativos Lógicos do Azure têm seus próprios limites de taxa de transferência. Se o recurso do aplicativo lógico exceder esses limites, o recurso do aplicativo lógico será limitado, não apenas uma instância ou execução específica do fluxo de trabalho.

Para localizar eventos de limitação neste nível, siga estes passos:

  1. No portal do Azure, abra seu recurso de aplicativo lógico.

  2. No menu de recursos do aplicativo lógico, em Monitoramento, selecione Métricas.

  3. Em Título do gráfico, selecione Adicionar métrica, que adiciona outra barra métrica ao gráfico.

  4. Na primeira barra métrica, na lista Métrica , selecione Eventos limitados de ação. Na lista Agregação, selecione Contagem.

  5. Na segunda barra de métricas, na lista Métrica , selecione Acionar eventos limitados. Na lista Agregação, selecione Contagem.

O gráfico agora mostra eventos limitados para ações e gatilhos no fluxo de trabalho do aplicativo lógico. Para obter mais informações, consulte Exibir métricas de integridade e desempenho do fluxo de trabalho em Aplicativos Lógicos do Azure.

Para lidar com a limitação nesse nível, você tem as seguintes opções:

  • Limite o número de instâncias de fluxo de trabalho que podem ser executadas ao mesmo tempo.

    Por padrão, se a condição de gatilho do fluxo de trabalho for atendida mais de uma vez ao mesmo tempo, várias instâncias desse gatilho serão acionadas e executadas simultaneamente ou em paralelo. Cada instância de gatilho é acionada antes que a instância de fluxo de trabalho anterior termine a execução.

    Embora o número padrão de instâncias de gatilho que podem ser executadas simultaneamente seja ilimitado, você pode limitar esse número ativando a configuração de simultaneidade do gatilho e, se necessário, selecionar um limite diferente do valor padrão.

  • Habilite o modo de alta taxa de transferência.

  • Desative o desprocessamento de lotes de matriz ou o comportamento "Dividir em" em gatilhos.

    Se um gatilho retornar uma matriz para as ações de fluxo de trabalho restantes processarem, a configuração Dividir em do gatilho dividirá os itens da matriz e iniciará uma instância de fluxo de trabalho para cada item da matriz. Esse comportamento efetivamente dispara várias execuções simultâneas até o limite Split On.

    Para controlar a limitação, desative o comportamento Split On do gatilho e faça com que seu fluxo de trabalho processe toda a matriz com uma única chamada, em vez de lidar com um único item por chamada.

  • Refatore ações em vários fluxos de trabalho menores.

    Como mencionado anteriormente, um fluxo de trabalho do aplicativo lógico de consumo é limitado a um número padrão de ações que podem ser executadas durante um período de 5 minutos. Embora você possa aumentar esse limite habilitando o modo de alta taxa de transferência, também pode considerar se deseja dividir as ações do fluxo de trabalho em fluxos de trabalho menores para que o número de ações executadas em cada fluxo de trabalho permaneça abaixo do limite. Dessa forma, você reduz a carga em um único fluxo de trabalho e distribui a carga em vários fluxos de trabalho. Essa solução funciona melhor para ações que lidam com grandes conjuntos de dados ou geram tantas ações em execução simultânea, iterações de loop ou ações dentro de cada iteração de loop que excedem o limite de execução de ações.

    Por exemplo, o fluxo de trabalho de Consumo a seguir faz todo o trabalho para obter tabelas de um banco de dados do SQL Server e obtém as linhas de cada tabela. O loop For each simultaneamente itera através de cada tabela para que a ação Obter linhas retorne as linhas de cada tabela. Com base nas quantidades de dados nessas tabelas, essas ações podem exceder o limite de execuções de ações.

    Captura de tela mostrando o fluxo de trabalho de consumo

    Após a refatoração, o fluxo de trabalho original é dividido em um fluxo de trabalho pai e um fluxo de trabalho filho.

    O fluxo de trabalho pai a seguir obtém as tabelas do SQL Server e, em seguida, chama o fluxo de trabalho filho para cada tabela para obter as linhas:

    Captura de tela mostrando o fluxo de trabalho pai de consumo que obtém as tabelas do SQL Server e chama o fluxo de trabalho filho.

    O fluxo de trabalho filho a seguir é chamado pelo fluxo de trabalho pai para obter as linhas de cada tabela:

    Captura de tela mostrando o fluxo de trabalho filho de consumo que obtém as linhas de cada tabela.

Limitação do conector

Cada conector tem seus próprios limites de limitação, que você pode encontrar na página de referência técnica de cada conector. Por exemplo, o conector do Barramento de Serviço do Azure tem um limite de limitação que permite até 6.000 chamadas por minuto, enquanto o conector do SQL Server tem limites de limitação que variam com base no tipo de operação.

Alguns gatilhos e ações, como HTTP, têm uma "política de repetição" que você pode personalizar com base nos limites da política de repetição para implementar o tratamento de exceções. Esta política especifica se e com que frequência um gatilho ou ação tenta novamente uma solicitação quando a solicitação original falha ou expira e resulta em uma resposta 408, 429 ou 5xx. Assim, quando a limitação é iniciada e retorna um erro 429, os Aplicativos Lógicos seguem a política de repetição quando suportada.

Para saber se um gatilho ou ação suporta políticas de repetição, verifique as configurações do gatilho ou da ação. Para ver as tentativas de repetição de um gatilho ou ação, aceda ao histórico de execuções da aplicação lógica, selecione a execução que pretende rever e expanda esse gatilho ou ação para ver detalhes sobre entradas, saídas e quaisquer tentativas.

O exemplo de fluxo de trabalho de consumo a seguir mostra onde você pode encontrar essas informações para uma ação HTTP:

Captura de tela mostrando o fluxo de trabalho de Consumo com o histórico de execução, tentativas, entradas e saídas de uma ação HTTP.

Embora o histórico de novas tentativas forneça informações de erro, você pode ter problemas para diferenciar entre a limitação do conector e a limitação de destino. Nesse caso, talvez seja necessário revisar os detalhes da resposta ou executar alguns cálculos de intervalo de limitação para identificar a origem.

Para fluxos de trabalho de aplicativos lógicos de consumo em Aplicativos Lógicos do Azure multilocatário, a limitação acontece no nível da conexão .

Para lidar com a limitação nesse nível, você tem as seguintes opções:

  • Configure várias conexões para uma única ação para que o fluxo de trabalho possa particionar os dados para processamento.

    Considere se você pode distribuir a carga de trabalho dividindo as solicitações de uma ação em várias conexões para o mesmo destino usando as mesmas credenciais.

    Por exemplo, suponha que seu fluxo de trabalho obtém tabelas de um banco de dados do SQL Server e, em seguida, obtém as linhas de cada tabela. Com base no número de linhas que você precisa processar, você pode usar várias conexões e vários loops For each para dividir o número total de linhas em conjuntos menores para processamento. Este cenário usa dois loops For each para dividir o número total de linhas ao meio. O primeiro Para cada loop usa uma expressão que obtém a primeira metade. O outro Para cada loop usa uma expressão diferente que obtém a segunda metade, por exemplo:

    • Expressão 1: A take() função obtém a frente de uma coleção. Para obter mais informações, consulte a take() função.

      @take(collection-or-array-name, div(length(collection-or-array-name), 2))

    • Expressão 2: A skip() função remove a frente de uma coleção e retorna todos os outros itens. Para obter mais informações, consulte a skip() função.

      @skip(collection-or-array-name, div(length(collection-or-array-name), 2))

      O exemplo de fluxo de trabalho Consumo a seguir mostra como você pode usar essas expressões:

      Captura de tela mostrando um fluxo de trabalho de Consumo que usa várias conexões para uma única ação.

  • Configure uma conexão diferente para cada ação.

    Considere se você pode distribuir a carga de trabalho espalhando as solicitações de cada ação por sua própria conexão, mesmo quando as ações se conectam ao mesmo serviço ou sistema e usam as mesmas credenciais.

    Por exemplo, suponha que seu fluxo de trabalho obtém as tabelas de um banco de dados do SQL Server e obtém cada linha em cada tabela. Você pode usar conexões separadas para que a obtenção das tabelas use uma conexão, enquanto a obtenção de cada linha usa outra conexão.

    O exemplo a seguir mostra um fluxo de trabalho Consumption que cria e usa uma conexão diferente para cada ação:

    Captura de tela mostrando um fluxo de trabalho de Consumo que cria e usa uma conexão diferente para cada ação.

  • Altere a simultaneidade ou paralelismo em um loop "Para cada um".

    Por padrão, as iterações de loop "Para cada" são executadas ao mesmo tempo até o limite de simultaneidade. Se você tiver uma conexão que está sendo limitada dentro de um loop "Para cada um", você pode reduzir o número de iterações de loop que são executadas em paralelo. Para obter mais informações, veja a seguinte documentação:

Serviço de destino ou limitação do sistema

Embora um conector tenha seus próprios limites de limitação, o serviço ou sistema de destino chamado pelo conector também pode ter limites de limitação. Por exemplo, algumas APIs no Microsoft Exchange Server têm limites de limitação mais rígidos do que o conector do Outlook do Office 365.

Por padrão, as instâncias de fluxo de trabalho de um aplicativo lógico e quaisquer loops ou ramificações dentro dessas instâncias são executados em paralelo. Esse comportamento significa que várias instâncias podem chamar o mesmo ponto de extremidade ao mesmo tempo. Cada instância não sabe sobre a existência da outra, portanto, as tentativas de repetir ações com falha podem criar condições de corrida em que várias chamadas tentam ser executadas ao mesmo tempo, mas para serem bem-sucedidas, essas chamadas devem chegar ao serviço ou sistema de destino antes que a limitação comece a acontecer.

Por exemplo, suponha que você tenha uma matriz que tenha 100 itens. Você usa um loop "For each" para iterar através da matriz e ativar o controle de simultaneidade do loop para que você possa restringir o número de iterações paralelas para 20 ou o limite padrão atual. Dentro desse loop, uma ação insere um item da matriz em um banco de dados do SQL Server, que permite apenas 15 chamadas por segundo. Esse cenário resulta em um problema de limitação porque uma lista de pendências de tentativas se acumula e nunca chega a ser executada.

A tabela a seguir descreve a linha do tempo do que acontece no loop quando o intervalo de repetição da ação é de 1 segundo:

Ponto no tempo Número de ações executadas Número de ações que falham Número de novas tentativas em espera
T + 0 segundos 20 inserções 5 falham, devido ao limite SQL 5 repetições
T + 0,5 segundos 15 inserções, devido a 5 repetições anteriores à espera Todos os 15 falham, devido ao limite SQL anterior ainda em vigor por mais 0,5 segundos 20 repetições
(anterior 5 + 15 novo)
T + 1 segundo 20 inserções 5 reprovações mais 20 tentativas anteriores, devido ao limite SQL 25 repetições (anteriores 20 + 5 novas)

Para lidar com a limitação nesse nível, você tem as seguintes opções:

  • Crie fluxos de trabalho individuais para que cada um lide com uma única operação.

    • Continuando com o cenário de exemplo do SQL Server nesta seção, você pode criar um fluxo de trabalho que coloca itens de matriz em uma fila, como uma fila do Barramento de Serviço do Azure. Em seguida, crie outro fluxo de trabalho que execute apenas a operação de inserção para cada item nessa fila. Dessa forma, apenas uma instância de fluxo de trabalho é executada a qualquer momento específico, o que conclui a operação de inserção e passa para o próximo item na fila, ou a instância recebe 429 erros, mas não tenta tentativas improdutivas.

    • Crie um fluxo de trabalho pai que chame um fluxo de trabalho filho ou aninhado para cada ação. Se o pai precisar chamar fluxos de trabalho filho diferentes com base no resultado do pai, você poderá usar uma ação de condição ou uma ação de alternância que determine qual fluxo de trabalho filho chamar. Esse padrão pode ajudá-lo a reduzir o número de chamadas ou operações.

      Por exemplo, suponha que você tenha dois fluxos de trabalho, cada um com um gatilho de sondagem que verifica sua conta de e-mail a cada minuto para um assunto específico, como "Sucesso" ou "Fracasso". Esta configuração resulta em 120 chamadas por hora. Em vez disso, se você criar um fluxo de trabalho pai único que sonda a cada minuto, mas chama um fluxo de trabalho filho que é executado com base no assunto "Sucesso" ou "Falha", você reduz o número de verificações de sondagem para metade, ou 60 neste caso.

  • Configure o processamento em lote. (Apenas fluxos de trabalho de consumo)

    Se o serviço de destino oferecer suporte a operações em lote, você poderá abordar a limitação processando itens em grupos ou lotes, em vez de individualmente. Para implementar a solução de processamento em lote, crie um fluxo de trabalho de aplicativo lógico de "recetor de lote" e um fluxo de trabalho de aplicativo lógico de "remetente de lote". O remetente do lote coleta mensagens ou itens até que seus critérios especificados sejam atendidos e, em seguida, envia essas mensagens ou itens em um único grupo. O recetor do lote aceita esse grupo e processa essas mensagens ou itens. Para obter mais informações, consulte Processar mensagens em lote em grupos.

  • Use as versões de webhook para gatilhos e ações, em vez das versões de sondagem.

    Porquê? Um gatilho de sondagem continua a verificar o serviço ou sistema de destino em intervalos específicos. Um intervalo muito frequente, como a cada segundo, pode criar problemas de limitação. No entanto, um gatilho ou ação de webhook, como HTTP Webhook, cria apenas uma única chamada para o serviço ou sistema de destino, o que acontece no momento da assinatura e solicita que o destino notifique o gatilho ou ação somente quando um evento acontece. Dessa forma, o gatilho ou ação não precisa verificar continuamente o destino.

    Portanto, se o serviço ou sistema de destino suportar webhooks ou fornecer um conector que tenha uma versão de webhook, essa opção é melhor do que usar a versão de sondagem. Para identificar gatilhos e ações do webhook, confirme se eles têm o ApiConnectionWebhook tipo ou se não exigem que você especifique uma recorrência. Para obter mais informações, consulte APIConnectionWebhook trigger e APIConnectionWebhook action.

Próximos passos