Visão geral das filas

Esta seção apresenta os conceitos gerais e centrais por trás da comunicação em fila. As seções subsequentes entram em detalhes sobre como os conceitos de enfileiramento descritos aqui são manifestados no Windows Communication Foundation (WCF).

Conceitos básicos de enfileiramento

Ao projetar um aplicativo distribuído, escolher o transporte certo para a comunicação entre serviços e clientes é importante. Vários fatores afetam o tipo de transporte a utilizar. Um fator importante — o isolamento entre o serviço, o cliente e o transporte — determina o uso de um transporte em fila ou de um transporte direto, como TCP ou HTTP. Devido à natureza dos transportes diretos, como TCP e HTTP, a comunicação para completamente se o serviço ou o cliente parar de funcionar ou se a rede falhar. O serviço, o cliente e a rede devem estar em execução ao mesmo tempo para que o aplicativo funcione. Os transportes em fila fornecem isolamento, o que significa que, se o serviço ou cliente falhar ou se os links de comunicação entre eles falharem, o cliente e o serviço podem continuar a funcionar.

As filas fornecem uma comunicação confiável mesmo com falhas nas partes comunicantes ou na rede. As filas capturam e entregam mensagens trocadas entre as partes comunicantes. As filas normalmente são apoiadas por algum tipo de loja, que pode ser volátil ou durável. As filas armazenam mensagens de um cliente em nome de um serviço e, posteriormente, encaminham essas mensagens para o serviço. As filas de indireção fornecem isolamento garantido de falhas por qualquer uma das partes, tornando-se assim o mecanismo de comunicação preferido para sistemas de alta disponibilidade e serviços desconectados. O indirection vem com o custo de alta latência. Latência é o atraso de tempo entre o momento em que o cliente envia uma mensagem e o momento em que o serviço a recebe. Isso significa que, uma vez que uma mensagem é enviada, você não sabe quando essa mensagem pode ser processada. A maioria dos aplicativos em fila lida com alta latência. A ilustração a seguir mostra um modelo conceitual de comunicação em fila.

Model of queued communication

Modelo conceitual de comunicação em fila

Na realidade, a fila é um conceito distribuído. Como tal, podem ser locais para qualquer uma das partes ou remotos para ambas as partes. Normalmente, a fila é local para o serviço. Nessa configuração, o cliente não pode depender da conectividade com a fila remota para estar constantemente disponível. Da mesma forma, a fila deve estar disponível independentemente da disponibilidade da leitura do serviço da fila. Um gerenciador de filas gerencia uma coleção de filas. Ele é responsável por aceitar mensagens enviadas para suas filas de outros gerenciadores de filas. Ele também é responsável por gerenciar a conectividade com filas remotas e transferir mensagens para essas filas remotas. Para garantir a disponibilidade das filas apesar das falhas do cliente ou do aplicativo de serviço, o gerenciador de filas geralmente é executado como um serviço externo.

Quando um cliente envia uma mensagem para uma fila, ele direciona a mensagem para a fila de destino, que é a fila gerenciada pelo gerenciador de filas do serviço. O gerenciador de filas no cliente envia a mensagem para uma fila de transmissão (ou saída). A fila de transmissão é uma fila no gerenciador de filas do cliente que armazena mensagens para transmissão para a fila de destino. Em seguida, o gerenciador de filas encontra um caminho para o gerenciador de filas que possui a fila de destino e transfere a mensagem para ela. Para garantir uma comunicação confiável, os gerenciadores de filas implementam um protocolo de transferência confiável para evitar a perda de dados. O gerenciador de filas de destino aceita mensagens endereçadas às filas de destino que possui e armazena as mensagens. O serviço faz solicitações para leitura da fila de destino, momento em que o gerenciador de filas entrega a mensagem ao aplicativo de destino. A ilustração a seguir mostra a comunicação entre as quatro partes.

Queued Application Diagram

Comunicação em fila em um cenário típico de implantação

Assim, o gerenciador de filas fornece o isolamento necessário para que o emissor e o recetor possam falhar independentemente sem afetar a comunicação real. O benefício da indireção extra que as filas fornecem também permite que várias instâncias de aplicativo leiam da mesma fila, para que o trabalho de farm entre os nós atinja uma taxa de transferência mais alta. Portanto, não é incomum ver filas sendo usadas para alcançar requisitos de escala e taxa de transferência mais altos.

Filas e transações

As transações permitem agrupar um conjunto de operações para que, se uma operação falhar, todas as operações falhem. Um exemplo de como usar transações é quando uma pessoa usa um caixa eletrônico para transferir R$ 1.000 de sua conta poupança para sua conta corrente. Isto implica as seguintes operações:

  • Retirar $1.000 da conta poupança.

  • Depositando $1.000 na conta corrente.

Se a primeira operação for bem-sucedida e R$ 1.000 forem retirados da conta poupança, mas a segunda operação falhar, os R$ 1.000 são perdidos porque já foram retirados da conta poupança. Para manter as contas em um estado válido, se uma operação falhar, ambas as operações devem falhar.

Nas mensagens transacionais, as mensagens podem ser enviadas para a fila e recebidas da fila sob uma transação. Assim, se uma mensagem é enviada em uma transação e a transação é revertida, o resultado é como se a mensagem nunca tivesse sido enviada para a fila. Da mesma forma, se uma mensagem é recebida em uma transação e a transação é revertida, o resultado é como se a mensagem nunca tivesse sido recebida. A mensagem permanece na fila para ser lida.

Devido à alta latência, quando você envia uma mensagem, não tem como saber quanto tempo leva para chegar à fila de destino, nem quanto tempo leva para o serviço processar a mensagem. Devido a isso, você não deseja usar uma única transação para enviar a mensagem, receber a mensagem e, em seguida, processar a mensagem. Isso cria uma transação que não é confirmada por um período indeterminado. Quando um cliente e um serviço se comunicam através de uma fila usando uma transação, duas transações estão envolvidas: uma no cliente e outra no serviço. A ilustração a seguir mostra os limites de transação na comunicação em fila típica.

Queue with transactions

Comunicação em fila mostrando transações separadas para captura e entrega

A transação do cliente processa e envia a mensagem. Quando a transação é confirmada, a mensagem está na fila de transmissão. No serviço, a transação lê a mensagem da fila de destino, processa a mensagem e, em seguida, confirma a transação. Se ocorrer um erro durante o processamento, a mensagem será revertida e colocada na fila de destino.

Comunicação assíncrona usando filas

As filas fornecem um meio de comunicação assíncrono. Os aplicativos que enviam mensagens usando filas não podem esperar que a mensagem seja recebida e processada pelo recetor devido à alta latência introduzida pelo gerenciador de filas. As mensagens podem permanecer na fila por muito mais tempo do que o aplicativo pretendia. Para evitar isso, o aplicativo pode especificar um valor Time-To-Live na mensagem. Esse valor especifica por quanto tempo a mensagem deve permanecer na fila de transmissão. Se esse valor de tempo for excedido e a mensagem ainda não tiver sido enviada para a fila de destino, a mensagem poderá ser transferida para uma fila de mensagens mortas.

Quando o remetente envia uma mensagem, o retorno da operação de envio implica que a mensagem só chegou à fila de transmissão no remetente. Como tal, se houver uma falha em obter a mensagem para a fila de destino, o aplicativo de envio não pode saber sobre isso imediatamente. Para tomar nota de tais falhas, a mensagem com falha é transferida para uma fila de mensagens mortas.

Qualquer erro, como uma mensagem que não alcança a fila de destino ou o tempo de vida expirando, deve ser processado separadamente. Não é incomum, portanto, que aplicativos enfileirados escrevam dois conjuntos de lógica:

  • A lógica normal do cliente e do serviço de enviar e receber mensagens.

  • Lógica de compensação para lidar com mensagens da transmissão ou entrega com falha.

As seções a seguir discutem esses conceitos.

Programação de fila de mensagens mortas

As filas de mensagens mortas contêm mensagens que não conseguiram alcançar a fila de destino por vários motivos. Os motivos podem variar de mensagens expiradas a problemas de conectividade que impedem a transferência da mensagem para a fila de destino.

Normalmente, um aplicativo pode ler mensagens de uma fila de mensagens mortas em todo o sistema, determinar o que deu errado e tomar as medidas apropriadas, como corrigir os erros e reenviar a mensagem ou tomar nota dela.

Programação da fila de mensagens suspeitas

Depois que uma mensagem chega à fila de destino, o serviço pode falhar repetidamente ao processar a mensagem. Por exemplo, um aplicativo que lê uma mensagem da fila em uma transação e atualiza um banco de dados pode encontrar o banco de dados temporariamente desconectado. Nesse caso, a transação é revertida, uma nova transação é criada e a mensagem é relida da fila. Uma segunda tentativa pode ser bem-sucedida ou falhar. Em alguns casos, dependendo da causa do erro, a mensagem pode falhar repetidamente a entrega para o aplicativo. Neste caso, a mensagem é considerada como "veneno". Essas mensagens são movidas para uma fila de veneno que pode ser lida por um aplicativo de manipulação de veneno.

Consulte também