Tratamento de erros e repetições no Azure Functions
O tratamento de erro no Azure Functions é importante para ajudar a evitar perda de dados, evitar perda de eventos e monitorar a integridade do aplicativo. Também é uma maneira importante de ajudá-lo a entender os comportamentos de repetição de gatilhos baseados em evento.
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 de versão prévia para determinados gatilhos foi removida em dezembro de 2022. As políticas de repetição para gatilhos com suporte agora estão em disponibilidade geral (GA). Para obter uma lista de extensões que atualmente dão suporte a políticas de repetição, consulte a seção Repetições.
Tratar erros
Os erros que ocorrem em uma função do Azure podem vir de:
- Uso de gatilhos e associações integrados do Functions.
- Chamadas para APIs de serviços subjacentes do Azure.
- Chamadas para pontos de extremidade REST.
- Chamadas para bibliotecas de cliente, pacotes ou APIs de terceiros.
Para evitar a perda de dados ou mensagens, é importante seguir as boas práticas de tratamento de erros. Esta tabela descreve algumas práticas recomendadas de tratamento de erros e fornece links para mais informações.
Recomendação | Detalhes |
---|---|
Habilitar o Application Insights | O Azure Functions integra-se ao Application Insights para coletar dados de erro, dados de desempenho e logs de runtime. 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 Azure Functions. |
Usar tratamento de erro estruturado | A captura e o registro em log de erros são essenciais para o monitoramento da 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 associação. Dependendo de sua estratégia de repetição específica, você também pode gerar uma nova exceção para executar a função novamente. |
Planejar sua estratégia de repetição | Várias extensões de associações do Functions fornecem suporte interno para repetições e outras permitem definir políticas de repetição, que são implementadas pelo runtime do Functions. Para gatilhos que não fornecem comportamentos de repetição, considere implementar seu próprio esquema de repetição. Para saber mais, confira Repetições. |
Design para idempotência | A ocorrência de erros durante o processamento de dados pode ser um problema para suas funções, especialmente no processamento de mensagens. É importante considerar o que acontece quando o erro ocorre e como evitar o processamento duplicado. Para saber mais, consulte Como projetar o Azure Functions para obter uma entrada idêntica. |
Novas tentativas
Existem dois tipos de repetições disponíveis para suas funções:
- Comportamentos de repetição internos de extensões de gatilho individuais
- Políticas de repetição fornecidas pelo runtime do Functions
A tabela a seguir indica quais gatilhos suportam tentativas e onde o comportamento de repetição está configurado. Ele também é vinculado a mais informações sobre erros provenientes dos serviços subjacentes.
Gatilho/associação | Origem de repetição | Configuração |
---|---|---|
Azure Cosmos DB | Políticas de repetição | Nível de função |
Armazenamento de Blobs | Extensão de associação | host. JSON |
Grade de Eventos | Extensão de associação | Assinatura 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 associação | host. JSON |
RabbitMQ | Extensão de associação | Fila de mensagens mortas |
Barramento de Serviço | Extensão de associaçã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 mensagens mortas do Barramento de Serviço.
Políticas de repetição
O Azure Functions permite definir políticas de repetição para tipos de gatilho específicos, que são impostas pelo runtime. Atualmente, esses tipos de gatilho dão suporte a políticas de repetição:
O suporte à repetição é o mesmo para modelos de programação do Python v1 e v2.
Não há suporte para as políticas de repetição na versão 1.x do runtime do Functions.
A política de repetição informa ao runtime para executar novamente uma execução com falha até que ocorra uma conclusão bem-sucedida ou o número máximo de tentativas seja atingido.
Uma política de repetição é avaliada quando uma função executada por um tipo de gatilho com suporte gera uma exceção não executada. Como melhor prática, você deve capturar todas as exceções em seu código e gerar novas exceções para todos os erros que devem 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 da execução tenha sido concluída. Por causa desse comportamento, o progresso na partição específica é pausado até a conclusão do processamento do lote atual.
A versão 5.x da extensão dos Hubs de Eventos dá suporte a recursos de repetição adicionais para interações entre o host do Functions e o hub de eventos. Para obter mais informações, consulte clientRetryOptions
na referência de host.json dos Hubs de Eventos.
Estratégias de repetição
Você pode configurar duas estratégias de repetição compatíveis com a política:
Um período de tempo especificado pode decorrer entre cada repetição.
Ao executar um plano de consumo, você só será cobrado pelo tempo em que o código de função estiver sendo executado. Você não é cobrado pelo tempo de espera entre execuções em nenhuma dessas estratégias de repetição.
Contagens máximas de repetição
Você pode configurar o número máximo de vezes que uma execução da função é repetida antes de uma eventual falha. A contagem de repetições 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 repetição, a contagem de repetição é perdida. Quando há falhas de instância, o gatilho do Hubs de Eventos é capaz de retomar o processamento e repetir o lote em uma nova instância, com a contagem de repetição redefinida para zero. O gatilho do timer não é retomado em uma nova instância.
Esse comportamento significa que a contagem máxima de repetições é um melhor esforço. Em alguns casos raros, uma execução pode ser repetida mais vezes do que o número máximo solicitado. Para gatilhos do Timer, pode haver menos repetições do que o número máximo solicitado.
Exemplos de tentativa
Exemplos são fornecidos para estratégias de atraso fixo e retirada exponencial. Para ver exemplos de uma estratégia específica, primeiro você deve selecionar essa estratégia na guia anterior.
Há suporte para novas tentativas no nível da função 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}");
}
Propriedade | Descrição |
---|---|
MaxRetryCount | Obrigatórios. O número máximo de repetições permitidas por execução de função. -1 significa repetir indefinidamente. |
DelayInterval | O atraso usado entre repetições. Especifique-a 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 essas propriedades em definições de política de repetição:
Propriedade | Descrição |
---|---|
estratégia | Obrigatórios. Usar qual estratégia de repetição. Os valores válidos são fixedDelay ou exponentialBackoff . |
maxRetryCount | Obrigatórios. O número máximo de repetições permitidas por execução de função. -1 significa repetir indefinidamente. |
delayInterval | O atraso usado entre repetições quando você está usando uma estratégia fixedDelay . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
minimumInterval | O atraso mínimo de repetição quando você está usando uma estratégia exponentialBackoff . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
maximumInterval | O atraso máximo de repetição quando você está usando a estratégia exponentialBackoff . Especifique-a 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 de sua versão de Node.js.
Aqui está um exemplo de uma função de gatilho do 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 de sua versão de Node.js.
Aqui está um exemplo de uma função de gatilho do 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 essas propriedades em definições de política de repetição:
Propriedade | Descrição |
---|---|
estratégia | Obrigatórios. Usar qual estratégia de repetição. Os valores válidos são fixedDelay ou exponentialBackoff . |
maxRetryCount | Obrigatórios. O número máximo de repetições permitidas por execução de função. -1 significa repetir indefinidamente. |
delayInterval | O atraso usado entre repetições quando você está usando uma estratégia fixedDelay . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
minimumInterval | O atraso mínimo de repetição quando você está usando uma estratégia exponentialBackoff . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
maximumInterval | O atraso máximo de repetição quando você está usando a estratégia exponentialBackoff . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
Aqui está um exemplo de uma função de gatilho do 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 essas propriedades em definições de política de repetição:
Propriedade | Descrição |
---|---|
estratégia | Obrigatórios. Usar qual estratégia de repetição. Os valores válidos são fixed_delay ou exponential_backoff . |
max_retry_count | Obrigatória. O número máximo de repetições permitidas por execução de função. -1 significa repetir indefinidamente. |
delay_interval | O atraso usado entre repetições quando você está usando uma estratégia fixed_delay . Especifique-a 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 estratégia exponential_backoff . Especifique-a como uma cadeia de caracteres com o formato: HH:mm:ss . |
maximum_interval | O atraso máximo de repetição quando você está usando a estratégia exponential_backoff . Especifique-a 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 associação
Ao se integrar com serviços do Azure, erros podem ser gerados nas APIs dos serviços subjacentes. As informações relacionadas a erros específicos de associação estão disponíveis nas seções "Exceções e códigos de retorno" dos seguintes artigos:
- Azure Cosmos DB
- Armazenamento de Blobs
- Grade de Eventos
- Hubs de Evento
- Hub IoT
- Hubs de Notificação
- Armazenamento de Filas
- Barramento de Serviço
- Armazenamento de Tabelas