当前位置:网站首页>Analyse du code source du processus d'acquisition et de connexion hikaricp II
Analyse du code source du processus d'acquisition et de connexion hikaricp II
2022-06-25 19:10:00 【Utilisateur 1422411】
Bienvenue sur mon blog,Synchroniser les mises à jour: Fengshan Hospital
Version source2.4.5-SNAPSHOT
HikariPoolDegetConnection()Méthodes
Dans l'article précédent《HikariCPObtenir l'analyse du code source du processus de connexion I》Moyenne,Nous avons analyséHikariDataSourceDegetConnection()Méthodes,Et cette méthode,En fait, les détails de la mise en œuvre sontHikariPoolDegetConnection()Dans la méthode,Analysons - le.HikariPoolDegetConnection()Méthodes.
Les codes sont les suivants::
public final Connection getConnection() throws SQLException {
return getConnection(connectionTimeout);
}Un autre paramètre est appelé ici.getConnection()Méthodes,Mais nous n'avons pas passé les paramètresconnectionTimeout,D'où ça vient??C'est en fait le paramètre défini par l'utilisateur lors de l'initialisation du pool de connexionconnectionTimeout,Il représente le délai d'obtention de la connexion,Par défaut si non configuré 30Secondes.On continue à regardergetConnection(connectionTimeout);Réalisation:
public final Connection getConnection(final long hardTimeout) throws SQLException {
//①
// Demander un jeton lors de l'obtention d'une connexion , C'est principalement pour le pool de connexion quand il est suspendu , L'utilisateur de contrôle n'a pas pu obtenir la connexion
// Quand le pool de connexion est suspendu , SemaphoreDe 10000 Tous les jetons seront occupés , Le thread sera bloqué ici pour attendre le jeton
suspendResumeLock.acquire();
// Enregistrer l'heure de début de la connexion get , Pour le jugement de temporisation
final long startTime = clockSource.currentTime();
try {
long timeout = hardTimeout;
do {
//②
//Obtenir la connexion à partir du pool de connexion, Temps morttimeout
final PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
//borrow La méthode ne revient que lorsque le temps d'arrêt est écoulé null
if (poolEntry == null) {
break; // We timed out... break and throw exception
}
final long now = clockSource.currentTime();
//③
// Quand vous obtenez la connexion , Déterminer si la connexion a été marquée pour être enlevée
if (poolEntry.isMarkedEvicted() || (clockSource.elapsedMillis(poolEntry.lastAccessed, now) > ALIVE_BYPASS_WINDOW_MS && !isConnectionAlive(poolEntry.connection))) {
// Si la connexion dépasse maxLifetime, Ou le test de connexion échoue , Fermez la connexion
closeConnection(poolEntry, "(connection is evicted or dead)"); // Throw away the dead connection (passed max age or failed alive test)
//Temps d'arrêt restant
timeout = hardTimeout - clockSource.elapsedMillis(startTime);
} else {
//④
// Enregistrer l'emprunt de connexion
metricsTracker.recordBorrowStats(poolEntry, startTime);
//CréationProxyConnection, ProxyConnection- Oui.ConnectionEmballage, Il crée également une tâche programmée pour la détection des fuites
return poolEntry.createProxyConnection(leakTask.schedule(poolEntry), now);
}
} while (timeout > 0L);
} catch (InterruptedException e) {
throw new SQLException(poolName + " - Interrupted during connection acquisition", e);
} finally {
//Relâchez la serrure.
suspendResumeLock.release();
}
//⑤
// Obtenir un délai de connexion pour exécuter le code suivant
logPoolState("Timeout failure ");
metricsTracker.recordConnectionTimeout();
String sqlState = null;
final Throwable originalException = getLastConnectionFailure();
if (originalException instanceof SQLException) {
sqlState = ((SQLException) originalException).getSQLState();
}
final SQLException connectionException = new SQLTransientConnectionException(poolName + " - Connection is not available, request timed out after " + clockSource.elapsedMillis(startTime) + "ms.", sqlState, originalException);
if (originalException instanceof SQLException) {
connectionException.setNextException((SQLException) originalException);
}
throw connectionException;
}①Semaphore
suspendResumeLock.acquire();
// Enregistrer l'heure de début de la connexion get , Pour le jugement de temporisation
final long startTime = clockSource.currentTime();getConnectionPremière étape, Le premier est d'obtenir le jeton . À partir du nom de la variable suspendResumeLockViens voir., Peut - être en attente (suspend)Concernant, Alors Accrochez quelque chose ? Si tout le monde l'avait lu HikariCP Documents,Ou utiliséHikariCP En attente pour , Alors vous avez dû deviner , Il s'agit de suspendre tout le pool de connexions .
- En attenteHikariCP
HikariCP En attente pour , En fait, c'est mettre en pause l'utilisateur pour obtenir la connexion ,C'est - à - dire, Après avoir suspendu tout le pool de connexion , S'il y a un thread pour obtenir une connexion à partir du pool de connexion , Alors ça va continuer à bloquer , Jusqu'à ce que le pool de connexion soit restauré .
A quoi bon raccrocher ?
Auteur brett Référence à l'utilisation en attente :
- Suspendre le pool de connexion
- Modifier la configuration du pool de connexion à la base de données ,Ou changer DNS Configuration( Pointez vers le nouveau serveur principal )
- Connexion existante dans le pool de connexion par disquette
- Restaurer le pool de connexion
HikariCP Peut passer pendant la période d'exécution JMXModifier certaines configurations( Pas toutes les configurations ), Oui.:connectionTimeout(Obtenir le temps d'arrêt de la connexion),leakDetectionThreshold( Temps de détection des fuites de connexion ),maxPoolSize(Nombre maximum de connexions au pool de connexions),minIdle(Nombre minimum de connexions inactives),maxLifetime(Durée de vie maximale de la connexion),idleTimeout( Connexion temps libre maximum ),Total 7 Item (s).
Par exemple, j'ai suspendu le pool de connexion ,Et il a été modifiémaxLifetime, Alors la connexion existante dans le pool de connexion est toujours la configuration précédente , Je vais expulser toutes les connexions de la piscine de connexion , Et ensuite restaurer le pool de connexion , Le pool de connexion crée une nouvelle connexion en utilisant la nouvelle configuration .
En plus de ça,, Vous pouvez également utiliser le pool de connexion pour suspendre , Le thread a été bloqué pour obtenir cette fonctionnalité de connexion , Pour simuler une défaillance de connexion à la base de données , Pour tester l'application .
- Comment cela a - t - il été réalisé?
OK, Nous savons que le but principal de ce code est de suspendre le pool de connexion , Empêcher l'utilisateur d'obtenir la connexion .Comment cela a - t - il été réalisé??
En fait...,suspendResumeLockLa classe decom.zaxxer.hikari.util.SuspendResumeLock, À l'intérieur, on utilise SemaphoreRéalisé.Semaphore- Oui. java DeconcurrentEnveloppé Classes d'outils simultanées, Il est utilisé pour tokeniser les fils , Nombre simultané de fils de contrôle .
Un exemple de scénario, Si c'était une seconde : Nous savons que la plus grande capacité de traitement simultané du serveur est le traitement simultané 1000 Demandes,Plus que 1000 Les serveurs de requête peuvent être désactivés , Sans expansion , Essayez de vous assurer que le service est disponible .À ce moment - là., Nous sommes sur le point de contrôler que le nombre de demandes des utilisateurs ne peut pas dépasser 1000Pas vrai?.
On peut utiliserSemaphoreRéalisation,Semaphore Comme un seau de jetons , Le seau peut contenir un nombre spécifié de jetons ,En parallèle, Chaque fil prend un dans le seau (Ou plusieurs)Token, Celui qui a le jeton peut continuer , Si vous n'avez pas le jeton, attendez. ( Selon la stratégie , Ou peut - être lancer une exception, etc ), Jusqu'à ce qu'un autre thread libère le jeton , Obtenir un jeton pour continuer .
La scène ci - dessus,On peut utiliserSemaphoreInitialisation 1000 Jetons, Prenez un jeton par fil , De cette façon, nous pouvons contrôler que le nombre de demandes traitées simultanément ne dépasse pas 1000C'est bon.
La même chose., Voyons comment suspendre le pool de connexion :
public void suspend() {
//MAX_PERMITS = 10000
acquisitionSemaphore.acquireUninterruptibly(MAX_PERMITS);
}HikariCP Initialisé ici 1 10 000 jetons ,Si l'utilisateur appellesuspend() Suspendre le pool de connexion ,En fait, c'est un appelSemaphoreObtenir une fois 1 10 000 jetons , Pour que les autres fils n'aient pas de jetons à prendre , J'ai dû attendre , Jusqu'à ce que l'utilisateur récupère le pool de Threads ,Libérez ça. 1 Dix mille jetons dans le seau .
Il est important de noter que, Pour utiliser la fonctionnalité du pool de connexions en attente ,Doit être configuréisAllowPoolSuspension=true, Sinon, l'utilisation de la fonction en attente entraînera une erreur .
Nous avons mentionnéisAllowPoolSuspension En fait, je dois dire suspendResumeLockUn point d'optimisation pour.
Lors de l'initialisation du pool de connexion ,C'estsuspendResumeLock Selon que vous avez activé la fonction de suspension ,Il y aura différentes implémentations,this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK;.
Si la fonction en attente n'est pas activée ,AlorssuspendResumeLockC'est unFAUX_LOCK.
FAUX_LOCKQu'est - ce que?Regarde le Code.:
public static final SuspendResumeLock FAUX_LOCK = new SuspendResumeLock(false) {
@Override
public void acquire() {}
@Override
public void release() {}
@Override
public void suspend() {}
@Override
public void resume() {}
};Tu n'as pas mal lu, C'est une implémentation vide ,Il n'y a rien dans la méthode.
À quoi ça sert??En fait, oui., Quand la fonction de suspension n'est pas activée , Il fournira une implémentation vide , L'espoir JIT Peut l'optimiser .C'est - à - dire, Chaque fois qu'un jeton est demandé, une méthode vide est appelée ,Ne fais rien., Le Code a été exécuté plusieurs fois ,JIT Il est possible de l'optimiser , Il n'y a pas d'appel du tout .Voilà., Chaque fois qu'on obtient une connexion , Économisez les frais généraux supplémentaires liés à la demande de jetons ,Amélioration des performances.
La vague la plus rapide n'est généralement pas un faux nom , Il doit y avoir quelque chose à apprendre ......Avez - vous appris?
Nous poursuivons l'analyse.
clockSource C'est une classe d'outils temporels ,Pour obtenir l'heure actuelle, Calculer la différence de temps, etc . L'heure actuelle est enregistrée ici , Pour le calcul ultérieur de la différence de temps , Utilisé pour déterminer si la connexion d'acquisition a expiré .
②Obtenir la connexion
//②
//Obtenir la connexion à partir du pool de connexion, Temps morttimeout
final PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
//borrow La méthode ne revient que lorsque le temps d'arrêt est écoulé null
if (poolEntry == null) {
break; // We timed out... break and throw exception
} Code ici ,Nous pouvons voir,DeconnectionBagJ'ai unpoolEntryObjet.poolEntry En fait, c'est une classe d'emballage pour la connexion à la base de données ,connectionBagC'est HikariCP Conteneur dans lequel la connexion à la base de données est effectivement enregistrée ,Il y a unCopyOnWriteArrayList.Parce queconnectionBagTrès important., Nous allons l'analyser séparément plus loin , Il n'y a pas de profondeur ici .
Mais à partir deconnectionBag Quand vous obtenez la connexion , Je vois un paramètre passé timeout,C'esttimeout C'est ce que nous avons configuré connectionTimeout,Obtenir le temps d'arrêt de la connexion,Si letimeoutDans le temps, Aucune connexion retournée ,Alors retournez à un null.
Il y a déjà un délai , Donc le jugement suivant est de sauter de la boucle , Je n'essaie pas d'obtenir la connexion .
Parce qu'il est trop long dans un article ,Questions en suspens,Suite du chapitre suivant!
边栏推荐
- Does GoogleSEO need to change the friend chain? (e6zzseo)
- LeetCode-101-对称二叉树
- Lilda Bluetooth air conditioning receiver helps create a more comfortable road life
- IDEA常用插件
- 网络安全检测与防范 测试题(二)
- Server journey from scratch - Yu Zhongxian integrated version (IP access server, LNMP compilation and installation, Lua environment and socket expansion)
- Tcp/ip test questions (V)
- QQ robot epidemic situation query / epidemic situation concern [latest beta2 version]
- Ali visual AI training camp -day05- creativity day - your image recognition project
- From the perspective of the core competitiveness of ABT, the Internet giant, who fell first
猜你喜欢

谈谈CNN中的位置和尺度问题

What are Baidu collection skills? 2022 Baidu article collection skills

Guangzhou Sinovel interactive creates VR Exhibition Hall panoramic online virtual exhibition hall

Kotlin Compose 终结toDo项目 点击可以编辑修改todo
![QQ robot: self forbidden words management of group members [latest beta2 version]](/img/1b/7dcc8ed344c9f62870d76f16b99f1d.png)
QQ robot: self forbidden words management of group members [latest beta2 version]

【C语言练习——打印上三角及其变形(带空格版)】

One night I worked as an XPath Terminator: XPath Helper Plus

Leetcode-78-subset

Laravel validation rule followed Role of auth:: id()
![[today in history] June 25: the father of notebook was born; Windows 98 release; First commercial use of generic product code](/img/ef/a26127284fe57ac049a4313d89cf97.png)
[today in history] June 25: the father of notebook was born; Windows 98 release; First commercial use of generic product code
随机推荐
Current situation of China's hydraulic cylinder industry in 2020 (with application fields, policies and regulations, supply and demand status and enterprise pattern) [figure]
Kotlin compose terminate todo project Click to edit and modify todo
中金财富安全吗? 开户需要多久
Solve the problem that sublime Text3 package control cannot install plug-ins
Google SEO external chain releases 50+ website platform sharing (e6zzseo)
Tiger DAO VC产品正式上线,Seektiger生态的有力补充
跳一跳小游戏辅助(手动版本)py代码实现
solidity日期工具
两轮市场红海,利尔达芯智行如何乘风破浪?
solidity 合约地址转钱包、钱包地址转合约
[C language practice - print the upper triangle and its deformation (with blank version)]
The meanings of /32, /48, /64 in IPv6 addresses
Is it safe to open an account with flush?
利尔达蓝牙空调接收器方案助力打造更舒适的公路生活
PHP数据库连接version1.1
Overview and trend analysis of China's CT examination equipment industry in 2021 [figure]
QQ机器人:群成员自我禁言管理【最新beta2版本】
Ali vision AI training camp-day01
Leetcode-101-symmetric binary tree
What are Baidu collection skills? 2022 Baidu article collection skills