文章目录
1.RabbitMQ概念
1.1.基本概念
MQ全称为Message Queue,即消息队列. 它也是一个队列,遵循FIFO原则.
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue Protocol高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开 发中应用非常广泛。
1.2.RabbitMQ使用场景
- 消峰&限流
- 应用解耦
- 异步处理
- 数据分发
- 消息通讯
- 分布式事务
- 排序保证&先进先出
1.3.常见的消息队列
ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。
2.RabbitMQ的原理
2.1.原理图
2.2.执行流程
组成部分说明如下:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
消息发布接收流程:
-----发送消息-----
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)
----接收消息-----
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。
3.安装RabbitMQ
3.1.安装erlang语音
otp_win64_20.2.exe
3.2.配置erlang的环境变量
3.3.安装RabbitMQ
rabbitmq-server-3.7.4.exe
3.4.安装RabbitMQ的可视化插件
进入mq地 安装目录的sbin目录,cmd执行 rabbitmq-plugins.bat enable rabbitmq_management
3.5.访问测试
http://localhost:15672 账号 : guest/guest
4.Rabbit的使用-helloworld
4.1.helloworld结构图
4.2.helloworld完成
4.2.1.导入依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<!--和springboot2.0.5对应-->
<version>5.4.1</version>
</dependency>
4.2.2.准备连接工具类
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class ConnectionUtil {
/**
* 建立与RabbitMQ的连接
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
//定义连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置服务地址
factory.setHost("127.0.0.1");
//端口
factory.setPort(5672);
//设置账号信息,用户名、密码、vhost
//Virtual代表虚拟消息服务器,每个服务器相对独立
factory.setVirtualHost("/");
factory.setUsername("guest");
factory.setPassword("guest");
// 通过工程获取连接
Connection connection = factory.newConnection();
return connection;
}
}
4.2.3.创建消息发送者
public class Sen {
//队列的名字
private static final String QUEUE_HELLO = "queue_hello";
public static void main(String[] args) {
Connection connection = null;
Channel channel = null;
try{
//1.创建链接对象
connection = ConnectionUtil.getConnection();
//2.创建通道
channel = connection.createChannel();
//3.声明队列:队列名字 ; 持久 ;独占链接 ;不用即删除 ; 参数
channel.queueDeclare(QUEUE_HELLO, true, false, false, null);
//4.发送消息:交换机 ; 队列名(routingkey) ;参数 ;消息了内容
channel.basicPublish("", QUEUE_HELLO ,null ,"我是一个hello消息".getBytes() );
System.out.println("已经发送消息:我是一个hello消息");
} catch (Exception e) {
e.printStackTrace();
}finally {
if(channel != null){
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
4.2.4.创建消息接受者
public class Rev {
//队列的名字
private static final String QUEUE_HELLO = "queue_hello";
public static void main(String[] args) {
try {
//1.创建链接
Connection connection = ConnectionUtil.getConnection();
//2.创建通道
Channel channel = connection.createChannel();
//3.声明队列
channel.queueDeclare(QUEUE_HELLO, true, false, false, null);
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body)throws IOException {
//交换机
String exchange = envelope.getExchange();
System.out.println("exchange:"+exchange);
//路由key
String routingKey = envelope.getRoutingKey();
System.out.println("routingKey:"+routingKey);
//消息id
long deliveryTag = envelope.getDeliveryTag();
System.out.println("deliveryTag:"+deliveryTag);
//消息内容
String msg = new String(body, "utf8");
System.out.println("收到消息:" + msg);
//System.out.println(1 / 0);
channel.basicAck(deliveryTag, false);
}
};
//4.接受消息 :队列 ; 签收方式(true:自动签收)
channel.basicConsume(QUEUE_HELLO, false,consumer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.2.5.手动签收
//4.接受消息 :队列 ; 签收方式(true:自动签收)
channel.basicConsume(QUEUE_HELLO, false,consumer);
在回调方法中
channel.basicAck(deliveryTag, false);
5.RabbitMq-workqueues
5.1.workqueues的思想
work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息。
应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。
5.2.workqueues代码实现
5.2.1.创建消息发送者
同 helloword一样,只是改个队列的名字
5.2.2.创建多个消息接受者
同 helloword一样,只是改个队列的名字
5.2.3.设置能者多劳
设置接受者同时只能处理一个消息
channel.basicQos(1);
6.发布订阅模型
6.1.原理图
解读:
1、1个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机到达队列,实现一个消息被多个消费者获取的目的
X(Exchanges):交换机一方面:接收生产者发送的消息。另一方面:知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。
6.2.Exchange分类
-
Fanout:广播
将消息交给所有绑定到交换机的队列 all
-
Direct:定向
把消息交给符合指定routing key 的队列 一堆或一个
-
Topic:通配符
把消息交给符合routing pattern(路由模式)的队列 一堆或者一个