> Tech > Comment fonctionne le connection pool ?

Comment fonctionne le connection pool ?

Tech - Par iTPro - Publié le 24 juin 2010
email

Quand connection pooling est validé (il l'est par défaut), le provider de données tire chaque connexion d'un pool de connexions inactives, pré-ouvertes, ou établit une nouvelle connexion avec la base de données et crée un nouveau pool. Il s'en suit que quand vous fermez votre code de connexion, cela revient

en fait à  restituer la connexion à 
un pool de connexions utilisées ; la
connexion base de données vers la
source de données reste ouverte et
continue à  contenir les ressources sur
le serveur jusqu’à  ce que le pooler interrompe
la connexion, timeout
oblige, et la ferme. Le timeout dure
entre 4 et 8 minutes. Cependant, si le
même processus a besoin de se reconnecter,
le connection pool le rebranche
simplement à  une connexion
« hot » existante – en supposant que la
chaîne de connexion et d’autres facteurs
n’ont pas changé. Vous risquez
de ne pas retrouver la même
connexion mais, en théorie, la
connexion que vous obtenez devrait
être fonctionnellement équivalente à 
l’originale. De ce fait, votre application
peut économiser le temps qu’il lui faudrait
pour établir une connexion entièrement
nouvelle avec le serveur.
Comme toute fonctionnalité spécialisée,
le connection pooling a ses
propres règles d’utilisation. Voici
quelques questions que vous pourriez
vous poser quant aux règles qui régissent
les connection pools.

Quand le .NET Data Provider crée-til
un nouveau pool ?
Votre application
ne pourra pas toujours utiliser une
connexion existante. Si l’un des éléments
suivants change, le .NET Data
Provider crée un nouveau pool :

  • La propriété ConnectionString – Cette propriété doit être la même
    chaque fois qu’ADO.NET utilise la
    méthode Open pour ouvrir l’objet
    Connection. Même si le seul changement
    est que les arguments sont
    dans un ordre différent, la chaîne est
    différente. Si vous ajoutez, changez
    ou supprimez des arguments –
    même s’ils reflètent simplement le
    comportement par défaut – la propriété
    est différente et vous obtenez
    un nouveau pool.

  • UserID (UID) ou mot de passe – Si
    vous utilisez un UID spécifique pour
    chaque connexion, chaque UID obtient
    son propre pool.

  • Le process identifier (PID) – Chaque
    processus, programme, composant,
    service Web ou application Web obtient
    son propre pool. Je reviendrai
    sur ce point dans un moment.

  • Le scope ou enlistment des transactions
    – Si vous utilisez des transactions,
    chaque scope de transactions
    obtient son propre pool.

Où sont créés les connection pools ? Le provider crée toujours des connection
pools sur le système où le code
créant la connexion s’exécute : sur le
client. En mode client/serveur (par
exemple, une application Windows
Forms ouvre une connexion vers un
serveur distant), le provider établit le
connection pool sur le client (système
local). Dans des architectures service
Web, ASP, ASP.NET ou COM+, le code
qui ouvre la connexion s’exécute sur
un serveur distant qui héberge
Microsoft IIS ou Microsoft Transaction
Server (MTS). Dans ces cas, le « client »
est le code qui tourne sur le serveur de
code distant. Les connection pools ne
sont pas créés sur le serveur de bases
de données sauf s’il se trouve qu’il héberge
IIS ou MTS.

Comment le paramétrage de la sécurité
affecte-t-il le pooling ?
On l’a vu, si
vous utilisez un UID spécifique pour
chaque connexion, chaque UID obtient
son propre pool. Mais, si vous indiquez
Integrated Security=SSPI dans
le ConnectionString, vous obtenez un
pool pour le User Account de votre
processus. Par conséquent, vous ne
pouvez pas spécifier un rôle ou UID
spécifique et partager le pool que le
.NET Data Provider a créé pour un
autre rôle ou utilisateur.

Pourquoi le PID affecte-t-il le pooling
?

Comme toute bonne interface de
base de données, ADO.NET ne peut
pas partager des connexions entre processus.
Donc, chaque processus doit
avoir son propre connection pool. Une
application client/serveur obtient son
propre PID chaque fois qu’on l’exécute.
S’il y a cinq instances d’une application,
chacune obtient son propre
PID, et ce, que l’on exécute l’application
sur un système ou sur cinq systèmes.
Si l’on utilise un composant intermédiaire
– comme un service Web,
un composant COM+ ou une application
Web – ce composant a lui aussi son
propre PID. Mais, dans ce cas, des instances
multiples exécutent le même
processus. Cela signifie qu’un service
Web peut être proposé à  une poignée
ou à  quelques milliers de clients – qui
tous partagent le même connection
pool. Quand vous développez votre
service Web, chaque fois que vous
compilez et créez un nouvel assemblage,
le nouvel exécutable obtient un
nouveau PID – et un nouveau connection
pool. Donc vous pourriez parfaitement
avoir deux copies presque identiques
d’un exécutable sur votre
système, mais chacune obtenant son
propre connection pool.

Que se passe-t-il quand le pool est
plein ?
Si le pool se remplit de
connexions (la limite par défaut est de
100 connexions), le .NET Data Provider
attend qu’une autre instance de l’application
ferme une connexion existante.
Si le .NET Data Provider ne peut pas
obtenir une connexion à  temps (c’està –
dire, dans la limite prescrite par le paramètre
Connection Timeout), il
déclenche une System.Invalid OperationException
avec le message
Timeout expired. The timeout period
elapsed prior to obtaining a connection
from the pool. This may have occurred
because all pooled connections
were in use and max pool size was reached.
Qui signifie : « Timeout expiré. La
période de timeout s’est écoulée avant
d’obtenir une connexion en provenance
du pool. Cela s’est peut-être
produit parce que toutes les
connexions poolées étaient en service
et que la taille de pool maximale a été
atteinte ». Il ne sert à  rien de montrer
ce message aux utilisateurs parce que
ce n’est pas leur faute et, généralement,
ils ne peuvent pas déboguer
votre code (qui est pourtant le premier
fautif). Quand j’obtiens ce message,
j’envoie un message au Webmaster en
proposant de corriger le problème. A
noter qu’ADO.NET utilise System.InvalidOperationException
pour diverses
situations, donc vous devez
scruter la chaîne Message pour détecter
ce qui ne va pas.

Quand les pools sont-ils détruits ? Les connection pools sont détruits
quand le processus qui les crée se termine. De ce fait, un ADO.NET Data
Provider fonctionnant sous IIS ou MTS
crée des connection pools et les détruit
quand le processus ou Application
Domain (AppDomain) se termine.
A noter l’existence d’un bogue
dans les compteurs de performances
que le SQL Server .NET Data Provider
(System.Data.SqlClient) expose. Ce
bogue signale à  tort l’existence de
pools actifs. Pour être certain que vous
ne voyez pas un pool « fantôme », arrêtez
l’application Performance Monitor,
prenez le temps de boire un café et revérifiez.
Ce bogue n’est pas corrigé
dans .NET Framework 1.1. Quand on
travaille avec des applications Windows
Forms, les pools quittent la scène
quand l’application ou le processus se
termine. Ce comportement est logique
parce que le processus qui crée le
connection pool à  distance ne se terminera
pas forcément si IIS agit
comme un agent pour l’application
Web ou le service Web.
Si vous ouvrez un autre code de
connexion, le pool ressuscite quand
vous ouvrez ses connexions membres.
Il ne faut pas confondre les connection
pools que le .NET Data Provider gère,
avec les connexions de bases de données
que le pooler ouvre et ferme.
Quand votre code ferme une connexion,
la connexion revient au pool.
Après un certain délai déterminé par le
.NET Data Provider, la connexion à  la
base de données se ferme si elle n’est
pas réutilisée.
Il faut savoir que si l’on ferme le
système SQL Server (ou le SGBD – système
de gestion de base de données)
ou s’il se ferme lui-même, les éventuels
connection pools SqlClient existants
demeurent, à  moins que IIS ou MTS ne
se ferment aussi. Ces pools restants
sont appelés zombied pools (pools
zombies). Si l’on redémarre ultérieurement
SQL Server, le SqlClient .NET
Data Provider essaie d’utiliser les zombied
pools pour se reconnecter au serveur.
Le résultat est le System.Data.
SqlClient.SqlException General
network error. Check your network
documentation. Heureusement, cette
exception détruit les zombied pools et,
quand le composant redémarre, le
SqlClient .NET Data Provider crée un
nouveau pool. Je conseille vivement
d’ajouter un gestionnaire d’exceptions
pour traiter cette situation.

Téléchargez gratuitement cette ressource

Comment cerner la maturité digitale de votre entreprise ?

Comment cerner la maturité digitale de votre entreprise ?

Conçu pour les directions IT et Métiers, ce guide vous permettra d'évaluer précisément vos processus de communication client, d'identifier vos lacunes et points d'inflexion pour établir un plan d’actions capable de soutenir durablement votre évolution. Bénéficiez maintenant d'une feuille de route complète.

Tech - Par iTPro - Publié le 24 juin 2010