La délégation de tâches en asynchrone est un moyen efficace d’alléger la charge que subissent nos systèmes. En effet, de nombreux cas d’utilisation ne nécessitent pas d’être exécutés de façon synchrone lorsqu’un utilisateur effectue une action ou qu’un événement extérieur intervient.
Par exemple, lorsqu’il n’est pas nécessaire de restituer la dernière version des données et que le traitement avant restitution est coûteux en ressources, il est possible de renvoyer des données préalablement mises en cache et de déporter en asynchrone une tâche de rafraîchissement de ce cache.
Un autre exemple concerne les systèmes qui mêlent des requêtes fortement consommatrices en ressources (CPU, mémoire, …) et des requêtes peu consommatrices pour lesquelles on va vouloir garantir une latence faible même lorsque des requêtes consommatrices sont en cours de traitement. Pour cela, déléguer les traitements coûteux à des workers via une file de messages peut aider à garantir des temps de réponse faibles pour les autres requêtes. Cette séparation est d’autant plus importante sur des systèmes qui s’appuient sur des technologies monothreadées telles que Ruby ou NodeJS (ce dernier a néanmoins l’avantage de ne pas consommer de ressources/process lorsqu’il effectue des I/O).
Pour résoudre cette problématique de délégation de tâches, on utilise habituellement une solution comme ActiveMQ ou RabbitMQ. Seulement, lorsqu’il est nécessaire :
- d’être tolérant à la panne
- d’être scalable que ce soit en ajoutant des publishers (qui soumettent les tâches asynchrones) ou des workers (qui consomment et exécutent ces tâches)
- de pouvoir intégrer des systèmes hétérogènes s’exécutant sur différentes plateformes (Java, Ruby, NodeJS, C, …)
aucune de ces deux solutions ne permet de satisfaire l’ensemble de ces critères. Cet article présente une solution possible à base de ZeroMQ, écrite en NodeJS et utilisée pour traiter les deux exemples précédents.
(Lire la suite…)