第一节:如何安装RabbitMQ
参考这两篇博文:
https://blog.csdn.net/weixin_39735923/article/details/79288578
https://www.cnblogs.com/ericli-ericli/p/5902270.html
安装成功之后,访问 http://localhost:15672
第二节:为什么要使用RabbitMQ?它解决了什么问题?
1,解决问题
(1)同步变异步
简单点说,就是将原来的一个线程,拆分成几个子线程,异步执行。举个栗子吧,比如订单服务,当你开始一个订单服务,内部的业务逻辑可能包括:扣减库存、生成相应单据、发红包、发短信通知等等。在业务发展初期,这些逻辑放在一起同步执行,可能没有太大关系。但是随着业务的发展订单量噌噌~地往上涨,大量的订单等着结果的返回,必然造成时间的浪费和性能的低下。这个时候,我们可以将不需要立即生效的操作拆分出来,异步执行。这个时候就可以用MQ来达到这个目的。在下单的主流程完成之后,发送一条消息给MQ让主流程快速结束,而由另外的单独线程拉取MQ中的消息去执行相应的逻辑。
(2)解耦
当要添加其他的业务逻辑的时候,我们不需要去修改主体程序部分,而是独立增加服务,让MQ推送消息即可(或服务拉取消息)。
(3)流量削峰
如下图,不管用户请求有多大,都一一进入消息队列,按顺序执行秒杀服务。
第三节:编写RabbitMQ入门例子
(1)首先在Spring Initializr 中生成一个springboot项目,依赖要选择web和RabbitMQ,然后导入eclipse。
(2)新建一个发送者配置类,里面定义一个队列:
package com.twf.rabbit;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SenderConfig {
@Bean
public Queue queue() {
return new Queue("hello-twf-queue");
}
}
(3)定义一个发送者
package com.twf.rabbit;
import java.util.Date;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Sender {
@Autowired
private AmqpTemplate amqpTemplate;
public void send() {
String msg="hello:" + new Date();
this.amqpTemplate.convertAndSend("hello-twf-queue", msg);
}
}
(4)定义一个接收者
package com.twf.rabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class Receiver {
@RabbitListener(queues="hello-twf-queue")
public void process(String msg) {
System.out.println("receiver:" + msg);
}
}
(5)修改配置文件
spring.application.name=springboot-amqp
server.port=8080
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=twf
spring.rabbitmq.password=123456
(6)写一个测试类
package com.twf.rabbit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=RabbitMqHelloApplication.class)
public class RabbitMqHelloApplicationTests {
@Autowired
private Sender sender;
@Test
public void send() {
sender.send();
}
}
(7)启动测试类,访问http://localhost:15672,可以在RabbitMQ的UI界面中看到如下内容:
注意:这里了解一下RabbitMQ的主要端口
4369 – erlang发现口
5672 --client端通信口
15672 – 管理界面ui端口
25672 – server间内部通信口
第四节:RabbitMQ通信为什么需要信道?为什么不是TCP直接通信?
原因:
1,因为TCP的创建和销毁的开销都大,创建要3次握手,销毁要4次握手。
2,如果不用信道,那么应用程序就会tcp连接到rabbit,高峰时,每秒成千上万条连接会造成资源的巨大浪费,而且操作系统每秒处理的tcp连接数也是有限制的,必定造成性能瓶颈。
3,信道的原理是一条线程一条信道,多条线程多条信道同用一条tcp连接。一条TCP连接可以容纳无限的通道,即每秒成千上万的请求也不会成为性能瓶颈。
(也就是复用TCP连接了,多个线程多个信道可以用同一个tcp连接,就不用频繁地创建tcp连接了,这样就提高了tcp连接的使用率,降低了创建tcp连接的开销)
第五节:采用springboot实现direct交换器消息流
(1)利用Spring Initializr 生成两个springboot项目,依赖选择web和RabbitMQ,然后导入eclipse,先看下项目结构:
(2)定义消息提供者provider的配置文件,配置交换器。
(3)定义一个发送者。
(4)设置消费者的配置文件,配置交换器,队列和路由键。
(5)定义一个消费者
(6)打开RabbitMQ的ui界面如下。
个人理解:就是生产者生成消息,发送到队列中,然后会发送给订阅了这个队列的消费者。生产者生成消息的时候,会给这条消息指定交换器和路由键,消息就会被发送到这个交换器。接下来判断路由键,消息有一个路由键,交换器和队列之间也绑定了一个路由键,如果这两个路由键相同,那么这条消息就会被发送到这个队列上来,而如果有哪个消费者订阅了这个队列,那么队列就会将消息发送给这个消费者。
生产者和消费者并不知道彼此的存在,它们只和消息队列打交道。消息队列是一种应用间的通信方式,消息发送后可以立即返回,由消息系统确保消息的可靠传递。消息的生产者只管将信息发布到MQ而不用管谁来取,消费者只管从MQ种取消息而不用管是谁发布的。
第六节:采用springboot实现topic交换器消息流
规则:模糊匹配规则。也就是说,交换器和队列之间的路由键不是精确的了,不再只匹配一种消息,而是可以匹配满足这个规则的所有消息了。只要满足这个规则,消息就会被发到这个队列上,进而发送给消费者。
代码见末尾源码链接。
第七节:采用springboot实现fanout交换器消息流
即广播交换器:把消息发出去,让所有人都知道。fanout交换机已经没有路由键了,我们只是简单地将队列绑定到交换机上,一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。
代码见末尾源码链接。
第八节:消息丢了怎么办?那就持久化它。
将消费者的监听注解中的autoDelete的值改为false就行了。
代码见末尾源码链接。
第九节:如何让消息安全到达目的地?
代码见末尾源码链接。
源码链接:https://github.com/tanwenfang/GitRepository