Processamento de erros e novas tentativas das Funções do Azure
A manipulação de erros no Azure Functions é importante para ajudá-lo a evitar dados perdidos, evitar eventos perdidos e monitorar a integridade do seu aplicativo. Também é uma maneira importante de ajudá-lo a entender os comportamentos de repetição de gatilhos baseados em eventos.
Este artigo descreve estratégias gerais para tratamento de erros e as estratégias de repetição disponíveis.
Importante
O suporte à política de repetição prévia para determinados gatilhos foi removido em dezembro de 2022. As políticas de repetição para gatilhos suportados agora estão geralmente disponíveis (GA). Para obter uma lista de extensões que atualmente oferecem suporte a políticas de repetição, consulte a seção Repetições .
Processar erros
Os erros que ocorrem em uma função do Azure podem vir de:
- Uso de acionadores e ligações de funções integradas.
- Chamadas para APIs de serviços subjacentes do Azure.
- Chamadas para pontos de extremidade REST.
- Chamadas para bibliotecas de clientes, pacotes ou APIs de terceiros.
Para evitar a perda de dados ou mensagens perdidas, é importante praticar um bom tratamento de erros. Esta tabela descreve algumas práticas recomendadas de tratamento de erros e fornece links para mais informações.
Recomendação | Detalhes |
---|---|
Ativar o Application Insights | O Azure Functions integra-se com o Application Insights para coletar dados de erro, dados de desempenho e logs de tempo de execução. Você deve usar o Application Insights para descobrir e entender melhor os erros que ocorrem em suas execuções de função. Para saber mais, consulte Monitorar o Azure Functions. |
Usar tratamento estruturado de erros | Capturar e registrar erros é fundamental para monitorar a integridade do seu aplicativo. O nível mais alto de qualquer código de função deve incluir um bloco try/catch. No bloco catch, você pode capturar e registrar erros. Para obter informações sobre quais erros podem ser gerados por associações, consulte Códigos de erro de vinculação. Dependendo da sua estratégia de repetição específica, você também pode gerar uma nova exceção para executar a função novamente. |
Planeje sua estratégia de repetição | Várias extensões de vinculação de funções fornecem suporte interno para novas tentativas e outras permitem definir políticas de repetição, que são implementadas pelo tempo de execução do Functions. Para gatilhos que não fornecem comportamentos de repetição, você deve considerar a implementação de seu próprio esquema de repetição. Para obter mais informações, consulte Tentativas. |
Design para idempotência | A ocorrência de erros quando você está processando dados pode ser um problema para suas funções, especialmente quando você está processando mensagens. É importante considerar o que acontece quando o erro ocorre e como evitar o processamento duplicado. Para saber mais, consulte Projetando o Azure Functions para entradas idênticas. |
Tentativas
Há dois tipos de tentativas disponíveis para suas funções:
- Comportamentos de repetição incorporados de extensões de gatilho individuais
- Políticas de repetição fornecidas pelo tempo de execução do Functions
A tabela a seguir indica quais gatilhos suportam novas tentativas e onde o comportamento de repetição está configurado. Ele também links para mais informações sobre erros que vêm dos serviços subjacentes.
Gatilho/vinculação | Fonte de repetição | Configuração |
---|---|---|
Azure Cosmos DB | Políticas de repetição | Nível de função |
Armazenamento de Blobs | Extensão de vinculação | host.json |
Event Grid | Extensão de vinculação | Subscrição do evento |
Hubs de Eventos | Políticas de repetição | Nível de função |
Kafka | Políticas de repetição | Nível de função |
Armazenamento de Filas | Extensão de vinculação | host.json |
RabbitMQ | Extensão de vinculação | Fila de letra morta |
Service Bus | Extensão de vinculação | host.json* |
Temporizador | Políticas de repetição | Nível de função |
*Requer a versão 5.x da extensão do Barramento de Serviço do Azure. Em versões de extensão mais antigas, os comportamentos de repetição são implementados pela fila de letras mortas do Service Bus.
Repetir políticas
O Azure Functions permite definir políticas de repetição para tipos de gatilho específicos, que são impostas pelo tempo de execução. Atualmente, esses tipos de gatilho oferecem suporte a políticas de repetição repetida:
O suporte a tentativas é o mesmo para modelos de programação Python v1 e v2.
As políticas de repetição não são suportadas na versão 1.x do tempo de execução do Functions.
A política de repetição informa ao tempo de execução para executar novamente uma execução com falha até que a conclusão bem-sucedida ocorra ou o número máximo de novas tentativas seja atingido.
Uma política de repetição é avaliada quando uma função executada por um tipo de gatilho suportado gera uma exceção não capturada. Como prática recomendada, você deve capturar todas as exceções em seu código e gerar novas exceções para quaisquer erros que você deseja resultar em uma nova tentativa.
Importante
Os pontos de verificação dos Hubs de Eventos não são gravados até que a política de repetição para a execução seja concluída. Devido a esse comportamento, o progresso na partição específica é pausado até que o processamento do lote atual seja concluído.
A versão 5.x da extensão Hubs de Eventos oferece suporte a recursos adicionais de repetição para interações entre o host de funções e o hub de eventos. Para obter mais informações, consulte clientRetryOptions
a referência host.json Hubs de Eventos.
Estratégias de repetição
Você pode configurar duas estratégias de repetição que são suportadas pela política:
É permitido um período de tempo especificado entre cada nova tentativa.
Ao executar em um plano de consumo, você é cobrado apenas pelo tempo que o código da função está sendo executado. Você não é cobrado pelo tempo de espera entre as execuções em nenhuma dessas estratégias de repetição.
Contagem máxima de tentativas
Você pode configurar o número máximo de vezes que a execução de uma função é repetida antes de uma eventual falha. A contagem de tentativas atual é armazenada na memória da instância.
É possível que uma instância tenha uma falha entre as tentativas de repetição. Quando uma instância falha durante uma política de novas tentativas, a contagem de tentativas é perdida. Quando há falhas de instância, o gatilho de Hubs de Eventos é capaz de retomar o processamento e repetir o lote em uma nova instância, com a contagem de tentativas redefinida para zero. O gatilho do temporizador não é retomado em uma nova instância.
Esse comportamento significa que a contagem máxima de tentativas é um esforço melhor. Em alguns casos raros, uma execução pode ser repetida mais do que o número máximo de vezes solicitado. Para gatilhos de temporizador, as novas tentativas podem ser menores do que o número máximo solicitado.
Exemplos de repetição
São fornecidos exemplos de estratégias de atraso fixo e de recuo exponencial. Para ver exemplos de uma estratégia específica, você deve primeiro selecionar essa estratégia na guia anterior.
As novas tentativas no nível da função são suportadas com os seguintes pacotes NuGet:
- Microsoft.Azure.Functions.Worker.Sdk>= 1.9.0
- Microsoft.Azure.Functions.Worker.Extensions.EventHubs>= 5.2.0
- Microsoft.Azure.Functions.Worker.Extensions.Kafka>= 3.8.0
- Microsoft.Azure.Functions.Worker.Extensions.Timer>= 4.2.0
[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
FunctionContext context)
{
var logger = context.GetLogger(nameof(TimerFunction));
logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus?.Next}");
}
Property | Description |
---|---|
MaxRetryCount | Obrigatório. O número máximo de tentativas permitidas por execução de função. -1 significa tentar novamente indefinidamente. |
DelayInterval | O atraso usado entre tentativas. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
Aqui está um exemplo de uma política de repetição definida no arquivo function.json :
{
"disabled": false,
"bindings": [
{
....
}
],
"retry": {
"strategy": "fixedDelay",
"maxRetryCount": 4,
"delayInterval": "00:00:10"
}
}
Você pode definir estas propriedades em definições de política de novas tentativas:
Property | Description |
---|---|
Estratégia | Obrigatório. A estratégia de repetição a utilizar. Os valores válidos são fixedDelay ou exponentialBackoff . |
maxRetryCount | Obrigatório. O número máximo de tentativas permitidas por execução de função. -1 significa tentar novamente indefinidamente. |
delayInterval | O atraso usado entre novas tentativas quando você está usando uma fixedDelay estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
mínimoIntervalo | O atraso mínimo de repetição quando você está usando uma exponentialBackoff estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
maximumInterval | O atraso máximo de repetição quando você está usando exponentialBackoff a estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
A maneira como você define a política de repetição para o gatilho depende da sua versão Node.js.
Aqui está um exemplo de uma função de gatilho de temporizador que usa uma estratégia de repetição de atraso fixo:
const { app } = require('@azure/functions');
app.timer('timerTriggerWithRetry', {
schedule: '0 */5 * * * *',
retry: {
strategy: 'fixedDelay',
delayInterval: {
seconds: 10,
},
maxRetryCount: 4,
},
handler: (myTimer, context) => {
if (context.retryContext?.retryCount < 2) {
throw new Error('Retry!');
} else {
context.log('Timer function processed request.');
}
},
});
A maneira como você define a política de repetição para o gatilho depende da sua versão Node.js.
Aqui está um exemplo de uma função de gatilho de temporizador que usa uma estratégia de repetição de atraso fixo:
import { app, InvocationContext, Timer } from '@azure/functions';
export async function timerTriggerWithRetry(myTimer: Timer, context: InvocationContext): Promise<void> {
if (context.retryContext?.retryCount < 2) {
throw new Error('Retry!');
} else {
context.log('Timer function processed request.');
}
}
app.timer('timerTriggerWithRetry', {
schedule: '0 */5 * * * *',
retry: {
strategy: 'fixedDelay',
delayInterval: {
seconds: 10,
},
maxRetryCount: 4,
},
handler: timerTriggerWithRetry,
});
Você pode definir estas propriedades em definições de política de novas tentativas:
Property | Description |
---|---|
Estratégia | Obrigatório. A estratégia de repetição a utilizar. Os valores válidos são fixedDelay ou exponentialBackoff . |
maxRetryCount | Obrigatório. O número máximo de tentativas permitidas por execução de função. -1 significa tentar novamente indefinidamente. |
delayInterval | O atraso usado entre novas tentativas quando você está usando uma fixedDelay estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
mínimoIntervalo | O atraso mínimo de repetição quando você está usando uma exponentialBackoff estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
maximumInterval | O atraso máximo de repetição quando você está usando exponentialBackoff a estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
Aqui está um exemplo de uma função de gatilho de temporizador que usa uma estratégia de repetição de atraso fixo:
import logging
from azure.functions import AuthLevel, Context, FunctionApp, TimerRequest
app = FunctionApp(http_auth_level=AuthLevel.ANONYMOUS)
@app.timer_trigger(schedule="*/1 * * * * *", arg_name="mytimer",
run_on_startup=False,
use_monitor=False)
@app.retry(strategy="fixed_delay", max_retry_count="3",
delay_interval="00:00:01")
def mytimer(mytimer: TimerRequest, context: Context) -> None:
logging.info(f'Current retry count: {context.retry_context.retry_count}')
if context.retry_context.retry_count == \
context.retry_context.max_retry_count:
logging.info(
f"Max retries of {context.retry_context.max_retry_count} for "
f"function {context.function_name} has been reached")
else:
raise Exception("This is a retryable exception")
Você pode definir estas propriedades em definições de política de novas tentativas:
Property | Description |
---|---|
Estratégia | Obrigatório. A estratégia de repetição a utilizar. Os valores válidos são fixed_delay ou exponential_backoff . |
max_retry_count | Obrigatório. O número máximo de tentativas permitidas por execução de função. -1 significa tentar novamente indefinidamente. |
delay_interval | O atraso usado entre novas tentativas quando você está usando uma fixed_delay estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
minimum_interval | O atraso mínimo de repetição quando você está usando uma exponential_backoff estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
maximum_interval | O atraso máximo de repetição quando você está usando exponential_backoff a estratégia. Especifique-o como uma cadeia de caracteres com o formato HH:mm:ss . |
@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
@TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
final ExecutionContext context
) {
context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}
Códigos de erro de vinculação
Quando você está integrando com os serviços do Azure, os erros podem ter origem nas APIs dos serviços subjacentes. As informações relacionadas a erros específicos de vinculação estão disponíveis nas seções "Exceções e códigos de retorno" dos seguintes artigos:
- BD do Cosmos para o Azure
- Armazenamento de Blobs
- Event Grid
- Hubs de Eventos
- Hub IoT
- Hubs de Notificação
- Armazenamento de Filas
- Service Bus
- Armazenamento de Tabelas