7

Sto monitorando il database SQL per le connessioni ogni 5 minuti. Per giorni passerà intorno a 5 connessioni (il mio inattivo), poi improvvisamente sono a 50. Ovviamente questo è un problema ricorsivo perché non riesco a capire perché vorrei saltare da 5 a 50 in 5 minuti con traffico zero.Connection Pool vuoto Hibernate 4, ma Impossibile trovare il colpevole

Sto usando Hibernate 4 e Tomcat e so di un problema in Hibernate che è stato patchato nella 4.3.2, ma sono su 4.3.5

Maggiori dettagli: La piscina di eventi vuoto succede ogni giorno esattamente alle 7:13:20 PM ... Suoni troppo automatici. Sto usando Quartz e viene eseguito ogni 1 minuto, ma non riesco a vedere come sono correlati.

Miei annunci:

jmxEnabled = true 
initialSize = 5 
maxActive = 50 
minIdle = 5 
maxIdle = 25 
maxWait = 10000 
maxAge = 10 * 60000 
timeBetweenEvictionRunsMillis = 5000 
minEvictableIdleTimeMillis = 60000 
validationQuery = "SELECT 1" 
validationQueryTimeout = 3 
validationInterval = 15000 
testOnBorrow = true 
testWhileIdle = true 
testOnReturn = false 
jdbcInterceptors = "ConnectionState" 
defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED 

Ambiente:

  • Tomcat 7.0.59
  • Java 1.7.0 update 76
  • SQL Server 2012

Maggiori informazioni : Ho ridotto la frequenza del lavoro al quarzo ogni 5 minuti. L'evento si è ancora verificato quando ho caricato una pagina/vista nell'applicazione. Questo era all'incirca alle 7:14 PM. Sono sull'orlo della retrocessione per il letargo 3.

Aggiornamento Oggi ho ricaricato l'applicazione in Tomcat Manager di 06:50, ma l'evento ancora avuto luogo. Thread Dump

+0

Ho rimosso il daemon genitore-> figlio tomcat e ora ho solo 10 operatori di quarzo denominati in modo appropriato. –

+0

Che tipo di pool di connessione stai usando? Ho scoperto che a volte provare Hikari o un altro provider CP può prestarsi a eseguire il debug delle istruzioni per tenere traccia di questi tipi di problemi. Potrebbe essere una buona idea provarlo in un ambiente di test. – bphilipnyc

+0

@bphilinyc Non ho provato un altro provider oltre a Tomcat. Tuttavia, ho implementato l'ambiente QA, ma non ho riscontrato lo stesso problema. Molto localizzato e molto probabilmente esterno. –

risposta

2

Voglio prima ringraziare tutti per aver fornito le vostre risposte. Come @JensSchauder mi aveva suggerito di provare a isolare il problema. Mi chiedo perché non ho avuto il problema in QA, ma l'ho fatto in produzione.

Anche se ho seguito il mio team di gestione delle reti, nessuno ci ha colpito fino a quando non ho ottenuto i registri di cui avevo bisogno.

Utilizziamo un prodotto chiamato Alert Logic per analizzare e identificare le vulnerabilità della sicurezza, ma sfortunatamente non è stato scoperto essere il colpevole fino a quando non sono stato in grado di tracciare i log di accesso di Apache a un indirizzo IP. whois ha identificato l'IP proveniente dal software Alert Logic da un host di Rackspace.

Il server delle applicazioni era nuovo e consisteva in una nuova immagine di architettura. Risulta che Alert Logic stava colpendo una vulnerabilità. Questo ha portato a uno svuotamento del pool di connessioni (bailing?)

Fino a metà settimana scorsa, non avevo idea che Alert Logic fosse nemmeno nell'equazione.In effetti, ora sto lavorando con Network Operations per ottenere una migliore osservazione del prodotto da quando è scaduto.

Più tardi questa settimana, pubblicherò i risultati della vulnerabilità durante il QA (poiché la produzione delle patch era prioritaria).

2

Ah questi tipi di bug sono divertenti. Ovviamente non c'è modo di indicarci l'esatta bozza (tranne quando qualcuno scava un bug nelle librerie che hai citato), quindi vediamo come puoi eseguire il debug di questo. Approssimativamente da facile a difficile da fare, anche se i dettagli dipendono dal tuo ambiente.

  1. Hai informazioni molto utili: il problema si verifica sempre allo stesso tempo. Questo suggerisce due opzioni: o uno dei tuoi lavori eseguiti con Quartz mangia connessioni, o qualcosa (possibile esterno) sta accadendo in quel momento causando il tuo codice a mangiare connessioni. Ovviamente è necessario controllare le configurazioni del lavoro e i lavori cron oi lavori configurati all'interno del database o simili per potenziali colpevoli. Si noti che potrebbero iniziare molto prima e arrivare a quel punto critico più tardi, quindi il lavoro potrebbe iniziare 2 ore prima per tutto ciò che sappiamo.

  2. Controllare i registri, i registri di sistema e i registri del database per qualsiasi cosa avvenga in quel momento o prima.

  3. Doppio controllo di tutto ciò che ottiene una connessione se restituisce sempre la connessione. Soprattutto quando vengono lanciate eccezioni. Un modo classico per fallire in quel è una costruzione del genere (java come pseudo codice):

    Connection con; 
    
    try { 
        con = getConnection(); 
        Statement = stmnt = con.createStatement(); 
        .... 
    } finally (Exception ex){ 
        if (stmnt != null) stmnt.close(); 
        if (con != null) con.close(); // this will never happen if stmnt.close throws an exceptions 
    
    } 
    
  4. Stabilire la registrazione che permettono di vedere esattamente quando la connessione non ottenere restituito. Tutto ciò che inizia qualsiasi cosa nella tua applicazione dovrebbe passare attraverso una sorta di wrapper (AOP intorno a Aspect, Servlet Filter o simili).Quel wrapper dovrebbe fare quanto segue: creare un ID univoco per l'azione (UUID) e inserire lo MDC of your logging framework. Alla fine dell'azione quell'ID viene rimosso di nuovo. Tutte le altre registrazioni dovrebbero includere quell'id. Includi anche il pool di connessioni. Tieni traccia di quando qualcosa ha richiesto una connessione, incluso il timestamp, l'id e possibilmente lo stacktrace (creando e memorizzando un'eccezione). Registro. Ogni volta che viene restituita una connessione, registrare l'ora in cui è stata utilizzata. Inoltre, ogni volta che viene richiesta una connessione, verificare se una connessione viene utilizzata più a lungo di una soglia.

  5. Isolare le cose: configurare un secondo server, in cui eseguire l'applicazione. Ha lo stesso problema? Esegui alcune parti solo su uno dei due server, hanno ancora entrambi il problema? Continua a escludere i candidati finché ne rimane uno solo.

+0

Il codice di esempio in # 3 manca dei blocchi 'try/catch' attorno a ciascuna delle chiamate' close() '. Se le chiamate a 'close()' generano un'eccezione, essa (a) maschera l'eccezione originale e (b) se 'Statement.close()' fallisce, la connessione non verrà chiusa. –

+0

@ChristopherSchultz esattamente, questo è il punto del codice di esempio. –

+0

che rende il codice fragile. Dovresti avere due blocchi try/catch nidificati nel blocco try/catch esistente. –

2

Se mi trovo di fronte a un tale problema, vorrei provare il mio meglio per ottenere un dump filo di quando le connessioni maxActive raggiunge 50. Si potrebbe provare ad aumentare questo limite maxActive per verificare se l'applicazione ha un più alto picco.

Vorrei anche configurare tomcat per utilizzare un provider di pool di connessioni come c3p0, se non è già in uso. Vorrei quindi creare una classe di hook personalizzata come descritto nella seguente sezione: http://www.mchange.com/projects/c3p0/#connection_customizers

Con questa classe personalizzata mantenere un contatore di corsa delle connessioni acquisite e rilasciate. Quando questo numero è vicino o al limite, avviare un dump del thread a livello di codice. Questo può essere fatto come descritto nella seguente pagina: http://crunchify.com/how-to-generate-java-thread-dump-programmatically/ Analizzare questo dump di thread per controllare l'origine delle connessioni.

Queste informazioni non saranno utili solo per il problema corrente ma anche per la risoluzione dei problemi di prestazioni futuri.

2

Ho costruito un Connection Pool monitoring tool, chiamato FlexyPool e potrebbe aiutarti a scoprire il colpevole. Supporta anche TomcatCP ed è possibile correlare le sue metriche con altri registri attualmente in uso,

Il connection lease time histogram dovrebbe indicare per quanto tempo una connessione è in attesa, il che significa che si potrebbero avere query lente.

Il concurrent connections histogram indica quante connessioni vengono utilizzate in una e se si dispone di meno di 50, si verifica un problema di perdita di connessione.

Problemi correlati