Règle
Libération blocage même sur d'exception d'exception.
Chaque verrouillage acquisition doit avoir a garantie
garantie, même lorsque exceptions se produisent.
Langues pris en charge:** Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonIntroduction
Les verrous non libérés sont l'une des causes les plus courantes de blocages et d'arrêts du système dans les applications Node.js de production. Lorsqu'une exception se produit entre l'acquisition du verrou et sa libération, le verrou reste bloqué indéfiniment. Les autres opérations asynchrones qui attendent ce verrou sont bloquées pour toujours, ce qui provoque des pannes en cascade sur le système. Un seul mutex non libéré peut entraîner l'arrêt d'une API entière, car la boucle d'événements se bloque et les demandes s'accumulent. Cela se produit avec des bibliothèques comme async-mutex, mutexifierou tout système de verrouillage manuel dont le déverrouillage n'est pas automatique.
Pourquoi c'est important
Stabilité et disponibilité du système : Les verrous non libérés provoquent des blocages qui bloquent les opérations asynchrones dans Node.js. Dans les serveurs Express ou Fastify, cela épuise les travailleurs disponibles, rendant l'application incapable de traiter de nouvelles requêtes. La seule solution consiste à redémarrer le processus, ce qui entraîne des temps d'arrêt. Dans les architectures microservices, les verrous non libérés dans un service peuvent entraîner des défaillances en cascade dans les services dépendants qui attendent des réponses.
Dégradation des performances : Avant le blocage complet, les verrous non libérés entraînent de graves problèmes de performance. Les opérations asynchrones se disputent les ressources verrouillées, créant une file d'attente de promesses en suspens qui ne sont jamais résolues. La contention des verrous crée des pics de latence imprévisibles qui dégradent l'expérience de l'utilisateur. Lorsque le nombre de requêtes simultanées augmente sous l'effet de la charge, la contestation s'aggrave de manière exponentielle.
Complexité du débogage : Les blocages dus à des verrous non libérés sont notoirement difficiles à déboguer dans les applications Node.js de production. Les symptômes apparaissent loin de la cause première, les processus suspendus montrent les promesses en attente mais pas le chemin d'exception qui n'a pas permis de libérer le verrou. Reproduire la séquence exacte d'exceptions qui a déclenché le blocage est souvent impossible dans les environnements de développement.
Épuisement des ressources : Au-delà des verrous eux-mêmes, l'incapacité à libérer les verrous est souvent liée à l'incapacité à libérer d'autres ressources telles que les connexions aux bases de données, les clients Redis ou les gestionnaires de fichiers. Cela aggrave le problème, en créant de multiples fuites de ressources qui font tomber les systèmes plus rapidement sous la charge.
Exemples de code
❌ Non conforme :
const { Mutex } = require('async-mutex');
const accountMutex = new Mutex();
async function transferFunds(from, to, amount) {
await accountMutex.acquire();
if (from.balance < amount) {
throw new Error('Insufficient funds');
}
from.balance -= amount;
to.balance += amount;
accountMutex.release();
}
Pourquoi ce n'est pas sûr : Si l'erreur "fonds insuffisants" est déclenchée, accountMutex.release() ne s'exécute jamais et le mutex reste verrouillé pour toujours. Tous les appels ultérieurs à transferFunds() se bloquera dans l'attente du mutex, gelant ainsi l'ensemble du système de paiement.
✅ Conforme :
const { Mutex } = require('async-mutex');
const accountMutex = new Mutex();
async function transferFunds(from, to, amount) {
const release = await accountMutex.acquire();
try {
if (from.balance < amount) {
throw new Error('Insufficient funds');
}
from.balance -= amount;
to.balance += amount;
} catch (error) {
logger.error('Transfer failed', {
fromId: from.id,
toId: to.id,
amount,
error: error.message
});
throw error;
} finally {
release();
}
}Pourquoi c'est sûr : Le attraper enregistre l'erreur avec le contexte avant de la relancer, et le bloc enfin garantit que la fonction de libération du mutex s'exécute, que l'opération réussisse, qu'elle provoque une erreur ou que l'erreur soit à nouveau provoquée par la fonction catch. Le verrou est toujours libéré, ce qui évite les blocages.
Conclusion
La libération du verrou doit être garantie et non conditionnée par une exécution réussie. Utiliser essai final en JavaScript ou les blocs runExclusive() fournie par des bibliothèques telles que async-mutex. Chaque acquisition de verrou doit avoir un chemin de libération inconditionnel visible dans le même bloc de code. Une bonne gestion des verrous n'est pas facultative, c'est la différence entre un système stable et un système qui se bloque aléatoirement sous charge.
.avif)
