Pular para o conteúdo principal

O CAC é freqüentemente solicitado a examinar problemas com filas de mensagens VOS. Aqui estão alguns interessantes, juntamente com algumas soluções e recomendações que eu gostaria de compartilhar com vocês.

Problema 1: Recentemente, um cliente veio até nós com um problema. Um solicitante não conseguiu adicionar uma mensagem a uma fila de mensagens, recebendo o código de erro e$max_file_exceeded. Estranhamente, a fila estava vazia, como mostra o comando list_messages.

Ao examinar a fila, verificou-se que a contagem dos blocos de disco utilizados para esta fila estava se aproximando do tamanho máximo de arquivo para um arquivo não-extenso.

nome: %s1#d01>AppData>queue.MQ

organização do arquivo: arquivo de fila de mensagens
usado pela última vez em: 11-08-16 14:45:13 edt
modificado pela última vez em: 11-08-16 14:45:13 edt
último salvado em: 10-06-14 21:34:18 edt
tempo criado: 10-06-09 11:03:15 edt
arquivo de transação: sim
log protegido: não
interruptor de segurança: não
auditoria: não
extensões dinâmicas: não
tamanho da extensão: 1
última mensagem: 51689380
blocos utilizados: 520201

Por que esta fila estava tanto cheia quanto vazia?

Em algum momento no passado, os servidores responsáveis pela drenagem das mensagens para fora da fila estavam desligados. Isto resultou em um acúmulo muito grande de mensagens. Essas mensagens eram eventualmente tratadas pelos servidores e excluídas da fila de espera. Quando as mensagens são excluídas de uma fila, uma chave é adicionada ao índice _record_index da fila, e o valor da chave indica o número de bytes da(s) mensagem(s) excluída(s). Quando uma nova mensagem é adicionada a uma fila de mensagens, o sistema de arquivo tentará encontrar uma mensagem excluída anteriormente do tamanho exato da nova mensagem. Se uma não estiver disponível, a nova mensagem é escrita no espaço virgem no final da fila.

Neste caso, não havia espaço virgem suficiente na fila para conter a nova mensagem, e não havia nenhuma mensagem pré-existente apagada do tamanho correto.

A moral desta história é que é uma boa idéia limitar o número de comprimentos únicos de mensagens em qualquer fila. Em vez de fazer com que cada mensagem use o número exato de bytes de que precisa, arredondar o valor até algum tamanho padrão. Ao usar esta técnica, você aumenta a chance de que uma nova mensagem possa reutilizar o espaço de uma mensagem eliminada anteriormente.

Problema 2: Recentemente, surgiu outra situação relativa ao desempenho das filas de mensagens. Um cliente declarou que o tempo para esvaziar uma fila de mensagens de mais de 400.000 mensagens estava demorando uma quantidade desordenada de tempo.

Eles tinham tido recentemente um problema com o fato de seus processos de servidor não poderem processar mensagens em uma fila de mensagens de forma oportuna. Felizmente, os solicitantes tinham sido mantidos em funcionamento para que nenhum dado fosse perdido. Quando o problema no servidor foi resolvido, passaram muitas horas antes que eles tivessem conseguido atender aos pedidos em atraso e pudessem então começar a processar as transações recentes. O cliente estava perguntando por que isso ocorria, e como isso poderia ser evitado ou acelerado em situações futuras.

Quando uma mensagem é excluída em uma fila de mensagens, uma chave é adicionada ao índice _record_index mantido pelo sistema, onde o valor da chave é o comprimento da mensagem. Se a mensagem sendo excluída tiver o mesmo comprimento que uma mensagem excluída anteriormente, a posição dos dados não utilizados é salva como uma entrada duplicada na chave que contém aquele tamanho de mensagem no final da lista de valores duplicados. Assim, se houver centenas de milhares de mensagens excluídas, todas do mesmo tamanho (ou o conjunto de comprimentos de mensagens excluídas for pequeno), a lista de chaves duplicadas é muito longa e o tempo para excluir uma única mensagem sobe linearmente.

Por outro lado, quando uma mensagem é adicionada à fila e existe uma chave _record_index para o comprimento da mensagem, o espaço ocupado pelo mais novo registro apagado é reutilizado para conter os dados para a nova mensagem. Este valor deve então ser excluído do valor da chave que contém o comprimento da mensagem. Assim, o tempo para adicionar uma mensagem aumenta linearmente; quanto mais mensagens eliminadas, mais tempo leva para adicionar uma nova mensagem.

A moral desta história é que o sistema mantém os dados nas filas de mensagens com memória; as filas lembram os locais e tamanhos de todas as mensagens anteriores. Esta informação persiste mesmo depois que a fila é esvaziada. Tente evitar que as filas de mensagens cresçam a um tamanho enorme (dezenas ou centenas de milhares de blocos de disco). Caso contrário, você verá que o custo de adicionar e apagar mensagens em uma fila pode crescer com o tempo.

As soluções para estas duas situações são as mesmas.

Solução A: Uma fila de mensagens pode ser truncada enquanto ela é aberta. A rotina s$truncate_queue pode ser usada para realizar isto. Entretanto, há 4 condições que devem ser satisfeitas:

1: não deve haver solicitantes mantendo a fila de mensagens aberta

2: a fila de mensagens deve ser drenada de todas as mensagens

3: esta rotina deve ser chamada por um servidor

4: a fila não pode ser um arquivo de transação

Se as 3 primeiras condições não forem cumpridas, s$truncate_queue retornará e$no_truncate_queue. Se a última condição não for atendida, s$truncate_queue retornará e$invalid_io_operação.

Solução B: se o projeto da aplicação permitir ter vários servidores, você pode periodicamente renomear a fila de mensagens existente, criar uma nova fila de mensagens com o nome correto, iniciar um novo conjunto de servidores, e fazer ricochete nos solicitantes. Quando os servidores iniciarem, eles começarão a processar em uma nova, mas vazia, fila de mensagens. Quando os solicitantes iniciarem, eles adicionarão seus pedidos à nova fila de mensagens, mas vazias. O conjunto original de servidores pode permanecer em funcionamento, processando o backlog de pedidos até que a fila esteja vazia. Então o antigo conjunto de servidores pode ser parado e a antiga fila de mensagens pode ser excluída.

Além disso, uma solução para o problema 1 pode ser a utilização de uma fila de mensagens baseada em extensão. Isso permitiria que mensagens adicionais fossem colocadas na fila, pois o tamanho máximo do arquivo seria maior por um fator do tamanho da extensão. Entretanto, usando filas de mensagens de extensão, o desempenho será ainda pior do que o normal se ou quando a fila de mensagens contiver um grande número de mensagens em qualquer ponto no tempo.

Como mencionado anteriormente, a limitação do número de comprimentos exclusivos de mensagens em qualquer fila aumentará a probabilidade de que uma nova mensagem possa reutilizar o espaço liberado por uma mensagem anteriormente eliminada. Isto ajudará a resolver os dois problemas mencionados neste post.

© 2024 Stratus Technologies.