1. 什么时候应该用MQ?
2. Rabbit 基础知识
3. docker 安装 RabbitMQ
RabbitMQ入门
项目下载地址 Springboot-RabbitMQ-demo
1. 基本概念
RabbitMQ是对于AMQP(高级消息队列协议)的具体实现,是一个用于在分布式系统中存储转发消息的网络通信协议。
AMQP 协议层角色相关的概念:
- 生产者(producer):产生消息的应用,能够传递消息到消息中间件的应用。
- 消息中间件(brokers):消息传递的中间载体,即我们今天的主角 RabbitMQ。
- 消费者(consumers):接收并处理消息的应用。从消息中间件获取消息并处理。
- 连接(Connection):生产者或消费者和消息中间件之间需要建立起连接。AMQP 应用层协议使用的是能够提供可靠投递的 TCP 连接,AMQP 的连接通常是长连接,AMQP 使用认证机制并且提供 TLS(SSL)保护。当我们的生产者 或 消费者 不再需要连接到消息中间件的的时候,需要优雅的释放掉它们与消息中间件 TCP 连接,而不是直接将 TCP 连接关闭。
信道(channel):通常情况下生产者 或 消费者 需要与 消息中间件之间建立多个连接。无论怎样,同时开启多个 TCP 连接都是不合适的,因为这样做会消耗掉过多的系统资源。AMQP 协议提供了信道(channel)这个概念来处理多连接,可以把通道理解成共享一个 TCP 连接的多个轻量化连接。一个特定通道上的通讯与其他通道上的通讯是完全隔离的,因此每个 AMQP 方法都需要携带一个通道号,这样客户端就可以指定此方法是为哪个信道准备的。
消息中间件相关的概念:
- 虚拟主机(vHosts):虚拟主机概念,一个 Virtual Host 里面可以有若干个 Exchange 和 Queue,我们可以控制用户在 Virtual Host 的权限。
用户(User):最直接了当的认证方式,谁可以使用当前的消息中间件。 - 交换机(Exchange):交换机接收生产者发出的消息并且路由到由交换机类型和被称作绑定(bindings)的规则所决定的到队列中,交换机不存储消息。
- 消息(message):生产者产生的和消费者处理的消息。
- 路由键(routing key):路由关键字,交换机 exchange 的路由规则利用这个关键字进行消息投递到消息队列。(路由键长度不能超过 255 个字节)
- 绑定(Binding):Binding 可以理解为交换机 Exchange 路由消息到消息队列的路由规则关系(即消息队列和交换机的绑定)。当交换机 Exchange 收到生产者传递的消息 Message 时会解析其 Routing Key,Exchange 根据 Routing Key 与交换机类型 Exchange Type 将 Message 路由到消息队列中去。
SpringBoot整合RabbitMQ
1. pom添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2. 增加yml配置
spring:
rabbitmq:
host: localhost
username: admin
password: admin
virtual-host: my_vhost
port: 5672
application:
name: rabbit_boot_send
注意: virtual_host是安装的时候指定的,默认为 / ;
3. 实现一个简单的生产者 例子
新建一个RabbitConfig的类,生成队列,交换机,并绑定。
@Configuration
public class RabbitConfig {
/**
* 测试队列1
*
* @return
*/
@Bean
public Queue boot_test_queue_1() {
return new Queue("boot_test_queue_1");
}
/**
* 主体模式的交换机
*
* @return
*/
@Bean
public TopicExchange boot_exchange_topic_1() {
return new TopicExchange("boot_exchange_topic_1");
}
/**
* 队列,交换机绑定
* @return
*/
@Bean
public Binding topic_1_queue() {
return BindingBuilder.bind(boot_test_queue_1())
.to(boot_exchange_topic_1())
.with("insert");
}
}
新建一个生产者类
@Component
public class BootSend {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String message) {
// 添加消息转换为 json序列化方式
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = dateFormat.format(new Date());
// 封装消息
Map<String, Object> params = new HashMap<>();
params.put("name", "大米饭");
params.put("age", 23);
params.put("date", format);
params.put("dates", new Date());
params.put("message", message);
// 序列化消息并发送到指定交换机
rabbitTemplate.convertAndSend("boot_exchange_topic_1", "insert", params);
System.out.println(message + format);
}
}
编写测试类,发送消息,去web页面查看消息。
@SpringBootTest
class BootrabbitApplicationTests {
@Autowired
BootSend bootSend;
@Test
void send() {
bootSend.send("haahshan");
}
}
启动测试类,web页面查看队列消息。
可以看到我们的消息成功发送到队列中。
4. 实现一个简单的消费者,接受队列消息
/**
* 队列1消费者
*/
@Component
public class BootConsumer {
@Autowired
AmqpAdmin amqpAdmin;
/**
* 接受指定队列的消息
*
* @param message
*/
@RabbitListener(queues = "boot_test_queue_1")
public void consumer(Message message) {
// 消息内容
String body = new String(message.getBody());
// 反序列化为对象 ,此处使用的fastjson 其他也可以
JSONObject jsonObject = JSON.parseObject(body);
System.out.println(jsonObject);
}
/**
* 新建队列,交换机,绑定
* AmqpAdmin 的用法
*/
public void createQueueExchangeBinding() {
//创建交换器
amqpAdmin.declareExchange(new DirectExchange("amqpAdmin.exchange"));
//创建队列
amqpAdmin.declareQueue(new Queue("amqpAdmin.queue", true));
//两种绑定方式
//绑定
//amqpAdmin.declareBinding(new Binding("amqpAdmin.queue", Binding.DestinationType.QUEUE,
// "amqpAdmin.exchange", "amqp.news", null));
//绑定
amqpAdmin.declareBinding(BindingBuilder.bind(new Queue("amqpAdmin.queue")).to(new TopicExchange("amqpAdmin.exchange")).with("amqp.news"));
}
}
在springboot启动类加上@EnableRabbit 注解
运行springboot,查看控制台 结果
消息被消费了。
本例子提供一个简单的入门应用。