1.RabbitMQ
1.1.安装:
地址:https://www.cnblogs.com/cqyp/p/13463302.html
1.2.五种消息模型
1.2.1.基本模式
P(producer/ publisher):生产者,一个发送消息的用户应用程序。
C(consumer):消费者,监听队列,如果有关于自己的消息,就立即消费。
队列(红色区域):消息的暂存区
生产者将消息发送到队列,消费者从队列中获取消息,队列是存储消息的缓冲区。
1.2.2.work消息模式
此模式,一个消息只能被一个消费者获取。多个消费者监听一个队列,当消费者c1获取了消息,但是还没执行完成时,消息队列中有了新的消息,防止堆积,消费者c2就会消费此消息。
1.3.订阅模式
1.3.1.订阅模式分类
1、1个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机(X)
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机到达队列,实现一个消息被多个消费者获取的目的
Exchange类型有以下几种:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key 的队列
Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
1.3.2.订阅模型-Fanout
流程图和上面的一致
消息发送流程:
- 1) 可以有多个消费者
- 2) 每个消费者有自己的queue(队列)
- 3) 每个队列都要绑定到Exchange(交换机)
- 4) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
- 5) 交换机把消息发送给绑定过的所有队列
- 6) 队列的消费者都能拿到消息。实现一条消息被多个消费者消费
1.3.3.订阅模型-Direct
P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列
C1:消费者,其所在队列指定了需要routing key 为 error 的消息
C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息
1.3.4.订阅模型-Topic
Topic
类型的Exchange
与Direct
相比,都是可以根据RoutingKey
把消息路由到不同的队列。只不过Topic
类型Exchange
可以让队列在绑定Routing key
的时候使用通配符!
`#`:匹配一个或多个词 : `audit.#`:能够匹配`audit.irs.corporate` 或者 `audit.irs`
`*`:匹配不多不少恰好1个词 : `audit.*`:只能匹配`audit.irs`
2.RabbitMQ整合springBoot
2.1.环境搭建
添加依赖
org.springframework.boot
spring-boot-starter-amqp
org.springframework.boot
spring-boot-starter-test
2.2.配置
2.2.1.配置application.yml
server:
port: 44000
spring:
application:
name: test-rabbitmq-producer
rabbitmq:
host: 192.168.157.129
port: 5672
username: guest
password: guest
virtualHost: /
2.2.2.定义RabbitConfifig类,配置Exchange、Queue、及绑定交换机。
@Configuration
public class RabbitmqConfig {
//队列
public static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
public static final String QUEUE_INFORM_SMS = "queue_inform_sms";
//交换机
public static final String EXCHANGE_TOPICS_INFORM="exchange_topics_inform";
//routingKey
public static final String ROUTINGKEY_EMAIL = "inform.#.email.#";
public static final String ROUTINGKEY_SMS = "inform.#.sms.#";
//声明交换机
@Bean(EXCHANGE_TOPICS_INFORM)
public Exchange EXCHANGE_TOPICS_INFORM() {
//durable(true) 持久化,mq重启之后交换机还在
return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_INFORM).durable(true).build();
}
//声明队列
@Bean(QUEUE_INFORM_EMAIL)
public Queue QUEUE_INFORM_EMAIL() {
return new Queue(QUEUE_INFORM_EMAIL);
}
@Bean(QUEUE_INFORM_SMS)
public Queue QUEUE_INFORM_SMS() {
return new Queue(QUEUE_INFORM_SMS);
}
//队列绑定交换机
@Bean
public Binding BINDING_QUEUE_INFORM_EMAIL (@Qualifier(QUEUE_INFORM_EMAIL) Queue queue,
@Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_EMAIL).noargs();
}
@Bean
public Binding BINDING_ROUTINGKEY_SMS(@Qualifier(QUEUE_INFORM_SMS) Queue queue,
@Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_SMS).noargs();
}
}
2.3.生产者
2.3.1.发送消息测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class Product05_springboot {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void testSendEmail() {
/**
* 发送消息
* 参数:
* 1. 交换机
* 2. routingKey
* 3. 消息内容
*/
String message = "send email message to user";
rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_TOPICS_INFORM,"inform.email",message);
}
}
2.4.消费者
导入依赖,配置yml文件,编写配置类和上面一样;
2.4.1.接收消息测试
@Component
public class ReceiveHandler {
@RabbitListener(queues = {RabbitmqConfig.QUEUE_INFORM_EMAIL})
public void send_email(String msg, Message message, Channel channel) {
System.out.println("接受的消息:" + msg);
}
}