Problema molto lento di Sidekiq con coda grande dovuto a un numero enorme di notifiche utente non lette

Quindi ho un problema con Sidekiq.

Funziona incredibilmente velocemente nell’esecuzione dei job quando lo monitoro tramite l’interfaccia web di Sidekiq. Ma occasionalmente sembra che si sovraccarichi e inizi a funzionare estremamente lentamente, operando al 1-5% circa della sua velocità normale, senza riprendersi a meno che non svuoti Redis, nonostante l’utilizzo delle risorse del server sia nella norma/basso.

Sembra che, una volta che la coda raggiunge una certa dimensione, si blocchi e rallenti drasticamente, causando una crescita ancora maggiore della coda. Sto solo ipotizzando, forse la coda è grande proprio perché si sta rallentando per qualche altro motivo.

Questo gif descrive ciò che osservo:

Ci sono molte risorse server disponibili: l’utilizzo della CPU è molto basso in questo momento, sotto il 10%. C’è anche molta RAM e spazio SSD disponibile. Per quanto riguarda il server, dispone di 16 core CPU con 32 thread. Ho provato a eseguire tra 8 e 14 unicorn_sidekiq. Ho anche provato con 20, ma questo ha generato molti errori 5xx.

Sono riuscito ad accelerare i job lenti visualizzati nella scheda ‘busy’ dell’interfaccia web di Sidekiq seguendo questa guida:

(aggiungendo ‘vm.overcommit_memory = 1’ al file /etc/sysctl.conf e riavviando), oltre a ridurre il numero di unicorn_sidekiq a 8 (da 12).

Tuttavia, continua a funzionare lentamente. Ieri ho notato questo messaggio nel log di Redis (l’unico altro avviso riguardava il fatto che overcommit_memory non fosse impostato su 1, cosa che ho già corretto):

# WARNING: /proc/sys/net/core/somaxconn è impostato sul valore inferiore di 128

^ Qualcuno ha risolto questo avviso?

Comunque, se qualcuno ha idee su quale potrebbe essere la causa e/o una soluzione, fatemelo sapere. Ve ne sarei grato.

Sarebbe davvero ottimo risolvere questo problema in modo che non si ripresenti, invece di dover svuotare la coda ogni volta.

Ecco uno screenshot di ciò che vedo nella dashboard di Sidekiq:

E alcuni screenshot dei job nella scheda ‘busy’:

Inoltre, qualcuno sa se è sicuro utilizzare questa opzione? Eliminare la coda a priorità bassa dall’interfaccia web di Sidekiq?

Aggiornamento: Ho eliminato la coda a bassa priorità senza problemi, tuttavia la velocità di elaborazione dei lavori è rimasta invariata.

Hai delle metriche su quanto tempo impiegano i tuoi job? Sembra che ci sia un’enorme quantità di contesa sui tuoi job PostAlert, mentre gli altri vengono completati rapidamente.

A giudicare da quanto ho osservato nell’interfaccia web di Sidekiq. Sì, hai ragione, altri lavori sembrano essere completati rapidamente, con l’eccezione di:

Jobs::PostAlert - da 0 a 3 minuti, con la maggior parte nell’intervallo da 0 a 1 minuto.
Jobs::ProcessPost - da 0 a 21 secondi.

Il tuo server SMTP è lento?

Sto utilizzando Amazon SES per l’invio e ho anche configurato il ricevitore di posta per la ricezione di VERP.

Il limite di invio visualizzato su SES è di 25 email al secondo. È troppo lento? Probabilmente posso richiedere un aumento.

Ora che lo menzioni, ho notato una correlazione con l’inizio di questo problema in un giorno in cui è stato inviato un numero di email di digest superiore al normale (molte email di digest sono state consolidate in un unico giorno a causa di un problema di configurazione verificatosi in passato).

Quanti utenti stai contattando via email? Come appaiono i volumi di posta?

Non sono sicuro di quanti utenti stiano ricevendo l’email. L’ultimo dato sugli utenti attivi negli ultimi 30 giorni dalla dashboard di amministrazione è di 60,8k; forse è un indicatore utile? Ecco le statistiche di invio da SES (limite di 100k+ in 24 ore):

Aggiornamento: Il limite di invio al secondo per SES è stato aumentato da 25 a 50. Ora è possibile inviare fino a 180.000 email all’ora (anche se il totale consentito al giorno è appena superiore a 100.000). Tuttavia, la velocità di elaborazione dei job Sidekiq non sembra essere migliorata.

Qualche anno fa abbiamo avuto un problema in cui gli utenti accumulavano 10.000 notifiche non lette, rallentando le query relative alle notifiche e, di conseguenza, rendendo il job PostAlert più lento.

Abbiamo implementato una protezione per evitare che ciò accadesse di nuovo, ma sul tuo ambiente potrebbero manifestarsi caratteristiche di prestazioni diverse.

Hai utenti impostati per monitorare categorie che non prestano attenzione al numero di notifiche?

Puoi verificare il numero massimo di notifiche non lette per utente nel tuo database?

Quindi ho svuotato di nuovo la coda a bassa priorità e l’ho lasciata così per un paio di giorni (nessuna modifica dall’ultimo aggiornamento): non ha accelerato immediatamente e i lavori in coda si sono accumulati rapidamente, ma sembra essersi risolto da solo con un po’ di tempo. L’elaborazione dei lavori ora è velocissima. :slight_smile: Con un intervallo di polling di 20 secondi, negli ultimi minuti ho visto un range da 55 a 140 lavori al secondo. Anche l’andamento giornaliero sembra sano, senza accumulo nella coda.

Grazie mille per l’aiuto @Falco @supermathie @Stephen, l’ho davvero apprezzato!

Per quanto riguarda le vostre domande, non sono sicuro di come verificarle. Sarei felice di controllare (avrei bisogno di alcune indicazioni) e fornire le informazioni se sono ancora utili. Qualcosa di potenzialmente rilevante è che ho impostato l’impostazione ‘max email al giorno per utente’ su 3 da molto tempo.

Forse ho parlato troppo presto. I job di Sidekiq stanno attualmente eseguendo a circa 1-3 al secondo con una coda di 8,81 milioni.

:philosoraptor:

Quando hai aggiornato l’ultima volta? Alcuni giorni fa ho apportato alcuni miglioramenti alle prestazioni al job PostAlert:

Alcuni dei nostri siti molto grandi stavano riscontrando problemi di prestazioni nelle categorie con molte persone che “osservano il primo post”. Questo commit ha risolto il problema sulla nostra piattaforma di hosting, quindi c’è la possibilità che possa aiutare anche il tuo sito.

Ottimo! Sto aggiornando ora, l’ultimo aggiornamento è stato circa 10 giorni fa (test superati). Monitorerò la situazione per vedere se ci sono miglioramenti e poi farò rapporto. Grazie!

Aggiornamento: Purtroppo non ci sono stati miglioramenti immediati della velocità dopo l’aggiornamento. Vedremo se migliora con il tempo.

Aggiornamento: Il sistema è ancora lento e la coda si sta accumulando. Si notano molti processi postmaster tramite ‘top’. Utilizzo CPU totale di circa l’85% (32 core), la stragrande maggioranza dei quali dovuta a postmaster. Il che è interessante, dato che prima oggi l’utilizzo della CPU era tra il 20% e il 35% (anche Sidekiq era ancora lento a quel tempo). Correlato: Primary Postgres database process (postmaster) eating all CPU - #5 by pfaffman

Pensi che questi avvisi di Redis possano essere correlati? Vengono visualizzati durante la ricompilazione dell’app:

# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

# WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

Qualcuno ha risolto questi errori per un’installazione Docker?

Ho già aggiunto vm.overcommit_memory = 1 a /etc/sysctl.conf per risolvere l’avviso relativo alla memoria overcommit.

Quindi ho risolto l’avviso su Transparent Huge Pages (THP) eseguendo semplicemente come root il comando echo never > /sys/kernel/mm/transparent_hugepage/enabled. Non l’ho ancora aggiunto a rc.local per la persistenza, solo per testare. Ho eseguito una ricostruzione di Discourse e le prestazioni sono più o meno le stesse, forse c’è un lieve miglioramento.

Non sono però sicuro di come risolvere questo avviso:
# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

Ho visto alcune persone dire che Docker continuerà a usare il valore 128 anche se il valore di sistema è impostato più alto, ad esempio seguendo una guida come questa: Performance tips for Redis Cache Server – Tech and Me

Penso che potrebbe essere una buona idea assegnare alcuni UNICORN_SIDEKIQS specificamente alla coda a priorità bassa.

Sembra che i task con priorità ‘default’, ovvero PostAlert, si stiano muovendo piuttosto lentamente e, una volta che si crea un backlog di questi task lenti a priorità predefinita, la coda a priorità bassa (con task che potrebbero essere completati a un ritmo significativamente più veloce) si espande, poiché quasi nessuno di essi sembra essere completato. Sospetto che questa espansione renda più lento l’elaborazione complessiva di tutte le code. Penso che questo potrebbe spiegare anche la grande fluttuazione nei lavori al secondo.

Qualcuno sa se è possibile assegnare UNICORN_SIDEKIQS nel file app.yml (o in qualche altro modo) a task con priorità specifica?

Aggiungere più Sidekiq mentre il database è un collo di bottiglia peggiorerà solo la situazione.

Come ho detto sopra, devi risolvere il problema delle prestazioni scadenti di PostgreSQL.