Aperçu
Lorsque j'interviewais à NetEase, l'intervieweur m'a posé une question et m'a dit
Après avoir passé une commande, si l'utilisateur ne paie pas et doit annuler la commande, que puis-je faire?
Ma réponse à l'époque était d'utiliser une tâche chronométrée pour scanner la table DB. L'intervieweur n'était pas très satisfait et a demandé:
Existe-t-il une autre façon d'utiliser des tâches chronométrées pour obtenir des notifications précises en temps réel?
Ma réponse à ce moment-là était:
Vous pouvez utiliser une file d'attente. Une fois la commande passée, un message est envoyé à la file d'attente et le temps d'expiration est spécifié. Une fois l'heure arrive, l'interface de rappel est exécutée.
Après que l'intervieweur ait écouté, il a cessé de demander. En fait, mon idée était juste à ce moment-là, mais je n'étais pas très professionnel. Le dicton professionnel est d'utiliser des messages retardés.
En fait, il y a en effet un problème avec l'utilisation de tâches chronométrées. Le système commercial d'origine espère que si la commande n'est pas payée en 10 minutes, la commande sera annulée immédiatement et que l'inventaire des produits sera publié. Cependant, une fois le volume de données important, le délai d'obtention des données de commande non rémunérés sera étendu. Certaines commandes seront annulées après 10 minutes, ce qui peut durer 15 minutes, 20 minutes, etc. De cette façon, l'inventaire ne sera pas libéré à temps et affectera également le nombre impair. En utilisant des messages de retard, l'opération d'annulation de la commande peut théoriquement être effectuée en fonction de l'heure définie.
Actuellement, la plupart des articles sur Internet sur l'utilisation de RabbitMQ pour implémenter des messages retardés concernent la façon d'utiliser la file d'attente de lettres Dead RabbitMQ à implémenter. La solution d'implémentation semble très compliquée et est implémentée à l'aide de l'API du client RabbitMQ d'origine, qui est encore plus verbeux.
Spring Boot a enveloppé l'API client RabbitMQ, qui est beaucoup plus simple à utiliser. Voici une introduction détaillée sur la façon d'utiliser le plug-in Rabbitmq_delayed_Message_Exchange et le démarrage Spring pour implémenter des messages retardés.
Préparation de logiciels
erlang
La version utilisée dans cet article est: Erlang 20.3
Lapin
Cet article utilise la version de la fenêtre de Rabbitmq, le numéro de version est: 3.7.4
Rabbitmq_delayed_Message_Exchange Plugin
Adresse de téléchargement du plugin: http://www.rabbitmq.com/community-plugins.html
Après avoir ouvert l'URL, Ctrl + F et recherchez Rabbitmq_delayed_Message_Exchange.
N'oubliez pas que vous devez choisir le numéro de version. Puisque j'utilise Rabbitmq 3.7.4, le plug-in Rabbitmq_delayed_Message_Exchange correspondant doit également choisir 3.7.x.
Si vous ne sélectionnez pas la bonne version, vous rencontrerez divers problèmes étranges lorsque vous utiliserez des messages retardés et il n'y a pas de solution sur Internet. J'ai lutté toute la nuit à cause de ce problème. N'oubliez pas de sélectionner la bonne version du plug-in.
Après avoir téléchargé le plugin, placez-le dans le répertoire des plugins sous le répertoire d'installation RabbitMQ et démarrez le plugin à l'aide de la commande suivante:
Rabbitmq-Plugins Activer Rabbitmq_delayed_Message_Exchange
Si le démarrage réussit, le message suivant apparaît:
Les plugins suivants ont été activés: Rabbitmq_delayed_Message_Exchange
Une fois le plug-in lancé avec succès, n'oubliez pas de redémarrer RabbitMQ pour le faire entrer en vigueur.
Rabbitmq intégré
C'est très simple, ajoutez-le simplement dans le fichier pom.xml du projet Maven
<dependency> <proupId> org.springframework.boot </rombasid> <ArtifactId> printemp-boot-starter-amqp </etefactId> </Dependency>
J'utilise 2.0.1.release pour Spring Boot.
Ensuite, ajoutez la configuration redis dans le fichier application.properties:
printemps.rabbitmq.host = 127.0.0.1spring.rabbitmq.port = 5672Spring.rabbitmq.Username = invitépring.rabbitmq.password = invité
Définir ConnectionFactory et RabbitTemplate
C'est aussi très simple, le code est le suivant:
package com.mq.rabbitmq; import org.springframework.amqp.rabbit.connection.cachingconnectionfactory; import org.springframework.amqp.rabbit.connection.connectionfactory; import org.springframework.amqp.rabbit.Core.rabbitTemplate; import; org.springframework.boot.context.properties.configurationproperties; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; @ configuration @ configuration rabbitmqqqqqqqqqqqqqqqqqqc {spring hospital; port int privé; Nom d'utilisateur de chaîne privée; mot de passe de chaîne privé; @Bean public ConnectionFactory ConnectionFactory () {CachingConnectionFactory CachingConnectionFactory = new CachingConnectionFactory (hôte, port); cachingConnectionFactory.SetUsername (nom d'utilisateur); cachingConnectionFactory.SetPassword (mot de passe); cachingConnectionFactory.setVirtualHost ("/"); cachingConnectionFactory.SetPublisherConfirms (true); retour CachingConnectionFactory; } @Bean public RabbitTemplate RabbitTemplate () {RabbitTemplate RabbitTemplate = new RabbitTemplate (ConnectionFactory ()); return RabbitTemplate; } public String gethost () {return host; } public void sethost (string host) {this.host = host; } public int getport () {port de retour; } public void setport (int port) {this.port = port; } public String getUserName () {return username; } public void setUsername (String username) {this.userName = username; } public String getPassword () {return mot de passe; } public void setPassword (String Motword) {this.password = mot de passe; }}Configuration d'échange et de file d'attente
package com.mq.rabbitmq; import org.springframework.amqp.core. *; import org.springframework.context.annotation.bean; import org.springframework.contex @Bean public customexchange DelayExchange () {map <string, object> args = new hashmap <> (); Args.put ("X-délai-Type", "Direct"); return new CustomexChange ("test_exchange", "x-délayed-mess", true, false, args); } @Bean Public Queue Queue () {file d'attente file d'attente = nouvelle file d'attente ("test_queue_1", true); retour de la file d'attente; } @Bean Public Binding Binding () {return binkingBuilder.bind (queue ()). To (delayExchange ()). Avec ("test_queue_1"). Noargs (); }}Il convient de noter ici que CustomexChange est utilisé, et non DirectExchange, et le type de Customexchange doit être un message en dérivation X.
Implémenter l'envoi de messages
package com.mq.rabbitmq; import org.springframework.amqp.amqpexception; import org.springframework.amqp.core.mesage; import org.springframework.amqp.core.messagepostprocessor; import org.springframework.amqp.rabbit.core.Rabbitmplate; org.springframework.beans.factory.annotation.Autowired; import org.springframework.sterreotype.service; import java.text.simpledateFormat; import java.util.date; @servicepublic class MessmeServiceIMPL {@autowired private rabbitTemplate rabbitTemplate; public void sendmsg (string queuename, String msg) {SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); System.out.println ("Message Send Heure:" + sdf.format (new Date ())); RabbitTemplate.ConvertandSend ("test_exchange", queuename, msg, new MessagePostProcessor () {@Override Message publique postProcessMessage (message message) lève Amqpexception {message.getMessageProperties (). Setheader ("x-Delay", 3000); return Message;}}); }}Notez que lors de l'envoi, un en-tête doit être ajouté
retomber
Le temps de retard que j'ai défini ici est de 3 secondes.
Messages
package com.mq.rabbitmq; import org.springframework.amqp.rabbit.annotation.rabbithandler; import org.springframework.amqp.rabbit.annotation.rabbitListener; import org.springframework.Stereotype.Conent; import java.text.simpledateFormat; java.util.date; @ComponentPublic class MessageReceiver {@rabbitListener (que les queues = "test_queue_1") public void reçoile (String msg) {SimpledateFormat sdf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); System.out.println ("Temps de réception des messages:" + sdf.format (new Date ())); System.out.println ("Message reçu:" + msg); }}Exécutez le programme Spring Boot et envoyez des messages
Exécutez le programme Spring Boot directement dans la méthode principale et Spring Boot analysera automatiquement la classe MessageReceiver.
Ensuite, utilisez simplement JUnit pour exécuter l'interface qui envoie le message.
package com.mq.rabbitmq; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.context.springboottest; org.springframework.test.context.junit4.springrunner; @runwith (springrunner.class) @springboottestpublic class rabbitmqapplicationtests {@Autowired messageServiceIMPl MessageService; @Test public void Send () {MessageService.Sendmsg ("test_queue_1", "Bonjour je suis de retard msg"); }} Après avoir fonctionné, vous pouvez voir les informations suivantes:
Message Envoi du temps: 2018-05-03 12:44:53
Après 3 secondes, la console de démarrage à ressort sera sorti:
Heure de réception des messages: 2018-05-03 12:44:56
Message reçu: bonjour je suis de retard msg
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.