Visão geral
Quando eu estava entrevistando no NetEase, o entrevistador me fez uma pergunta e disse
Depois de fazer um pedido, se o usuário não pagar e precisar cancelar o pedido, o que posso fazer?
Minha resposta na época era usar uma tarefa cronometrada para digitalizar a tabela de banco de dados. O entrevistador não ficou muito satisfeito e perguntou:
Existe alguma outra maneira de usar tarefas cronometradas para obter notificações precisas em tempo real?
Minha resposta naquele momento foi:
Você pode usar uma fila. Depois que o pedido é feito, uma mensagem é enviada para a fila e o tempo de validade é especificado. Quando a hora chegar, a interface de retorno de chamada é executada.
Depois que o entrevistador ouviu, ele parou de perguntar. Na verdade, minha ideia estava certa naquela época, mas eu não era muito profissional. O ditado profissional é usar mensagens atrasadas.
De fato, há de fato algum problema em usar tarefas cronometradas. O sistema de negócios original espera que, se o pedido não for pago em 10 minutos, o pedido será cancelado imediatamente e o inventário do produto será divulgado. No entanto, uma vez que o volume de dados seja grande, o tempo para obter dados de pedidos não pagos será estendido. Alguns pedidos serão cancelados após 10 minutos, o que pode ser de 15 minutos, 20 minutos, etc. Dessa forma, o inventário não será liberado no tempo e também afetará o número ímpar. Usando mensagens de atraso, a operação de cancelamento do pedido pode teoricamente ser executada de acordo com o tempo definido.
Atualmente, a maioria dos artigos na Internet sobre o uso do RabbitMQ para implementar mensagens atrasadas é sobre como usar a fila de cartas mortas do RabbitMQ para implementar. A solução de implementação parece muito complicada e é implementada usando a API original do cliente RabbitMQ, que é ainda mais detalhada.
A Spring Boot envolveu a API do cliente RabbitMQ, que é muito mais simples de usar. Aqui está uma introdução detalhada de como usar o rabbitmq_delayed_message_exchange plug-in e a bota da mola para implementar mensagens atrasadas.
Preparação de software
Erlang
A versão usada neste artigo é: Erlang 20.3
RabbitMQ
Este artigo usa a versão da janela do RabbitMQ, o número da versão é: 3.7.4
rabbitmq_delayed_message_exchange plugin
Endereço para download do plug-in: http://www.rabbitmq.com/community-plugins.html
Depois de abrir o URL, Ctrl + F e Pesquise Rabbitmq_delayed_Message_Exchange.
Lembre -se, você deve escolher o número da versão. Como estou usando o RabbitMQ 3.7.4, o rabbitmq_delayed_message_exchange correspondente também deve escolher 3.7.x.
Se você não selecionar a versão correta, encontrará vários problemas estranhos ao usar mensagens atrasadas e não há solução na Internet. Eu lutei a noite toda por causa desse problema. Lembre-se de selecionar a versão plug-in correta.
Depois de baixar o plug -in, coloque -o no diretório do plugins no diretório de instalação do RabbitMQ e inicie o plug -in usando o seguinte comando:
RabbitMQ-PLUGINS Ativar rabbitmq_delayed_message_exchange
Se a startup for bem -sucedida, a seguinte mensagem aparecerá:
Os seguintes plugins foram ativados: Rabbitmq_delayed_Message_Exchange
Depois que o plug-in é lançado com sucesso, lembre-se de reiniciar o RabbitMQ para entrar em vigor.
RabbitMQ integrado
Isso é muito simples, basta adicioná -lo no arquivo pom.xml do projeto Maven
<Depencency> <PuerpId> org.springframework.boot </frugiD> <ArtifactId> Spring-boot-starter-amqp </artifactId> </dependency>
Estou usando o 2.0.1.Release para a inicialização da primavera.
Em seguida, adicione a configuração Redis no arquivo Application.Properties:
spring.rabbitmq.host = 127.0.0.1spring.rabbitmq.port = 5672spring.rabbitmq.username = hóspedespring.rabbitmq.password = convidado
Definir ConnectionFactory e Rabbittemplate
Também é muito simples, o código é o seguinte:
pacote com.mq.rabbitmq; importar org.springframework.amqp.rabbit.connection.cachingConnectionFactory; importar org.springframework.amqp.rabbit.connection.connection; org.springframework.boot.context.properties.configurationProperties; importar org.springframework.context.annotation.bean; importar org.springframework.context.annotation.configuration;@configuration@configurationProperties (prefixixxix = springn. springn.configuration; hospedar; private int porta; Nome de usuário privado de string; senha de sequência privada; @Bean public ConnectionFactory ConnectionFactory () {CachingConnectionFactory CachingConnectionFactory = new CachingConnectionFactory (host, porta); CachingConnectionFactory.setUserName (nome de usuário); CachingConnectionFactory.SetPassword (senha); CachingConnectionFactory.SetVirtualHost ("/"); CachingConnectionFactory.SetPublisherConfirms (true); Retornar CachingConnectionFactory; } @Bean public rabbittemplate rabbittemplate () {rabbittemplate rabbittemplate = new rabbittemplate (conextactory ()); retornar rabbittemplate; } public string gethost () {return host; } public void sethost (string host) {this.host = host; } public int getport () {return porta; } public void Setport (int porta) {this.port = port; } public string getUserName () {return userName; } public void setUserName (string userName) {this.username = nome de usuário; } public string getPassword () {return senha; } public void setPassword (string senha) {this.password = senha; }}Configuração de troca e fila
pacote com.mq.rabbitmq; importar org.springframework.amqp.core. {@Bean public CustomexChange deLexChange () {map <string, object> args = new hashmap <> (); args.put ("x-dellayed-type", "direto"); devolver novo CustomexChange ("test_exchange", "x-delabled-message", verdadeiro, false, args); } @Bean public file fileeue () {fila fila = new fila ("test_queue_1", true); retornar a fila; } @Bean public binding binding () {return bindingbuilder.bind (fileue ()). Para (deounExchange ()). Com ("test_queue_1"). Noargs (); }}Deve-se notar aqui que o CustomexChange é usado, não o DirectExChange, e o tipo de troca de customxange deve ser compensado por X.
Implementar o envio de mensagens
package com.mq.rabbitmq;import org.springframework.amqp.AmqpException;import org.springframework.amqp.core.Message;import org.springframework.amqp.core.MessagePostProcessor;import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.beans.factory.annotation.autowired; importar org.springframework.tereotype.service; importar java.text.simpledateFormat; importar java.util.date; @ServicePitublic MessensericeImpl {@Autowired Rabbemate; @ServicePublic MessageS MessageSpl {@Autowired Rabbemate; Rabbitplate; public void sendmsg (string queuename, string msg) {simpledateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); System.out.println ("Mensagem Enviar tempo:"+sdf.format (new Date ())); rabitemplate.convertandSend ("test_exchange", queuename, msg, new messagePostProcessor () {@Override public mensagem postprocessMessage (mensagem da mensagem) lança amqPexception {message.getMessageProperties (). Setheader ("x-delay", 3000); }}Observe que, ao enviar, um cabeçalho deve ser adicionado
x-delay
O tempo de atraso que defino aqui é de 3 segundos.
Consumidores de mensagens
pacote com.mq.rabbitmq; importar org.springframework.amqp.rabbit.annotation.rabbithandler; importar org.springframework.amqp.rabbit.annotation.rabbitListener; org.springframework.teretypey.mport; Java.util.date; @componentPublic class MessageReceiver {@rabbitListener (fileues = "test_queue_1") public void Receber (string msg) {SimpledateFormat sdf = new SimpleFormat ("yyyyy-mm-dd hh: mm: ss"; System.out.println ("Tempo de recepção da mensagem:"+sdf.format (new Date ())); System.out.println ("Mensagem recebeu:"+msg); }}Execute o programa de inicialização da primavera e envie mensagens
Execute o programa de inicialização da primavera diretamente no método principal e a inicialização da primavera analisará automaticamente a classe Messagereceiver.
Em seguida, basta usar o JUNIT para executar a interface que envia a mensagem.
pacote com.mq.rabbitmq; importar org.junit.test; importar org.junit.runner.runwith; importar org.springframework.beans.factory.annotation.autowired; importestestrostestring.springframework.test.contet.springtest; org.springframework.test.context.junit4.springrunner; @runwith (springrunner.class) @springboottestpublic classe rabbitMqApplicationTests {@AUTOWIRED MENSEssssel ServiceImpl MessageService; @Test public void send () {messenservice.sendmsg ("test_queue_1", "olá eu sou atraso msg"); }} Após a corrida, você pode ver as seguintes informações:
Mensagem de envio de tempo: 2018-05-03 12:44:53
Após 3 segundos, o console de inicialização da primavera será lançado:
Hora da recepção da mensagem: 2018-05-03 12:44:56
Mensagem recebida: Olá, sou atraso na msg
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.