目录
消息中间件:MQ
MessageQueue 即消息队列,队列指的是一种先进先出的数据结构。消息由生产者生成,发送到mq进行排队,再由消费者按照原有的顺序进行取出消费。类似qq,微信等IM通讯就是典型的消息队列。java现在常用的消息中间件有:rabbitmq,rocketmq,kafka。本阶段先了解rabbit,后续我也会陆陆续续的出另外两个mq的学习。
mq作用
1.异步
生产者把消息放入mq后,可以继续去生产其他的消息,不用等着消费者消费。
2.解耦
各个服务之间解耦,减少服务依赖,提高稳定性。而且一个生产者生产的消息可以由多个消费者消费。
3.削峰填谷
非核心业务如:积分服务等在高峰期时放入消息队列,服务器空闲时再消费。提高吞吐
mq优缺点
使用mq对我们的系统有以上各种好处,但是加入任何的中间件对系统也是有他的缺点。
缺点:
降低系统可用性,系统加入了mq,如果mq宕机那么系统肯定就会不可用。
系统复杂性提高,异步调用链路增加,还要考虑mq丢失,幂等,顺序等等问题
消息一致性问题,a系统发送消息,到b,c系统处理,b系统成功,c系统失败
有优点,有缺点,所以说我们在选择中间件的时候,需要根据业务实际情况进行选择。下面给出一个常用mq的对比
关于mq的理论知识先简单介绍下,至于常见的比如消息幂等,顺序,及消息高可用每个中间件有不同的处理方式,就不挨个说了,后面写到的话就稍微说明下。接下来我们直接进入使用,安装步骤请自行百度了
MQ简单使用
本文采用spring boot+rabbit mq来学习,就不演示单纯用管理界面使用rabbit了
1.新建一个spring boot项目,并加入rabbit mq依赖
<!-- rabbit -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.6.6</version>
</dependency>
2.配置mq
# rabbitMq 相关配置
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
virtual-host: /
username: guest
password: ZLbleak7474
3.订阅发布模式配置
package com.rabbit.config;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName FanoutExchangeConfig
* @Description 订阅发布模式是一个生产者对应多个消费者(fanout-exchange)模式,
* 可以理解为广播模式
* Fanout模式需要声明exchange,并绑定queue,由exchange负责转发到queue上。
* @Author andy
* @Date 2022/7/16 16:35
* @Version 1.0
*/
@Configuration
public class FanoutExchangeConfig {
/**
* 交换机名称
*/
public static String FANOUT_EXCHANGE = "fanoutExchange";
/**
* 消息队列名称
*/
public static final String QUEUE_ONE = "fanout.queue.one";
public static final String QUEUE_TWO = "fanout.queue.two";
/**声明了两个消息队列*/
@Bean
public Queue fanoutQueueOne() {
return new Queue(QUEUE_ONE);
}
@Bean
Queue fanoutQueueTwo() {
return new Queue(QUEUE_TWO);
}
/**
* 声明交换器
*/
@Bean
FanoutExchange getFanoutExchange(){
return new FanoutExchange(FANOUT_EXCHANGE);
}
/**
* 绑定队列到交换器,由交换器进行发送
*/
@Bean
Binding binQueueOne(){
return BindingBuilder.bind(fanoutQueueOne()).to(getFanoutExchange());
}
@Bean
public Binding binQueueTwo() {
return BindingBuilder.bind(fanoutQueueTwo()).to(getFanoutExchange());
}
}
4.新建一个controller用来发送消息
package com.rabbit.controller;
import com.rabbit.config.FanoutExchangeConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping(value = "send")
public class ProducerController {
@Resource
private RabbitTemplate rabbitTemplate;
@GetMapping("fanout-exchange")
public void sendExchange(){
String msg = "hello rabbit";
rabbitTemplate.convertAndSend(FanoutExchangeConfig.FANOUT_EXCHANGE, null, msg);
}
}
现在就可以启动访问发送消息了,发送了以后也可以登录管理界面查看
5.新建消费者消费消息
package com.rabbit.config;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @ClassName ConsumerDemo
* @Description 消费者模拟
* @Author andy
* @Date 2022/7/16 17:09
* @Version 1.0
*/
@Component
public class ConsumerDemo {
Logger log = LoggerFactory.getLogger(ConsumerDemo.class);
/**
* 监听消息队列,记得注解里面用常量,否则报错
*/
@RabbitListener(queues = FanoutExchangeConfig.QUEUE_ONE)
public void listenerOne(String msg, Channel channel, Message message){
log.info("接收到队列one的消息:"+msg);
}
@RabbitListener(queues = FanoutExchangeConfig.QUEUE_TWO)
public void listenerTwo(String msg, Channel channel, Message message){
log.info("接收到队列two的消息:"+msg);
}
}
注意一个点,如果最开始还没有发送消息,也没有去控制台新建交换器队列等内容,不要把消费者一起启动,不然就找不到定义的消息。
本章主要先了解一下rabbit的简单使用,下次会介绍其他交换器,以及消息等等。