Il CAC riceve spesso richieste di intervento per risolvere problemi relativi alle code dei messaggi VOS. Di seguito ne riporto alcuni particolarmente interessanti, insieme ad alcune soluzioni e raccomandazioni che vorrei condividere con voi.
Problema 1: Recentemente, un cliente ci ha segnalato un problema. Un richiedente non riusciva ad aggiungere un messaggio a una coda di messaggi, ricevendo il codice di errore e$max_file_exceeded. Stranamente, la coda era vuota, come mostrato dal comando list_messages.
Dopo aver esaminato la coda, si è visto che il numero di blocchi disco utilizzati per questa coda si stava avvicinando alla dimensione massima consentita per un file non esteso.
nome: %s1#d01>AppData>queue.MQ
organizzazione dei file: file della coda dei messaggi
ultimo utilizzo: 11-08-16 14:45:13 edt
ultima modifica: 11-08-16 14:45:13 edt
ultimo salvataggio: 10-06-14 21:34:18 edt
ora di creazione: 10-06-09 11:03:15 edt
file di transazione: sì
log protetto: no
interruttore di sicurezza: no
audit: no
estensioni dinamiche: no
dimensione estensione: 1
ultimo messaggio: 51689380
blocchi utilizzati: 520201
…
Perché questa coda era sia piena che vuota?
In passato, i server responsabili dello svuotamento della coda dei messaggi sono rimasti offline. Ciò ha causato un accumulo molto consistente di messaggi. Questi messaggi sono stati infine gestiti dai server e cancellati dalla coda. Quando i messaggi vengono cancellati da una coda, viene aggiunta una chiave all'indice _record_index della coda e il valore della chiave indica il numero di byte dei messaggi cancellati. Quando un nuovo messaggio viene aggiunto a una coda di messaggi, il file system tenterà di trovare un messaggio precedentemente eliminato della dimensione esatta del nuovo messaggio. Se non è disponibile, il nuovo messaggio viene scritto nello spazio libero alla fine della coda.
In questo caso, non c'era abbastanza spazio libero nella coda per contenere il nuovo messaggio e non c'era alcun messaggio cancellato preesistente della dimensione corretta.
La morale di questa storia è che è una buona idea limitare il numero di lunghezze uniche dei messaggi in una determinata coda. Anziché far sì che ogni messaggio utilizzi il numero esatto di byte di cui ha bisogno, arrotondate il valore a una dimensione standard. Utilizzando questa tecnica, aumentate la possibilità che un nuovo messaggio possa riutilizzare lo spazio di un messaggio precedentemente eliminato.
Problema 2: Recentemente, si è verificata un'altra situazione relativa alle prestazioni delle code dei messaggi. Un cliente ha segnalato che il tempo necessario per svuotare una coda contenente oltre 400.000 messaggi era eccessivamente lungo.
Recentemente avevano avuto un problema con i processi del server che non riuscivano a elaborare tempestivamente i messaggi in una coda di messaggi. Fortunatamente, i richiedenti erano stati mantenuti in esecuzione, quindi non erano andati persi dati. Una volta risolto il problema del server, ci sono volute molte ore prima che riuscissero a smaltire le richieste arretrate e potessero quindi iniziare a elaborare le transazioni recenti. Il cliente chiedeva perché si fosse verificato questo problema e come fosse possibile prevenirlo o accelerare il processo in situazioni future.
Quando un messaggio viene eliminato da una coda di messaggi, viene aggiunta una chiave al _record_index gestito dal sistema, dove il valore della chiave è la lunghezza del messaggio. Se il messaggio eliminato ha la stessa lunghezza di un messaggio eliminato in precedenza, la posizione dei dati inutilizzati viene salvata come voce duplicata sulla chiave contenente la dimensione di quel messaggio alla fine dell'elenco dei valori duplicati. Pertanto, se ci sono centinaia di migliaia di messaggi eliminati, tutti della stessa dimensione (o se l'insieme delle lunghezze dei messaggi eliminati è piccolo), l'elenco delle chiavi duplicate è molto lungo e il tempo necessario per eliminare un singolo messaggio aumenta in modo lineare.
Al contrario, quando un messaggio viene aggiunto alla coda ed esiste una chiave _record_index per la lunghezza del messaggio, lo spazio occupato dal record eliminato più recente viene riutilizzato per contenere i dati del nuovo messaggio. Questo valore deve quindi essere eliminato dal valore chiave contenente la lunghezza del messaggio. Pertanto, il tempo necessario per aggiungere un messaggio aumenta in modo lineare: più messaggi vengono eliminati, più tempo occorre per aggiungere un nuovo messaggio.
La morale di questa storia è che i dati gestiti dal sistema nelle code dei messaggi hanno memoria; le code ricordano la posizione e le dimensioni di tutti i messaggi precedenti. Queste informazioni permangono anche dopo che la coda è stata svuotata. Cercate di evitare che le vostre code dei messaggi raggiungano dimensioni eccessive (decine o centinaia di migliaia di blocchi su disco). Altrimenti, vi accorgerete che il costo dell'aggiunta e dell'eliminazione dei messaggi da una coda può aumentare nel tempo.
Le soluzioni a entrambe queste situazioni sono le stesse.
Soluzione A: Una coda di messaggi può essere troncata mentre è aperta. Per farlo, è possibile utilizzare la routine s$truncate_queue. Tuttavia, è necessario soddisfare 4 condizioni:
1: non devono esserci richiedenti che mantengono aperta la coda dei messaggi
2: la coda dei messaggi deve essere svuotata di tutti i messaggi
3: questa routine deve essere richiamata da un server
4: la coda non può essere un file di transazione
Se le prime 3 condizioni non sono soddisfatte, s$truncate_queue restituirà e$no_truncate_queue. Se l'ultima condizione non è soddisfatta, s$truncate_queue restituirà e$invalid_io_operation.
Soluzione B: se il design dell'applicazione consente di avere più server, è possibile rinominare periodicamente la coda dei messaggi esistente, creare una nuova coda dei messaggi con il nome corretto, avviare un nuovo set di server e rimbalzare i richiedenti. Quando i server si avviano, inizieranno l'elaborazione su una nuova coda dei messaggi, ma vuota. Quando i richiedenti si avviano, aggiungeranno le loro richieste nella nuova coda dei messaggi vuota. Il set originale di server può rimanere in esecuzione, elaborando le richieste in arretrato fino a quando la coda non sarà vuota. Quindi il vecchio set di server può essere arrestato e la vecchia coda di messaggi può essere eliminata.
Inoltre, una soluzione al problema 1 potrebbe essere quella di utilizzare una coda di messaggi basata sull'estensione. Ciò consentirebbe di inserire ulteriori messaggi nella coda, poiché la dimensione massima del file sarebbe maggiore di un fattore pari alla dimensione dell'estensione. Tuttavia, utilizzando code di messaggi basate sull'estensione, le prestazioni sarebbero ancora peggiori del normale se o quando la coda di messaggi contenesse un numero elevato di messaggi in un determinato momento.
Come accennato in precedenza, limitare il numero di lunghezze uniche dei messaggi in una determinata coda aumenterà la probabilità che un nuovo messaggio possa riutilizzare lo spazio liberato da un messaggio precedentemente eliminato. Ciò contribuirà a risolvere entrambi i problemi menzionati in questo post.
