Ir para o conteúdo principal

O CAC é frequentemente solicitado a analisar problemas relacionados às filas de mensagens do VOS. Aqui estão alguns casos interessantes, juntamente com algumas soluções e recomendações que gostaria de compartilhar com vocês.

Problema 1: Recentemente, um cliente nos procurou com um problema. Um solicitante não conseguia adicionar uma mensagem a uma fila de mensagens, recebendo o código de erro e$max_file_exceeded. Estranhamente, a fila estava vazia, conforme mostrado pelo comando list_messages.

Ao examinar a fila, verificou-se que o número de blocos de disco utilizados para essa fila estava se aproximando do tamanho máximo permitido para um arquivo sem extensão.

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

organização do arquivo: arquivo de fila de mensagens
último uso em: 16/08/11 14:45:13 EDT
última modificação em: 16/08/11 14:45:13 EDT
último salvamento em: 14/06/10 21:34:18 EDT
hora de criação:             09/06/10 11:03:15 EDT
arquivo de transação: sim
proteção de log: não
chave de segurança: não
auditoria:                          não
extensões dinâmicas: não
tamanho da extensão: 1
última mensagem: 51689380
blocos usados: 520201

Por que essa fila estava cheia e vazia ao mesmo tempo?

Em algum momento no passado, os servidores responsáveis por esvaziar a fila de mensagens ficaram fora de linha. Isso resultou em um grande acúmulo de mensagens. Essas mensagens acabaram sendo processadas pelos servidores e excluídas da fila. 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(ns) excluída(s).  Quando uma nova mensagem é adicionada a uma fila de mensagens, o sistema de arquivos tentará encontrar uma mensagem excluída anteriormente com o tamanho exato da nova mensagem. Se não houver nenhuma disponível, a nova mensagem é gravada no espaço vazio no final da fila.

Nesse caso, não havia espaço livre suficiente na fila para acomodar a nova mensagem, e não havia nenhuma mensagem excluída pré-existente com o tamanho adequado.

A moral da história é que é recomendável limitar o número de comprimentos de mensagem distintos em qualquer fila. Em vez de cada mensagem ocupar exatamente o número de bytes de que necessita, arredonde o valor para um tamanho padrão. Ao utilizar essa técnica, você aumenta a probabilidade de que uma nova mensagem possa reutilizar o espaço de uma mensagem excluída anteriormente.

Problema 2: Recentemente, surgiu outra situação relacionada ao desempenho das filas de mensagens. Um cliente informou que o tempo necessário para esvaziar uma fila de mensagens com mais de 400.000 mensagens estava demorando excessivamente.

Recentemente, eles tiveram um problema com os processos do servidor, que não conseguiam processar as mensagens em uma fila de mensagens em tempo hábil. Felizmente, os solicitantes continuaram em funcionamento, de modo que não houve perda de dados. Quando o problema do servidor foi resolvido, levou muitas horas até que eles conseguissem dar conta das solicitações acumuladas e pudessem então começar a processar as transações recentes. O cliente perguntou por que isso ocorreu e como isso pode ser evitado ou acelerado em situações futuras.

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

Por outro lado, quando uma mensagem é adicionada à fila e existe uma chave _record_index com o comprimento da mensagem, o espaço ocupado pelo registro excluído mais recente é reutilizado para armazenar os dados da nova mensagem. Esse valor deve então ser excluído da chave que contém o comprimento da mensagem. Assim, o tempo necessário para adicionar uma mensagem aumenta linearmente; quanto mais mensagens excluídas, mais tempo leva para adicionar uma nova mensagem.

A moral da história é que os dados mantidos pelo sistema nas filas de mensagens ocupam memória; as filas lembram a localização e o tamanho de todas as mensagens anteriores. Essas informações permanecem mesmo depois que a fila é esvaziada. Procure evitar que suas filas de mensagens atinjam tamanhos excessivos (dezenas ou centenas de milhares de blocos de disco). Caso contrário, você perceberá que o custo de adicionar e excluir mensagens de uma fila pode aumentar com o tempo.

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

Solução A: Uma fila de mensagens pode ser truncada enquanto estiver aberta. A rotina s$truncate_queue pode ser usada para realizar essa operação. No entanto, há quatro condições que devem ser satisfeitas:

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

2: todas as mensagens devem ser removidas da fila de mensagens

3: esta rotina deve ser chamada por um servidor

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

Se as três primeiras condições não forem atendidas, s$truncate_queue retornará e$no_truncate_queue. Se a última condição não for atendida, s$truncate_queue retornará e$invalid_io_operation.

Solução B: se o projeto da aplicação permitir a existência de vários servidores, é possível renomear periodicamente a fila de mensagens existente, criar uma nova fila de mensagens com o nome correto, iniciar um novo conjunto de servidores e redirecionar os solicitantes. Quando os servidores forem iniciados, eles começarão a processar em uma fila de mensagens nova, mas vazia. Quando os solicitantes forem iniciados, eles adicionarão suas solicitações à nova fila de mensagens vazia. O conjunto original de servidores pode permanecer em execução, processando o acúmulo de solicitações até que a fila esteja vazia. Em seguida, o conjunto antigo de servidores pode ser parado e a fila de mensagens antiga pode ser excluída.

Além disso, uma solução para o problema 1 pode ser o uso de uma fila de mensagens baseada em extensões. Isso permitiria que mensagens adicionais fossem colocadas na fila, já que o tamanho máximo do arquivo seria maior em um fator equivalente ao tamanho da extensão. No entanto, ao usar filas de mensagens baseadas em extensões, o desempenho ficará ainda pior do que o normal se, ou quando, a fila de mensagens vier a conter um grande número de mensagens em um determinado momento.

Como mencionado anteriormente, limitar o número de comprimentos de mensagem distintos em qualquer fila aumentará a probabilidade de que uma nova mensagem possa reutilizar o espaço liberado por uma mensagem excluída anteriormente. Isso ajudará a resolver os dois problemas mencionados neste post.

© 2024 Stratus Technologies.