Des lecteurs comme vous aident à soutenir MUO. Lorsque vous effectuez un achat en utilisant des liens sur notre site, nous pouvons gagner une commission d'affiliation. En savoir plus.

En tant que développeur Web, il est crucial que vos applications fonctionnent aussi rapidement que possible. Vous devez créer des applications Web qui répondent aux demandes le plus rapidement possible.

L'une des nombreuses technologies qui peuvent vous aider est la mise en file d'attente des tâches.

Alors, qu'est-ce que la file d'attente de tâches et comment pouvez-vous l'utiliser pour optimiser une application Node.js ?

Qu'est-ce que la file d'attente de tâches?

La file d'attente de messages est un moyen de communication asynchrone entre deux applications ou services, généralement appelé le producteur et consommateur. C'est un concept bien connu utilisé dans les architectures sans serveur et microservices.

La notion de tâche ou emploifaire la queue exploite la file d'attente des messages pour améliorer les performances des applications. Il résume les complexités de la gestion des messages et vous permet de définir des fonctions pour gérer les travaux ou les tâches de manière asynchrone à l'aide d'une file d'attente, réduisant ainsi le taux de

utilisation de la mémoire dans certaines parties d'une application.

L'exemple le plus courant de logiciel de file d'attente de messages est RabbitMQ. Les outils de file d'attente de tâches incluent Celery et Bull. Vous pouvez également configurer RabbitMQ pour qu'il fonctionne comme une file d'attente de tâches. Lisez la suite pour en savoir plus sur la mise en file d'attente de tâches dans Node.js à l'aide de Bull.

Qu'est-ce que BullMQ?

BullMQ (Bull.js) est une bibliothèque Node.js utilisée pour implémenter des files d'attente dans les applications Node. Bull est un système basé sur Redis (vous connaissez peut-être mieux Redis en tant qu'outil de stockage rapide des données) et c'est une option rapide et fiable à considérer pour la mise en file d'attente des tâches dans Node.js.

Vous pouvez utiliser Bull pour de nombreuses tâches telles que la mise en œuvre de travaux différés, de travaux planifiés, de travaux répétables, de files d'attente prioritaires, etc.

Alors, comment pouvez-vous utiliser Bull et Redis pour exécuter des tâches Node.js de manière asynchrone ?

Comment configurer Bull et Redis pour la mise en file d'attente de tâches dans Node.js

Pour démarrer avec la mise en file d'attente des tâches dans Node.js avec Bull, vous devez installer Node.js et Redis sur votre machine. Vous pouvez suivre le Guide des laboratoires Redis pour installer Redis si vous ne l'avez pas installé.

La première étape de l'implémentation de Bull consiste à l'ajouter aux dépendances de votre projet en exécutant npm installer taureau ou fil ajouter taureau dans le terminal à l'intérieur du dossier de votre projet. Il existe plusieurs façons d'initialiser une file d'attente dans Bull, comme indiqué ci-dessous :

constante File d'attente = exiger('taureau');

// différentes façons d'initialiser une file d'attente
// - en utilisant la chaîne d'URL redis
constante emailQueue = nouveau File d'attente("File d'attente des e-mails", 'redis://127.0.0.1:6379');

// - avec une connexion redis et un objet d'options de file d'attente
constante file d'attente vidéo = nouveau File d'attente("File d'attente vidéo", 'redis://127.0.0.1:6379', queueOptions);

// - sans connexion redis mais avec queueOption
constante docQueue = nouveau File d'attente("File d'attente de documents", queueOptions);

// - sans connexion redis ni options de file d'attente
constante File d'attente = nouveau File d'attente("Ma file d'attente");

Ceux-ci utilisent tous une configuration minimale pour Bull dans Node.js. L'objet options prend en charge de nombreuses propriétés et vous pouvez en apprendre davantage à leur sujet dans le section des options de file d'attente de la documentation de Bull.

Implémentation d'une file d'attente de tâches de messagerie à l'aide de BullMQ

Pour implémenter une file d'attente pour l'envoi d'e-mails, vous pouvez définir votre fonction producteur qui ajoute des e-mails à la file d'attente d'e-mails, et une fonction consommateur pour gérer l'envoi d'e-mails.

Tout d'abord, vous pouvez initialiser votre file d'attente dans une classe à l'aide d'une URL Redis et de certaines options de file d'attente, comme indiqué ci-dessous.

// queueHandler.js
constante File d'attente = exiger('taureau');

// utilise ici un vrai module de gestion d'e-mails - ceci n'est qu'un exemple
constante emailHandler = exiger('./emailHandler.js');

// définit les constantes, l'URL Redis et les options de file d'attente
constante REDIS_URL = 'redis://127.0.0.1:6379';

constante queueOpts = {
// options de limiteur de débit pour éviter de surcharger la file d'attente
limiteur: {
// nombre maximum de tâches que la file d'attente peut prendre
maximum: 100,

// temps d'attente en millisecondes avant d'accepter de nouvelles tâches après
// atteint la limite
durée: 10000
},
préfixe: 'EMAIL-TASK', // un préfixe à ajouter à toutes les clés de file d'attente
Options de travail par défaut: { // options par défaut pour les tâches dans la file d'attente
tentatives: 3, // nombre de fois par défaut pour réessayer une tâche

// pour supprimer une tâche de la file d'attente après l'achèvement
removeOnComplete: vrai
}
};

classeFile d'attente des e-mails{
constructeur() {
ce.queue = nouveau File d'attente("File d'attente des e-mails", REDIS_URL, queueOpts);
}
};

exporterdéfaut file d'attente d'e-mail; // exporte la classe

Maintenant que vous avez initialisé une file d'attente, vous pouvez définir votre fonction producteur (à l'aide de Bull ajouter() fonction) comme méthode de File d'attente des e-mails classe pour ajouter des e-mails à la file d'attente des tâches. Le bloc de code suivant le démontre :

// queueHandler.js

classeFile d'attente des e-mails{
constructeur () {
// ...
}

// fonction producteur pour ajouter des e-mails à la file d'attente
asynchrone addEmailToQueue (emailData) {
// ajoute une tâche avec le nom 'email_notification' à la file d'attente
attendrece.queue.add('notification_e-mail', e-mailDonnées) ;
console.enregistrer('l'e-mail a été ajouté à la file d'attente...');
}
};

exporterdéfaut file d'attente d'e-mail; // exporte la classe

La fonction producteur est prête, vous pouvez maintenant définir une fonction consommateur (à l'aide de Bull processus() ) pour traiter toutes les tâches de messagerie dans la file d'attente, c'est-à-dire appelez la fonction pour envoyer un e-mail. Vous devez définir cette fonction consommateur dans le constructeur de la classe.

// queueHandler.js
classeFile d'attente des e-mails{
constructeur () {
// ...

// fonction consommateur qui prend le nom assigné de la tâche et
// une fonction de rappel
ce.queue.process('notification_e-mail', asynchrone (emailJob, fait) => {
console.enregistrer("traitement de la tâche de notification par e-mail");
attendre emailHandler.sendEmail (emailJob); // envoie le mail
fait(); // finissez la tâche
})
}
// ...
};

exporterdéfaut file d'attente d'e-mail; // exporte la classe

Un travail peut également avoir des options pour définir son comportement dans la file d'attente ou la façon dont la fonction consommateur le gère. Vous pouvez en savoir plus à ce sujet dans le section des options d'emploi de la documentation de Bull.

Le e-mailEmploi argument est un objet qui contient les propriétés de la tâche que la file d'attente doit traiter. Il comprend également les principales données nécessaires à la construction de l'e-mail. Pour faciliter la compréhension, le envoyerEmail() fonction serait similaire à cet exemple:

// emailHandler.js
constante sendgridMail = exiger('@sendgrid/mail');

constante apiKey = process.env. SENDGRID_API_KEY

sendgridMail.setApiKey (apiKey); // définit les identifiants de sécurité du transporteur de messagerie

constante envoyerEmail = asynchrone (emailJob) => {
essayer {
// extrait les données de l'e-mail du travail
constante { nom, email } = emailJob.data ;

constante msg = {
depuis: '[email protected]',
pour: '[email protected]',
sujet: 'Salut! Accueillir',
texte: `Bonjour ${nom}, bienvenue à MUO`
};

attendre sendgridMail.sendMail (message); // envoyer un e-mail

// marque la tâche comme terminée dans la file d'attente
attendre emailJob.moveToCompleted('fait', vrai);
console.enregistrer('E-mail envoyé avec succès...');
} attraper (erreur) {
// déplace la tâche vers les travaux ayant échoué
attendre emailJob.moveToFailed({ message: 'le traitement de la tâche a échoué..' });
console.error (erreur); // enregistre l'erreur
}
}

exporterdéfaut envoyerEmail ;

Maintenant que les fonctions de producteur et de consommateur sont définies et prêtes à être utilisées, vous pouvez maintenant appeler votre fonction de producteur n'importe où dans votre application pour ajouter un e-mail à la file d'attente pour le traitement.

Un exemple de contrôleur ressemblerait à ceci :

// userController.js
constante File d'attente des e-mails = exiger('../handlers/queueHandler.js')

constante s'inscrire = asynchrone (req, res) => {
constante { nom, email, mot de passe } = req.body ;

// --
// une requête pour ajouter le nouvel utilisateur à la base de données...
// --

// ajouter à la file d'attente des e-mails
constante emailData = { nom, email } ;
attendre EmailQueue.addEmailToQueue (emailData);

res.statut(200).json({
message: "Inscription réussie, veuillez vérifier votre e-mail"
})
}

Ton queueHandler.js le fichier devrait maintenant être comme suit :

// queueHandler.js
constante File d'attente = exiger('taureau');
constante emailHandler = exiger('../handlers/emailHandler.js');

constante REDIS_URL = 'redis://127.0.0.1:6379';

constante queueOpts = {
limiteur: {
maximum: 100,
durée: 10000
},

préfixe: 'EMAIL-TASK',

Options de travail par défaut: {
tentatives: 3,
removeOnComplete: vrai
}
};

classeFile d'attente des e-mails{
constructeur() {
ce.queue = nouveau File d'attente("File d'attente des e-mails", REDIS_URL, queueOpts);

// consommateur
ce.queue.process('notification_e-mail', asynchrone (emailJob, fait) => {
console.enregistrer("traitement de la tâche de notification par e-mail");
attendre emailHandler.sendEmail (emailJob);
fait();
})
}

// producteur
asynchrone addEmailToQueue (emailData) {
// ajoute une tâche avec le nom 'email_notification' à la file d'attente
attendrece.queue.add('notification_e-mail', e-mailDonnées) ;
console.enregistrer('l'e-mail a été ajouté à la file d'attente...');
}
};

exporterdéfaut file d'attente d'e-mail ;

Lorsque vous implémentez cela dans une API REST Node.js, vous remarquerez une diminution du temps de réponse du point de terminaison d'inscription et des délais de livraison des e-mails plus rapides, par rapport à l'alternative.

Les files d'attente de tâches vous ont également permis de gérer indépendamment les erreurs d'inscription et d'e-mail.

Optimisation des applications à l'aide des files d'attente de tâches

Les files d'attente de messages et de tâches sont un excellent moyen d'améliorer les performances générales des applications. Ils sont également très bon marché et vous pouvez les utiliser dans autant de parties d'une application que vous le souhaitez.

Bien que ce didacticiel ait utilisé les e-mails comme exemple de scénario pour gérer les tâches gourmandes en mémoire avec des files d'attente, il existe de nombreux autres cas où vous pouvez appliquer les mêmes concepts. Il s'agit notamment des opérations de lecture/écriture lourdes, du rendu d'images ou de documents de haute qualité et de l'envoi de notifications groupées.