Het openen van een databaseverbinding is een dure operatie en pooling van verbindingen wordt gebruikt om databaseverbindingen open te houden, zodat ze opnieuw kunnen worden gebruikt. Dit voorkomt dat u herhaaldelijk netwerksessies moet openen, authenticeren en autorisatie moet controleren. Pooling houdt de verbindingen actief zodat, wanneer later een verbinding wordt aangevraagd, een van de actieve wordt gebruikt in plaats van er een helemaal opnieuw te moeten maken.
Connection Pooling
Pooling van verbindingen is een van de meest gebruikelijke methoden geworden voor het afhandelen van databaseverbindingen voorafgaand aan een queryverzoek. Normaal gesproken denken we dat een verbinding met de database snel is, maar dat is niet het geval, vooral niet wanneer een groot aantal clients verbinding maakt. Zonder pooling van verbindingen zou een verzoek tot 35-50 ms duren om verbinding te maken, maar 1-2 ms als pooling van verbindingen wordt gebruikt. Pooling van verbindingen is daarom het vooraf toewijzen van databaseverbindingen en deze vervolgens te recyclen wanneer nieuwe clients verbinding maken
Redenen voor pooling van verbindingen
- Om te voorkomen dat je server crasht. PostgreSQL-servers zijn beperkt tot een aantal clients dat ze tegelijkertijd verwerken, afhankelijk van de geheugenparameter. Als dit aantal wordt overschreden, zal de server uiteindelijk crashen. Bij pooling van verbindingen gebruiken clients een bepaald aantal verbindingen.
- Vergemakkelijk de verwerking van zoekopdrachten. Normaal gesproken worden databaseverzoeken op een seriële manier uitgevoerd met als criterium first-in, first-out. Met een groot aantal klanten zou dit eeuwen duren om dit proces te bereiken. Daarom zou de benadering moeten zijn om een enkele verbinding te maken met gepijplijnde verzoeken die gelijktijdig kunnen worden uitgevoerd in plaats van elk tegelijk.
- Verbeter de beveiliging. Vaak gaat een verbinding gepaard met een handshake die gemiddeld 25-35 ms kan duren, waarbij een SSL tot stand wordt gebracht, wachtwoorden worden gecontroleerd en de configuratie-informatie wordt gedeeld. Al dit werk voor elke aangesloten gebruiker zal resulteren in een uitgebreid geheugengebruik. Met pooling van verbindingen wordt het aantal verbindingen echter verminderd, waardoor geheugen wordt bespaard.
Soorten pooling van verbindingen
Er zijn in principe twee soorten verbindingspooling, maar er is een derde type tijdelijke oplossing die werkt als een strategie voor verbindingspooling die bekend staat als permanente verbindingen.
Persistente verbinding pooling
Deze aanpak is bedoeld om een eerste verbinding actief te houden vanaf het moment dat deze wordt gestart. Het bevat de functies voor het poolen van verbindingen niet volledig, maar goed genoeg om een continue verbinding te bieden. Het is heel handig voor een kleine set clientverbindingen waarvan de overhead kan variëren van 25-50 ms. Een beperking van deze aanpak is dat deze beperkt is tot een aantal verbindingen met de db met normaal gesproken één enkele verbinding per ingang naar de server.
Framework Connection Pooling
Framework-verbindingspooling vindt plaats op toepassingsniveau waarbij, telkens wanneer uw serverscript wordt gestart, een pool van verbindingen tot stand wordt gebracht voor het afhandelen van queryverzoeken die later zullen binnenkomen.
Standalone verbinding pooling
Voor elke verbinding met de database wordt een overheadgeheugen tussen 5 en 10 MB gebruikt om te voorzien in een queryverzoek. Dit is niet helemaal goed voor een groot aantal verbindingen. Het gebruik van de framework-pooling van verbindingen kan worden beperkt door dit aantal verbindingen, omdat er mogelijk veel geheugen wordt gebruikt. We kiezen er dus voor om de Standalone connection pooling te gebruiken die is geconfigureerd in overeenstemming met de sessies, afschriften en transacties van Postgres. Het belangrijkste voordeel van deze aanpak is:minimale overheadkosten van ongeveer 2 kb voor elke verbinding.
Wanneer u een klasse voor het poolen van verbindingen maakt, moet deze voldoen aan de volgende factoren voor betere databaseprestaties:
- Wijs de verbindingen vooraf toe
- Bekijk verbindingen die beschikbaar zijn
- Nieuwe verbindingen toewijzen
- Wacht tot er een verbinding beschikbaar is
- Verbinding sluiten
De verbindingen vooraf toewijzen
Door vooraf te zorgen voor meer verbindingen, wordt de behandeling van verzoeken vergemakkelijkt op het moment dat de applicatie is gestart. Als uw server bijvoorbeeld is ontwikkeld met Java, kunt u vectoren gebruiken om beschikbare inactieve verbindingen op te slaan met behulp van de onderstaande code.
availableConnections = new Vector(connections);
busyConnections = new Vector();
for(int i=0; i<connections; i++) {
availableConnections.addElement(makeNewConnection());
}
Beschikbare verbindingen overzien
De klasse zou in staat moeten zijn om te controleren op een inactieve verbinding in een lijst met bezette verbindingen en deze terug te sturen. Dit wordt in principe gedaan om een verbinding te hergebruiken of verbindingen die niet in gebruik zijn te sluiten. Soms is er een time-out voor verbindingen, dus bij het herstellen van een verbinding is het heel belangrijk om te controleren of deze nog steeds open is. Als dit niet het geval is, moet u deze verbinding verwerpen en het proces herhalen. Wanneer een verbinding wordt weggegooid, wordt een slot geopend dat kan worden gebruikt om een nieuwe verbinding te verwerken wanneer de limiet is bereikt. Dit kan worden bereikt met
public synchronized Connection getConnection() throws SQLException {
if (!availableConnections.isEmpty()) { Connection existingConnection =
(Connection)availableConnections.lastElement(); int lastIndex = availableConnections.size() - 1; availableConnections.removeElementAt(lastIndex); if (existingConnection.isClosed()) {
notifyAll(); // Freed up a spot for anybody waiting.
return(getConnection()); // Repeat process. } else {
busyConnections.addElement(existingConnection);
return(existingConnection); }
} }
Een nieuwe verbinding toewijzen
Je zou in staat moeten zijn om een achtergrondthread te starten om een nieuwe verbinding toe te wijzen als er geen inactiviteit beschikbaar is en als de verbindingslimiet bijna wordt bereikt.
if ((totalConnections() < maxConnections) && !connectionPending) { // Pending = connecting in bg
makeBackgroundConnection(); }
try {
wait(); // Give up lock and suspend self.
} catch(InterruptedException ie) {} return(getConnection()); // Try again.
Wachten op een nieuwe verbinding
Wanneer er geen inactieve verbinding is en de verbindingslimiet is bereikt, moet de configuratie kunnen wachten tot er een nieuwe verbinding beschikbaar is zonder voortdurend poolen. We kunnen dit doen met behulp van de wachtmethode die een threadsynchronisatievergrendeling biedt en de thread opschort totdat er een melding is gegeven.
try {
wait();
} catch(InterruptedException ie) {}
return(getConnection());
Voor een goede toepassingsethiek moeten klanten niet in realtime wachten op een verbinding, maar u zult een uitzondering maken wanneer verbindingen afwezig zijn met de onderstaande code:
throw new SQLException("Connection limit reached");
De verbinding verbreken
Wanneer verbindingen worden verzameld, moet u ze sluiten in plaats van dit expliciet te doen. Als u echter een expliciete benadering wilt om een verbinding te verbreken, kunt u het volgende gebruiken:
public synchronized void closeAllConnections() {
// The closeConnections method loops down Vector, calling // close and ignoring any exceptions thrown. closeConnections(availableConnections); availableConnections = new Vector(); closeConnections(busyConnections);
busyConnections = new Vector();
}
Conclusie
Pooling van verbindingen voor PostgreSQL helpt ons het aantal bronnen te verminderen dat nodig is om verbinding te maken met de database en verbetert de snelheid van de verbinding met de database. Dit wordt bereikt door verbindingen met de DB te poolen, deze verbindingen te onderhouden en daardoor het aantal verbindingen dat moet worden geopend te verminderen.