J’ai récemment eu besoin de limiter l’utilisation d’une portion de mon code entre différents services (à la manière d’une sémaphore).
J’utilise RedLock.net (lock distribué) pour gérer la concurrence mais ce dernier ne fait qu’un verrou unitaire (concurrence = 1) et donc ne répondait pas à mon besoin.
En parcourant un peu le site RedisLabs j’ai pu tomber sur cette algorithme qui propose une implémentation “juste” (premier arrivé premier servi) d’une semaphore distribuée.
N’existant pas d’implémentation en .NET j’ai du en développer une moi même.
Vous pouvez retrouver les sources ici: https://github.com/Golapadeog/DSemaphore.net (le package nuget arrivera prochainement)
Utilisation
Dans un premier temps on créé une factory
|
|
Qui nous permet d’instancier nos sémaphores.
A la manière de la classe SemaphoreSlim on indique le maximum de concurrence que l’on souhaite
|
|
Et il suffit de verrouiller avec la méthode WaitAsync.
|
|
Et voilà c’est aussi simple que ça! 👌
Limites et recommandations
En implémentant l’algorithme proposée par RedisLabs j’ai pu y voir quelques limites (qui sont propre au système distribué et difficilement corrigeables sans apporter de la lourdeur).
- Comme énoncé précédemment si votre service s’arrête pour une raison X et donc n’a pas le temps de libérer son vérrouillage alors ce dernier ne sera considéré comme obsolète qu’à la fin du délai indiqué à l’appel de la méthode WaitAsync
- La vérification fonctionne par polling, par défaut la fréquence est établie à 10ms, il est possible de la configurer à la création de la sémaphore. Mais cette fréquence provoque une incertitude sur la détection des verrous obsolètes. Il est recommandé d’utiliser des timeouts >= 1sec pour ne pas rencontrer de problème. (pour faire simple la précision permettant de déterminer si une semaphore a expirée ou non est de +/- la fréquence de vérification)
En théorie oui, car un lock peut être traité par une semaphore à 1.
En revanche je ne le recommande pas, même si cette implémentation est très performante, elle ne l’est pas autant que les solutions de lock classique qui ont bien moins de vérifications à faire.
En bref c’est du code classique: semaphore pour limiter la concurrence et lock pour l’empêcher.