Rabbit MQ:
1.同步通信和异步通信:
大多数时间使用同步,时效性较强。
mq,消息队列,是用来存放消息的队列,就是事件驱动架构中的broker.
2.基于docker安装rabbit MQ:
2.1、docker pull rabbitmq:3-management
2.2、运行mq容器:
docker run -e RABBITMQ_DEFAULT_USER=lihong -e RABBITMQ_DEFAULT_PASS=123456 --name mq --hostname mq1 -p 15672:15672 -p 5672:5672 -d rabbitmq:3-management
注:15672是管理平台端口,5672是消息通信的端口
3.rabbit MQ的常见消息模型:
rabbit mq发送和接收消息:
消息的发送者将消息发送完毕后就关闭了通道,而接收者一直等待消息的接收
4.spring AMQP:
导入amqp的依赖,配置amqp的地址等相关信息。
4.1、基本消息队列(BasicQueue)
4.1.1、使用spring amqp向消息队列发送消息
@SpringBootTest @RunWith(SpringRunner.class) public class SpringAmqpTest { @Autowired private RabbitTemplate rabbitTemplate; @Test public void testSendMessage(){ String queenName="simple.queue"; String message="你好,sping amqp"; rabbitTemplate.convertAndSend(queenName,message); } }
4.1.2、使用spring amqp接收消息
@Component public class ListenerMessageSpringAmqp { @RabbitListener(queues = "simple.queue") public void listenerMessage(String msg){ System.out.println("接收到的消息为:"+msg); } }
随时发送随时接收。
4.2、工作消息队列workQueue:实现多个消费者处理请求
消费者根据处理能力处理对应数量的消息:
案例:
消息发送者publisher
public void testSendMessage() throws InterruptedException { String queenName="simple.queue"; String message="hello__"; for (int i = 0; i < 50; i++) { rabbitTemplate.convertAndSend(queenName,message+i); Thread.sleep(20); } }
消息接收者:
@Component public class ListenerMessageSpringAmqp { @RabbitListener(queues = "simple.queue") public void listenerMessage1(String msg) throws InterruptedException { System.out.println("消费者1接收到的消息为:"+msg+" "+LocalDateTime.now()); Thread.sleep(20); } @RabbitListener(queues = "simple.queue") public void listenerMessage2(String msg) throws InterruptedException { System.err.println("消费者2接收到的消息为:"+msg+" "+LocalDateTime.now()); Thread.sleep(200); } }
logging: pattern: dateformat: MM-dd HH:mm:ss:SSS spring: rabbitmq: host: 192.168.157.129 # rabbitMQ的ip地址 port: 5672 # 端口 username: lihong password: 123456 virtual-host: / listener: simple: prefetch: 1
4.3、FaboutQueue:实现多个消费者都可以接收到消息
4.3.1、在consumer服务中创建配置类,声明Exchange、queue、Binding
@Configuration public class FanoutConfig { //声明路由 @Bean public FanoutExchange fanoutExchange(){ return new FanoutExchange("lihong.fanout"); } //声明队列 @Bean public Queue queue1(){ return new Queue("fanout.queue1"); } //绑定队列 @Bean public Binding binding1(FanoutExchange fanoutExchange,Queue queue1){ return BindingBuilder.bind(queue1).to(fanoutExchange); } //声明队列 @Bean public Queue queue2(){ return new Queue("fanout.queue2"); } //绑定队列 @Bean public Binding binding2(FanoutExchange fanoutExchange,Queue queue2){ return BindingBuilder.bind(queue2).to(fanoutExchange); } }
4.3.2、publisher发送消息
@Test public void testSendMessage3(){ String exchangeName="lihong.fanout"; String message="hello fanout queue"; rabbitTemplate.convertAndSend(exchangeName,"",message); }
4.3.3、消息接收者接收消息
@Component public class FanoutQueueTest { @RabbitListener(queues = "fanout.queue1") public void listenerMessage1(String msg) throws InterruptedException { System.out.println("消费者1接收到的消息为:"+msg); } @RabbitListener(queues = "fanout.queue2") public void listenerMessage2(String msg) throws InterruptedException { System.err.println("消费者2接收到的消息为:"+msg); } }
4.4、DirectQueue:(发送消息到指定队列)
4.4.1、消费者接收消息(通过@RabbitListener声明exchange,queue,key)
@Component public class DirectQueueTest { @RabbitListener(bindings =@QueueBinding (exchange = @Exchange("lihong.direct"), value = @Queue(name = "direct.queue1"), key = {"red","yellow"})) public void listenerMessage1(String msg){ System.out.println("direct.queue1:"+msg); } @RabbitListener(bindings =@QueueBinding (exchange = @Exchange("lihong.direct"), value = @Queue(name = "direct.queue2"), key = {"red","blue"})) public void listenerMessage2(String msg){ System.out.println("direct.queue1:"+msg); } }
4.4.2、publisher发送消息
/** * directQueue发送消息 */ @Test public void testSendMessage4(){ String exchangeName="lihong.direct"; String message="hello "; rabbitTemplate.convertAndSend(exchangeName,"red",message+"blue"); }
4.5、TopicQueue:(支持通配符,当需要向多个key中发送消息时,direct需要定义许多的路由key)
4.5.1、消息监听,接收消息
@Component public class TopicQueueTest { @RabbitListener(bindings = @QueueBinding(value =@Queue("topic.queue1"), exchange = @Exchange(value = "lihong.topic",type = ExchangeTypes.TOPIC),key = {"today.#"})) public void listenerMessage1(String msg){ System.out.println("topic.queue1:"+msg); } @RabbitListener(bindings = @QueueBinding(value =@Queue("topic.queue2"), exchange = @Exchange(value = "lihong.topic",type = ExchangeTypes.TOPIC),key = {"#.xinqing"})) public void listenerMessage2(String msg){ System.out.println("topic.queue2:"+msg); } }
4.5.2、发送消息
/** * topicQueue发送消息 */ @Test public void testSendMessage5(){ String exchangeName="lihong.topic"; String message="今天很糟糕"; rabbitTemplate.convertAndSend(exchangeName,"today.weather",message); }
4.6、使用消息转换器接收和发送任意类型的消息
声明队列有两种方式:1.通过bean声明,2.通过@rablitListener声明
4.6.1、在父工程的pom文件中引入依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
4.6.2、在consumer和publisher的引导类中声明消息转换器。
@Bean public MessageConverter messageConverter(){ return new Jackson2JsonMessageConverter(); }
4.6.3、发送object消息
/** * 发送object类型的数据 */ @Test public void testSendMessage6(){ Map<String ,Object> map=new HashMap<>(); map.put("name","张三"); map.put("age",45); rabbitTemplate.convertAndSend("object.queue",map); }
4.6.4、接收object类型的消息
@Component public class ObjectMessageListener { @RabbitListener(queues = "object.queue") public void getMessage(Map<String, Object> map){ System.out.println("object.queue:"+map); } }