Fórum Como encontrar uma mensagem na fila do MSMQ? #582005
31/05/2017
0
Cenário:
Aqui na empresa temos 20 PDV's e todos fazem comunicação com SAT, porém não temos 1 SAT para cada PDV, então foi desenvolvida uma aplicação que distribui as chamadas dos PDV's para os equipamentos SAT disponíveis na loja, uma espécie de "roteador". Quando um PDV fecha a venda e manda os dados para o SAT, as chamadas são enfileiradas no MSMQ, que serão lidas por uma aplicação consumidora dessas mensagens e no final serão colocadas em uma outra fila de "mensagens já processadas", onde cada PDV fará a leitura dos registros e quando encontrar a mensagem que corresponde ao seu pedido original, tira a mensagem da fila de "mensagens já processadas".
Problema:
Acho muito demorado essa última parte, pois o PDV tem que ler a fila inteira pra achar o que precisa, só que se a fila for muito grande, pode haver muita demora para o cliente pagante.
Pergunta:
Será que o vocês poderiam me aconselhar em como localizar a mensagem que o PDV precisa de maneira rápida?
Segue o exemplo de como eu faço a busca.
Fazendo uma simulação de 20 PDV's acessando, ele retorna a mensagem em torno de 16s, o que acaba sendo muita coisa. Em alguns momentos a consulta que usa Parallel dá a seguinte exception: "A mensagem para a qual o cursor está apontando atualmente foi removida da fila por outro processo ou por outra chamada a Receive sem o uso desse cursor."
Aqui na empresa temos 20 PDV's e todos fazem comunicação com SAT, porém não temos 1 SAT para cada PDV, então foi desenvolvida uma aplicação que distribui as chamadas dos PDV's para os equipamentos SAT disponíveis na loja, uma espécie de "roteador". Quando um PDV fecha a venda e manda os dados para o SAT, as chamadas são enfileiradas no MSMQ, que serão lidas por uma aplicação consumidora dessas mensagens e no final serão colocadas em uma outra fila de "mensagens já processadas", onde cada PDV fará a leitura dos registros e quando encontrar a mensagem que corresponde ao seu pedido original, tira a mensagem da fila de "mensagens já processadas".
Problema:
Acho muito demorado essa última parte, pois o PDV tem que ler a fila inteira pra achar o que precisa, só que se a fila for muito grande, pode haver muita demora para o cliente pagante.
Pergunta:
Será que o vocês poderiam me aconselhar em como localizar a mensagem que o PDV precisa de maneira rápida?
Segue o exemplo de como eu faço a busca.
MessageQueueTransaction transaction = new MessageQueueTransaction();
try
{
transaction.Begin();
//As mensagens da fila estão identificadas por uma label e eu uso essa informação para buscar a mensagem na fila
string label = CreateLabelForMessage(intLojaID, intSatVendaId);
Message message = _messageQueue.GetAllMessages().AsParallel().FirstOrDefault(x => x.Label == label);
if (message == null)
return;
_messageQueue.ReceiveById(message.Id, transaction);
transaction.Commit();
SAT_VendaDO objSatVenda = (SAT_VendaDO)message.Body;
dtoSatVenda.Codigo_Retorno = objSatVenda.Codigo_Retorno;
dtoSatVenda.Retorno_Motivo = objSatVenda.Retorno_Motivo;
dtoSatVenda.XML = objSatVenda.XML;
dtoSatVenda.Data_Retorno = objSatVenda.Data_Retorno;
dtoSatVenda.Chave_Consulta = objSatVenda.Chave_Consulta;
dtoSatVenda.Numero_Documento = objSatVenda.Numero_Documento;
dtoSatVenda.Enum_Status_ID = objSatVenda.Enum_Status_ID;
dtoSatVenda.SAT_ID = objSatVenda.SAT_ID;
dtoSatVenda.SAT_Venda_ID = objSatVenda.SAT_Venda_ID;
}
catch (Exception ex)
{
transaction.Abort();
}
finally
{
_messageQueue.Close();
}
return;
Fazendo uma simulação de 20 PDV's acessando, ele retorna a mensagem em torno de 16s, o que acaba sendo muita coisa. Em alguns momentos a consulta que usa Parallel dá a seguinte exception: "A mensagem para a qual o cursor está apontando atualmente foi removida da fila por outro processo ou por outra chamada a Receive sem o uso desse cursor."
Jefferson Cruz
Curtir tópico
+ 0
Responder
Post mais votado
08/06/2017
Opa Jefferson, vamos lá. Primeiro, o problema de utilizar o paralelismo nessa consulta é justamente o erro que tu tens recebido eventualmente. Conforme o número de buscas paralelas aumenta, esses erros também irão. Sem contar que podem existir inserções enquanto há uma busca, o que complica ainda mais as coisas.
Sobre a implementação, me parece uma questão de trocar a estrutura de dados, abandonando o MSMQ. Como o grande gargalo é para o cliente, trocar a fila por um estrutura indexada é o caminho. Acho que um dicionário de dados seria o ideal, utilizando como "key" um identificador único que os PDV's conhecem. Assim, a busca teria complexidade de O(1). Claro que levaria mais tempo para armazenamento, sem contar a implementação do dicionário, mas no medio/longo prazo tu terias ganho, e nem sei se isso seria possível na tua estrutura.
O paralelismo também é um caminho, mas a natureza do sistema dificulta a implementação correta, e o ganho certamente não seria tão grande.
Sobre a implementação, me parece uma questão de trocar a estrutura de dados, abandonando o MSMQ. Como o grande gargalo é para o cliente, trocar a fila por um estrutura indexada é o caminho. Acho que um dicionário de dados seria o ideal, utilizando como "key" um identificador único que os PDV's conhecem. Assim, a busca teria complexidade de O(1). Claro que levaria mais tempo para armazenamento, sem contar a implementação do dicionário, mas no medio/longo prazo tu terias ganho, e nem sei se isso seria possível na tua estrutura.
O paralelismo também é um caminho, mas a natureza do sistema dificulta a implementação correta, e o ganho certamente não seria tão grande.
Henrique Gasparotto
Responder
Gostei + 1
Mais Posts
19/06/2017
Jefferson Cruz
Fiz alguns ajustes no serviço e toda vez que uma mensagem é processada eu guardo ela no MSMQ e também na memória, assim a consulta passa a ser na memória pesquisando dentro de um dicionário pelo numero do pedido, como você citou. Consegui diminuir o tempo de pesquisa de 16s para até 5s.
Responder
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)