web-dev-qa-db-fra.com

Pool de connexions Tomcat JDBC: testOnBorrow vs testWhileIdle

Pour diverses raisons, les connexions dans un pool peuvent devenir invalides: délai de connexion du serveur, problèmes de réseau ...

D'après ce que je comprends, un pool de connexions Tomcat JDBC ne fournit aucune garantie quant à la validité des connexions qu'il fournit à l'application.

Pour éviter (en fait seulement de réduire le risque) d'obtenir une connexion non valide à partir du pool, une solution semble être la configuration de la validation des connexions. Valider une connexion signifie exécuter une requête très basique sur la base de données (par exemple SELECT 1; sur MySQL).

Tomcat JDBC Connection Pool propose plusieurs options pour tester la connexion. Les deux que je trouve les plus intéressantes sont testOnBorrow et testWhileIdle.

Au début, je pensais que testOnBorrow est la meilleure option car elle valide essentiellement la connexion avant de la fournir à l'application (avec une fréquence maximale définie par validationInterval).

Mais au bout d'une seconde, j'ai réalisé que tester la connexion juste avant de l'utiliser pouvait avoir un impact sur la réactivité de l'application. Je pense donc que l'utilisation de testWhileIdle peut être plus efficace car elle teste les connexions alors qu'elles ne sont pas utilisées.

Peu importe l'option que je choisis, il semble qu'ils ne font que réduire le risque d'obtenir une connexion non valide, mais ce risque existe toujours.

Je finis donc par demander: dois-je utiliser testOnBorrow ou testWhileIdle ou un mélange des deux?

En passant, je suis surpris que validationInterval ne s'applique pas à testOnReturn et je ne comprends pas vraiment le but de testOnConnect.

14
Antoine Mottier

Il n'y a pas de bonne réponse à 100% à cela. C'est une question de compromis et de contexte.

  • La plupart du temps, testOnBorrow est le moins risqué car il garantit (du mieux qu'il peut) qu'avant qu'une connexion ne soit renvoyée de la piscine pour votre usage, une vérification de base a été effectuée que le client et db-server est en bons termes.
  • Cela n'empêche toujours pas la condition de concurrence critique de la connexion au serveur de tomber, entre le moment où le "contrôle de cohérence" a été effectué et le moment où votre application a utilisé la connexion.
  • Mais en considérant cela comme un cas d'angle, le testOnBorrow donne une assez bonne assurance.

  • Maintenant, le compromis avec cela est que, chaque fois que vous demandez une connexion, une requête (quelle que soit sa légèreté) est effectuée sur le serveur de base de données. Cela peut être très rapide, mais le coût n'est toujours pas nul.

Et si vous avez une application occupée, avec une très bonne fiabilité de connexion à la base de données, alors vous commencerez à voir à partir des données, que le COÛT de "vérification de validité sur chaque demande de connexion du pool" l'emporte sur les avantages de détecter les problèmes de connexion .

  • D'un autre côté, si votre application n'est pas uniformément occupée (comme la plupart des applications du monde réel), il est extrêmement avantageux d'avoir l'option testOnBorrow.
  • Il garantit au maximum que vous avez une bonne connexion avant de l'utiliser. Surtout si l'on considère le coût (nouvelle tentative + intervention manuelle + perte de flux de travail, etc.) de "ne pas pouvoir récupérer facilement" d'une opération de base de données ayant échoué.

  • Imaginez maintenant si vous avez l'option testOnIdle. Cela nécessite que vos connexions deviennent inactives (en fonction du délai d'inactivité de la connexion) avant qu'un contrôle d'intégrité puisse être effectué.

  • Il s'agit d'une amélioration des performances par rapport à testOnBorrow mais elle présente ses propres inconvénients.
    • Les connexions app-to-db dans le monde réel ne sont pas seulement des ruptures basées sur le délai d'inactivité, elles peuvent être supprimées en fonction des règles de pare-feu, de l'encombrement n/w, de la maintenance/des correctifs du serveur db, etc.
    • Cela revient donc à la mesure des données du nombre d'erreurs de connexion observées dans les données, lorsque vous n'aviez aucune sorte de "validation de connexion".
  • Et une chose à surveiller avec cette option est lorsque votre pool fonctionne le mieux avec des connexions maximales et que votre application fonctionne bien, et pour une raison quelconque si votre serveur de base de données subit un redémarrage ou similaire. Toutes les connexions en direct (du point de vue du client) disparaissent désormais pour la plupart, jusqu'à ce que le délai d'inactivité démarre. Donc, votre problème de base de données (qui aurait été un incendie) est maintenant un peu aggravé, jusqu'à ce que les connexions de l'application se rétablissent ou que vous redémarriez également l'application.

Et un dernier point de données est que pour certaines applications, le chemin critique n'est pas le temps de la "requête de validation" (en millisecondes, je l'espère). Les applications ont de plus gros problèmes à traiter. Et bien sûr, pour certaines applications, ce temps est très important.

15
Raja Nadar

Juste pour vous faire savoir, je viens de le tester et il est possible d'utiliser à la fois les propriétés testOnBorrow et testOnIdle.

Comme mentionné ci-dessus, cependant, j'opterai pour testOnBorrow uniquement en raison du fait que mon application n'est pas soumise à un trafic important et peut se permettre de valider une connexion avant de la saisir.

Comme indiqué dans les commentaires, testOnBorrow ne nécessite pas de requête de validation. Si vous choisissez d'en garder un, il peut s'agir d'une simple sélection:

jdbc.Hive.testOnBorrow=true
jdbc.Hive.validationQuery=SELECT 1

Si vous souhaitez utiliser testWhileIdle, vous pouvez utiliser ce qui suit:

jdbc.testWhileIdle=true
jdbc.minEvictableIdleTimeMillis=1800000
jdbc.timeBetweenEvictionRunsMillis=1800000`

Plus d'informations sur DBCP: https://commons.Apache.org/proper/commons-dbcp/configuration.html

6
UltimaWeapon