rabbitMQ学习笔记
1.特点:
1.1 开源 稳定 性能好
1.2 与spring AMQP完美结合 api丰富
1.3 保证数据不丢失的情况下做到高可用 高可靠
2.应用场景:
2.1 异步:将消息放到消息中间件 需要时进行处理
2.2 削峰:限制访问流量 返回对应的响应信息 避免服务因超负载而崩溃
2.3 解耦:通过发布 订阅模式 解决服务间的耦合
3.AMQP协议:
3.1 概念:是一个提供消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计
3.2 相关概念:
a.Server:接收客户端的连接,实现AMQP实体服务
b.Connection:连接,应用程序与Server的网络连接,TCP连接
c.Channel:信道,消息读写等操作在信道中进行。客户端可以建立多个信道,每个信道代表一个会话任务
d.Message:消息,应用程序和服务器之间传送的数据,消息可以非常简单,也可以很复杂。有Properties和Body组成。Properties为外包装,可以对消息进行修饰,比如消息的优先级、延迟等高级特性;Body就是消息体内容
e.Virtual Host:虚拟主机,用于逻辑隔离。一个虚拟主机里面可以有若干个Exchange和Queue,同一个虚拟主机里面不能有相同名称的Exchange或Queue
f.Exchange:交换器,接收消息,按照路由规则将消息路由到一个或者多个队列。如果路由不到,或者返回给生产者,或者直接丢弃。RabbitMQ常用的交换器常用类型有direct、topic、fanout、headers四种,后面详细介绍
g.Binding:绑定,交换器和消息队列之间的虚拟连接,绑定中可以包含一个或者多个RoutingKey
h.RoutingKey:路由键,生产者将消息发送给交换器的时候,会发送一个RoutingKey,用来指定路由规则,这样交换器就知道把消息发送到哪个队列。路由键通常为一个“.”分割的字符串,例如“com.rabbitmq”
i.Queue:消息队列,用来保存消息,供消费者消费
4.常用交换器
4.1 交换器类型:RabbitMQ常用的交换器类型有direct、topic、fanout、headers四种
4.2 四种类型交换器的功能特点:
4.2.1 Direct Exchange:将所有发送到该交换器的消息被转发到RoutingKey指定的队列中,也就是说路由到BindingKey和RoutingKey完全匹配的队列中
4.2.2 Topic Exchange:将所有发送到Topic Exchange的消息被转发到所有RoutingKey中指定的Topic的队列上面(Exchange将RoutingKey和某Topic进行模糊匹配,其中“”用来匹配一个词,“#”用于匹配一个或者多个词。例如“com.#”能匹配到“com.rabbitmq.oa”和“com.rabbitmq”;而"login."只能匹配到“com.rabbitmq”)
4.2.3 Fanout Exchange:不处理路由键,会把所有发送到交换器的消息路由到所有绑定的队列中。优点是转发消息最快,性能最好
4.2.4 Headers Exchange:不依赖路由规则来路由消息,而是根据消息内容中的headers属性进行匹配
5.rabbitmq安装(docker安装)
5.1 下载: docker pull rabbitmq:3.8.0-beta.4-management
5.2 安装镜像: docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.8.0-beta.4-management
6.mq的基本使用
springboot整合rabbitmq:
依赖:
<!--rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置信息:
spring:
rabbitmq:
host: 139.186.75.113
port: 5672
username: guest
password: guest
publisher-confirms: true
6.1 direct模式
说明:相当于是一种点对点的发送和接收 ,消息发送到'hello'这个队列上,则监听该队列的就会收到该队列的消息
6.1.1 配置队列:
@Configuration
public class RabbitConfig {
@Bean
public Queue queue(){
return new Queue("hello");
}
}
6.1.2 消息发送:
@Component
public class MessageSender {
@Autowired
private AmqpTemplate rabbitTemplate;
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void send(){
String context = "hello " + format.format(new Date());
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("hello", context);
}
}
6.1.3 消息接收:
@Component
public class MessageReceive {
@RabbitListener(queues = "hello")
public void receiveMessage(String string){
System.out.println("direct接收信息:"+string);
}
}
6.2 topic模式
说明: 比如下面要举得这个例子 交换机设置为topic模式,生产者生成的消息的路由键值为goods.XXXX.其中XXXX,可能为add、delete、update、modify等. 队列一绑定的是goods.add,队列二绑定的是goods.#,这样的话,如果生产者生产一个路由键值为goods.add的消息,辣么2个队列都将会收到。如果生产者生成一个路由键值为goods.delete的消息,辣么只有1个队列将会收到.
6.2.1 配置队列:
@Configuration
public class RabbitConfig {
@Bean(name = "delete")
public Queue topicQueue1(){
return new Queue("goods.delete");
}
@Bean(name = "add")
public Queue topicQueue2(){
return new Queue("goods.add");
}
@Bean
public TopicExchange getTopicExchange(){
return new TopicExchange("exchange");
}
@Bean
public Binding bindExchange1(@Qualifier("delete") Queue queue, TopicExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("goods.add");
}
@Bean
public Binding bindExchange2(@Qualifier("add") Queue queue, TopicExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("goods.#");
}
}
6.2.2 发送消息:
@Component
public class MessageSender {
@Autowired
private AmqpTemplate rabbitTemplate;
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void sendTopic(){
String context = "发送一个topic消息 " + format.format(new Date());
System.out.println("Sender : " + context);
/*param1:交换机名称;param2:路由键;param3:发送消息内容*/
this.rabbitTemplate.convertAndSend("exchange","goods.update", context);
}
}
6.2.3 接收消息:
@Component
public class MessageReceive {
@RabbitListener(queues = "goods.delete")
public void receiveMessage2(String string){
System.out.println("goods.delete队列接收信息:"+string);
}
@RabbitListener(queues = "goods.add")
public void receiveMessage3(String string){
System.out.println("goods.add队列接收信息:"+string);
}
}
6.3 fanout模式
说明:相当于一种广播模式 所有队列注册到交换机上 被监听的队列都能收到消息
6.3.1 配置队列:
@Configuration
public class RabbitConfig {
@Bean(name="Amessage")
public Queue AMessage() {
return new Queue("fanout.A");
}
@Bean(name="Bmessage")
public Queue BMessage() {
return new Queue("fanout.B");
}
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("fanoutExchange");//配置广播路由器
}
@Bean
Binding bindingExchangeA(@Qualifier("Amessage") Queue AMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(@Qualifier("Bmessage") Queue BMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}
}
6.3.2 发送消息:
@Component
public class MessageSender {
@Autowired
private AmqpTemplate rabbitTemplate;
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void sendFanout(){
String context = "发送一个fanout消息 " + format.format(new Date());
System.out.println("Sender : " + context);
/*param1:交换机名称;param2:"";param3:发送消息内容*/
this.rabbitTemplate.convertAndSend("fanoutExchange","", context);
}
}
6.3.3 接收消息:
@Component
public class MessageReceive {
@RabbitListener(queues = "fanout.A")
public void receiveMessage4(String string){
System.out.println("fanout.A队列接收信息:"+string);
}
@RabbitListener(queues = "fanout.B")
public void receiveMessage5(String string){
System.out.println("fanout.B队列接收信息:"+string);
}
}
6.4 headers模式
略