Como encontrar uma mensagem na fila do MSMQ?

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.

            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

Jefferson Cruz

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.

Henrique Gasparotto

Henrique Gasparotto
Responder

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

Que tal ter acesso a um e-book gratuito que vai te ajudar muito nesse momento decisivo?

Ver ebook

Recomendado pra quem ainda não iniciou o estudos.

Eu quero
Ver ebook

Recomendado para quem está passando por dificuldades nessa etapa inicial

Eu quero

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar