Domanda

Qual è il modo migliore per impostare il tuo pool rispetto a: -

  1. Quando si creano connessioni?
  2. Quando chiudi le connessioni e vorresti chiuderle tutte?
  3. Testare le connessioni sono ancora buone. Quando e come?
  4. Come si può capire un buon numero per il numero massimo di connessioni?
  5. Che tipo di monitoraggio hai in atto per garantire che gli utenti del pool si comportino bene? Riesci a impedire a un brutto pezzo di codice di eliminare tutto?
  6. Hai scritto il tuo pool o hai utilizzato una libreria di terze parti?

Credo che questa sia una domanda agnostica, ma i commenti su " caratteristiche " di database / lingue particolari sono i benvenuti. Ad esempio, potrebbe essere più lento o più costoso connettersi su alcuni database rispetto ad altri.

Per chiarire, non ho intenzione di scrivere un pool da zero, questa domanda è più su come configurare una libreria esistente che fa il pool.

È stato utile?

Soluzione

Ho scritto un pool di connessioni per il database in Java quando era solo un modello di progettazione e non una libreria comune. Ora uso quello integrato in Tomcat.

Ho usato un thread per monitorare diversi aspetti del pool e diversi parametri per controllarne il comportamento ...

  1. minimumInPool = " 3 " ... Questi primi tre vengono creati all'avvio. Il pool non può mai scendere al di sotto di tre.
  2. maximumIdleTimeBeforeRemoval = " 60 " ... Se una connessione è inattiva per un'ora, quindi rilasciarla e crearne una nuova. Il tempo di inattività probabilmente significa che ci sono solo un minimo di tre nel pool.
  3. maximumInUseTimeBeforeRemoval = " 30 " ... Se una data connessione è stata verificata per oltre 30 minuti, probabilmente qualcosa non va. Richiamalo e uccidi la connessione.
  4. maximumTimeBeforeRemoval = " 60 " ... Rimuovilo se ha più di 60 minuti.
  5. maximumUsageBeforeRemoval = " 1000 " ... Rimuovilo se è stato verificato più di 1000 volte.
  6. monitorInterval = " 15 " ... Controlla i parametri sopra ogni 15 minuti.

Questo mi è servito molto bene per un paio d'anni. Il più alto che abbia mai visto la piscina era 151 connessioni durante una sbirciatina selvaggia. Di solito la piscina era a circa una dozzina durante un uso intenso e al minimo fino a un minimo di tre nelle prime ore del mattino.

Ho usato i thin driver JDBC di Oracle e mi sono collegato a un database Oracle.

Altri suggerimenti

Ecco la logica che ho usato per un'implementazione recente.

  1. Dispone di due tipi di connessioni nel pool di connessioni. Il primo è pronto, ovvero aperto ma non utilizzato da un client. Il secondo è attivo, ovvero utilizzato da un client.

  2. Il pool di connessioni deve mantenere un numero limitato di connessioni pronte, è possibile regolare un minimo di N e un massimo di M. N in base alla velocità di picco alla quale i client richiedono connessioni. Se il numero di connessioni pronte scende a zero, è necessario un N. più grande Se il numero è costantemente elevato (diciamo sopra 10), è necessario un N. inferiore

  3. Quando un client desidera una connessione, assegnagli uno di quelli pronti (rendendolo attivo), quindi aprine immediatamente uno nuovo se ora c'è meno di N pronto (ma non far aspettare il client per questo per completare o perderai il vantaggio del pooling). Questo assicura che ci saranno sempre almeno N connessioni pronte. Se nessuno è pronto quando il cliente lo desidera, dovrà attendere mentre ne crei uno nuovo.

  4. Quando il client termina con una connessione attiva, riportalo allo stato pronto se ci sono meno di connessioni M ready. Altrimenti chiudilo. Questo ti impedisce di avere più di connessioni M pronte.

  5. Ricicla periodicamente le connessioni pronte per evitare connessioni non aggiornate. Se ci sono più di N connessioni pronte, basta chiudere la connessione più vecchia. Altrimenti chiudilo e riaprilo un altro.

Questo ha il vantaggio di avere abbastanza e connessioni giovanili pronte nel tuo pool di connessioni senza sovraccaricare il server.

Il DBCP di Jakarta Commons fa già tutto ciò che hai elencato:

  • crea connessioni secondo necessità e le gestisce in un pool
  • può chiudere le connessioni se non sono state utilizzate per un certo periodo di tempo
  • può eseguire una query su una connessione prima di distribuirla e, se si verifica un errore, la connessione viene eliminata e ne viene creata una nuova. Le connessioni possono anche essere testate periodicamente mentre è inattivo.
  • è possibile impostare un limite per le connessioni che verranno create e anche per il numero minimo di connessioni che devono essere pronte. Il limite ovviamente dipende molto dalla tua applicazione.
  • Non so come, ma DBCP sa quando una connessione non viene chiusa e la chiude per te, generando un'eccezione in modo da sapere cosa è successo quando vedi il tuo registro.
  • DBCP ha un parametro di timeout che è molto utile. Se vengono utilizzate tutte le connessioni nel pool, attenderà quel periodo di tempo affinché una connessione venga restituita al pool e se non ne sono disponibili quando viene raggiunto il limite, viene visualizzato un errore.

Puoi mettere a punto il tuo pool giocando con il numero minimo di connessioni, il numero massimo di connessioni da creare e il timeout. Un timeout più lungo ti consentirà di avere un limite inferiore di connessioni, mentre un timeout più breve richiederà probabilmente un numero maggiore. Questo dipende fortemente da ciò che fa l'applicazione e da come utilizza le connessioni.

Concordo con Matt b sul fatto che non dovremmo reinventare la ruota.

Tuttavia l'uso di Commons DBCP è discutibile in base alle risposte di questo e questo domande. Vi sono menzionate alternative migliori come c3po o proxool .

Oppure puoi usare il meccanismo di pool di connessioni dipendente da rdbms.

Non sono sicuro del contesto in cui stai utilizzando le tue connessioni, ma posso condividere ciò che sembra funzionare per me.

Uso SQL Server come back-end e utilizzo una combinazione di cache con esso per ottenere prestazioni migliori. La mia pratica è quella di mantenere aperta la connessione solo se ne ho davvero bisogno e di non mettere in comune le connessioni in modo che vengano ripulite immediatamente e posso vedere in SQL Activity Monitor esattamente cosa è attivo e cosa no. Ogni connessione occupa memoria, quindi è bello tenerla sotto un rombo sordo quando non è necessaria.

Prima di rispondere alla domanda di apertura e chiusura della connessione, vorrei dire che la memorizzazione nella cache è davvero importante. Far uscire un oggetto dalla cache ti farà risparmiare un sacco di tempo. In alcune delle mie app asp.net quando la memorizzazione nella cache è attiva in dev ho riscontrato che difficilmente riesco a misurare la latenza mentre con una chiamata DB potrebbero essere necessari da 15ms a 45ms per completare la chiamata e questo non sta nemmeno considerando un'altra latenza fattori o carico. L'altro metodo che utilizzo è una buona struttura di oggetti per i miei dati, in modo da apportare un aggiornamento DB solo se qualcosa cambia. Ho implementato alcuni metodi sul mio oggetto o per assicurarmi di fare il minor numero di IO possibile.

Detto questo sappiamo tutti che dobbiamo accedere e scrivere sul nostro DB ad un certo punto, quindi seguo due principi:

  1. Tieni le porte e le finestre chiuse per risparmiare energia. Una connessione aperta in un posto significa che non è disponibile in un altro (o la memoria e altre risorse sono più limitate). Abbiamo disattivato il raggruppamento perché ha portato a prestazioni migliori per noi.

  2. Faccio tutto il possibile in batch o in una sola volta quando la connessione è aperta. Questo è un po 'più complicato, quindi lasciami spiegare.

    • un metodo che ho usato è quello di passare i miei oggetti di connessione nel tubo in modo che tutti gli oggetti possano usare un oggetto di connessione. Ciò comporta l'apertura e la chiusura di una connessione anziché forse 10 o più a seconda dell'app. Un buon esempio di questo è uno dei nostri modelli di acquisto che sfrutta la potenza del server SQL per la raccolta di statistiche e la creazione di schemi di ordinamento complicati. Non ha senso continuare ad aprire e chiudere la connessione quando si esegue una ricerca di 200 KB + DB o qualunque sia l'app a cui si rivolgono. L'altra parte di ciò è che quando uso l'oggetto provo a raggruppare i miei aggiornamenti per ridurre il tempo in cui mantengo aperta la connessione. Quindi, facendo una scope_identity sulla chiamata insert, mi occupo sia del mio inserimento che di una ricerca dell'ID univoco da aggiungere al mio oggetto prima di memorizzarlo nella cache. Ai tempi in cui stavo sviluppando app per la prima volta, avrei effettivamente aperto la connessione non appena la pagina avesse iniziato a caricarsi e poi l'avessi chiusa. Non consiglio più di farlo. Ora un giorno c'è un grande vantaggio in questo tipo di astrazioni e livelli che consiglierei a qualsiasi programmatore principiante di prestare molta attenzione.

I miei due centesimi:

Metti in cache i tuoi dati! Cache i tuoi dati! Cache i tuoi dati! Fai il minor accesso DB possibile quando non puoi memorizzare nella cache e quindi memorizzare i dati nella cache!

Perché reinventare la ruota?

Qualcuno ha già probabilmente risolto il problema, e meglio.

Se ti trovi nel mondo Java, puoi utilizzare Commons DBCP .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top