Stiamo cercando di far funzionare Service Broker nel nostro ambiente al fine di risolvere un caso aziendale. Non so se il titolo del messaggio sia buono, ma la mia domanda è sotto. Ma potrebbe non essere una buona domanda, quindi dopo è quello che stiamo facendo e perché penso che sia la domanda giusta.
Quanti messaggi devono essere inviati in una conversazione prima di terminare la conversazione?
Vogliamo utilizzare Service Broker per aggiornare in modo asincrono una tabella dei risultati. La tabella dei risultati è piatta e veloce. Abbiamo trigger sulle tabelle di base che inviano un messaggio con la loro tabella e chiave primaria. Abbiamo tre code:
- Bassa latenza - l'obiettivo è l'elaborazione di 15 secondi. Gestisce gli articoli che cambiano in relazione a un articolo specifico.
- Coda in blocco: l'elaborazione richiede 5 minuti. Gestisce quando cambia qualcosa che interessa molte centinaia (o migliaia) di oggetti. Separa l'elenco degli elementi interessati e li inserisce nella coda di latenza bassa posticipata
- Bassa latenza differita - l'obiettivo è l'elaborazione di 30 minuti. Questo elabora gli elementi ma solo dalla coda in blocco.
Fondamentalmente, se le informazioni di un cliente vengono aggiornate; ciò influisce su molti prodotti in modo che venga inviato alla coda in blocco per un'elaborazione più lenta. Tuttavia, se un prodotto viene aggiornato, viene inviato alla coda a bassa latenza.
Riutilizziamo conversazioni simili al blog di Remus Rusanu http://rusanu.com/2007/04/25/reusing-conversations/ , con l'eccezione che lo facciamo in base al modulo della chiave primaria. Questo ha il vantaggio secondario di aiutare nella deduplicazione della chiave primaria.
Quindi, riutilizziamo le conversazioni e rientriamo nelle nostre linee guida. Con due thread, sono stato in grado di masterizzare 125 messaggi / secondo (calo artificiale di diverse migliaia di messaggi), che è più che in grado di tenere il passo con la produzione (circa 15 messaggi / sec).
Tuttavia, il problema che stiamo riscontrando è che dopo un periodo di tempo, ~ 4 ore o 120.000 messaggi, abbiamo iniziato a vedere blocchi e contese elevate su sysdesend e sulla tabella delle code. I blocchi sono LCK_M_U e sono blocchi KEY. A volte hobt si risolve in sysdesend e altre volte nella tabella delle code specifica (queue_).
Abbiamo un processo in atto che terminerà le conversazioni dopo 24 ore o 30 minuti di inattività già, quindi potremmo semplicemente aumentare il tempo prima di passare in rassegna le conversazioni.
Stiamo usando SQL 2016 Enterprise (13.0.4001.0)
- Attiva incendi (invia a bassa latenza o in blocco)
- Cerca o crea un handle di conversazione.
- invia messaggio
- Procedura attivata in coda
- Aggiorna la tabella dei risultati
Il processo di pulizia viene eseguito ogni 10 minuti per vedere se ci sono conversazioni inattive. se li trova più di tre volte di seguito, lo contrassegna come inattivo e termina le conversazioni.
Per favore fatemi sapere se ci sono ulteriori dettagli che potrebbero essere utili. Non ho molta esperienza con Service Broker, quindi non so se i nostri messaggi / sec sono bassi, alti o indifferenti.
AGGIORNARE
Quindi oggi abbiamo riprovato e abbiamo riscontrato lo stesso problema. Abbiamo modificato la durata della conversazione in 2 ore e questo non ha avuto alcun effetto. Quindi abbiamo implementato il trucco 150; che aveva lo stesso problema.
Tonnellate di attese su INVIO CONVERSAZIONE, in attesa su sysdesend. Qualcuno ha ulteriori idee?
AGGIORNAMENTO 2
Abbiamo eseguito il test più a lungo oggi e per uno dei periodi di esempio di 17 minuti, abbiamo elaborato 41K messaggi su 4 handle di conversazione. Siamo riusciti a tenere il passo tranne verso la fine quando i blocchi sul sysdesend e sul tavolo della coda sono diventati troppo e abbiamo iniziato a vagare dietro prima di fermarlo. Sembra che non abbiamo problemi nell'elaborare i messaggi, senza che le cose entrino nella coda, possiamo tirarli fuori ed elaborarli almeno 5 volte quella velocità. La nostra velocità sembra essere limitata in base all'aggiunta di messaggi.
In un test successivo, abbiamo rimosso uno dei trigger che rappresentavano l'80% dei messaggi. Anche con questo carico molto ridotto, abbiamo iniziato a vedere le stesse attese.
AGGIORNAMENTO 3
Grazie, Remus per il tuo consiglio (e grazie per aver pubblicato articoli di blog così eccellenti sull'argomento, sono stati fondamentali per arrivare a questo punto).
Lo abbiamo eseguito di nuovo oggi e abbiamo fatto di meglio (come siamo andati più a lungo prima di vedere le attese e anche più a lungo prima che ci paralizzasse). Quindi, i dettagli.
Abbiamo modificato: * Aumentato il numero di conversazioni mantenute per thread da 1: 1 a 2: 1. Fondamentalmente, avevamo 8 handle di conversazione per 4 thread.
- consolidata la coda di massa (perché un messaggio in arrivo potrebbe significare centinaia di messaggi in uscita) per consolidare in un numero minore di messaggi più grandi.
Note su questo tentativo:
disabilitando la procedura di attivazione della coda di destinazione. nessun cambiamento nel blocco (abbiamo aspettato 5 minuti) e i messaggi sono stati inviati a sys.transmission_queues.
monitoraggio di sys.conversation_endpoints. Questo numero è passato da 0 a 13K molto rapidamente, e poi è aumentato più lentamente durante il giorno fino a circa 25K dopo ~ 5 ore. Il blocco non ha iniziato a verificarsi fino a quando non ha raggiunto 16K +/-
Sono entrato nel DAC ed ho eseguito i comandi DBREINDEX per le code, anche se da una query i record di fantasmi non hanno mai superato i 200 o giù di lì prima che arrivasse la pulizia e trascinavo il conteggio a 0.
sysdesend e sysdercv avevano conteggi identici di 24.932 quando ho terminato il test.
abbiamo elaborato ~ 310.000 messaggi in 5 ore.
Siamo andati così a lungo prima che le cose andassero in pezzi che pensavo davvero che ce l'avremmo fatta questa volta. Domani proveremo a forzare i messaggi a passare il filo.
sys.conversation_endpoints
durante il test (costante o in aumento, e quanto è grande quando si verifica il blocco). 2) Quando si verifica il blocco, la disabilitazione della coda di destinazione fa la differenza nel blocco SEND (la disabilitazione della coda deve indirizzare SEND a sys.transmission_queue). e 3) Forzare i messaggi a passare al cavo, anche localmente (impostare endpoint SSB, aggiungere percorsi) cambia il comportamento a lungo termine
ALTER QUEUE ... REBUILD
fa la differenza una volta iniziato il blocco?
we started seeing blocks and high contention on sysdesend and the queue table.
-> Qual è il tipo di attesa -PAGELATCH_EX/SH and WRITELOG
? Hai usato il trucco 150 ? Se le tabelle di sistema sono il tuo punto di contesa, il trucco di 150 sarà molto utile.