RabbitMQ学习总结(一)

MQ是什么? MQ的好处是什么? MQ有什么缺点?
MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
优点:应用解耦 异步提速 削峰填谷
缺点:可用降低(集群) 复杂度提高 数据的一致

AMQP 和 JMS
MQ是消息通信的模型;实现MQ的大致有两种主流方式:AMQP、JMS。

AMQP:
AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。
JMS:
JMS即Java消息服务(JavaMessage Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信

AMQP 与 JMS 区别
JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式
JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。
JMS规定了两种消息模式;而AMQP的消息模式更加丰富

RabbitMQ和MQ的关系是什么?
RabbitMQ是MQ的一种实现
RabbitMQ概念(重要)
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。

RabbitMQ的安装

RabbitMQ的使用:五种工作模式
简单模式、工作队列模式、发布订阅模式、路由模式、通配符模式

MQ的学习目的
MQ: message queue 消息队列
消息队列如何实现分布式的通信
生产者、消费者、中间件
MQ的优势
应用解耦
异步提速
削峰填谷
MQ的缺点
可用降低(集群)
复杂度提高
数据的一致
RabbitMQ和MQ的关系
ActiveMQ:基于JMS
ZeroMQ:基于C语言开发
RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
RocketMQ:基于JMS,阿里巴巴产品
Kafka:类似MQ的产品;分布式消息系统,高吞吐量
RabbitMQ概念
在这里插入图片描述
虚拟机连接网络三种方式:
在这里插入图片描述
(1)创建一个用户
(2)创建一个虚拟主机(VirtualHost)
(3)VirtualHost绑定用户
(4)host: 127.0.0.1
port: 5672
username:guest
password: guest
virtualHost: /

1.生产者
//1.创建连接工厂
//2.设置连接参数(host/port/username/password/virtualhost)
//3.创建连接
//4.通过连接创建通道(channel)
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.200.131");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
---------------------------------------
//5.创建一个交换机(Exchange)
//6.创建一个队列(Queue)
//7.绑定交换机和队列之间的关系(Binding)
---------------------------------------
//8.发送消息----------------------------------------
//9.关闭资源
channel.close();
connection.close();
2.消费者
//1.创建连接工厂
//2.设置连接参数(host/port/username/password/virtualhost)
//3.创建连接


//4.通过连接创建通道(channel)
--------------------------------------------
//5.创建一个交换机(Exchange)
//6.创建一个队列(Queue)
//7.绑定交换机和队列之间的关系(Binding)
Exchange,Queue,Binding:声明的时候,如果已经存在,则不再创建,如果不存在,才进行创建
要: 启动消费者的时候,启动顺序没有要求
不要:将消费者必须要在生产者运行之后才能启动
--------------------------------------------
//8.监听队列,从队列中获取消息
Consumer consumer = new DefaultConsumer(channel){
handleDelivery()....
};
channel.basicConsume("queueName",true,consumer);
------------------------------------------
//9.关闭资源
不要去关闭资源

简单模式
在这里插入图片描述

/**
        * 参数一:队列名称
        * 参数二:是否持久化,队列在RabbitMQ重启后是否还存在
        * 参数三:消费者是否独占该队列
        * 参数四:是否自动删除,当没有consumer自动删除
        * 参数五:额外参数
        */
      channel.queueDeclare("hello_world",true,false,false,null);
/**
        * 参数一:交换机名称,若使用默认,则给值为""
        * 参数二:routingKey 路由key
        * 参数三:配置信息
        * 参数四:消息体
        */
      channel.basicPublish("","hello_world",null,"hello rabbitmq~~~~".getBytes());

生产者发送消息
生产者创建连接(Connection),开启一个信道(Channel),连接到RabbitMQ Broker;
声明队列并设置属性;如是否排它,是否持久化,是否自动删除;
将路由键(空字符串)与队列绑定起来;
发送消息至RabbitMQ Broker;
关闭信道;
关闭连接;
消费者接收消息
消费者创建连接(Connection),开启一个信道(Channel),连接到RabbitMQ Broker
向Broker 请求消费相应队列中的消息,设置相应的回调函数;
等待Broker回应闭关投递响应队列中的消息,消费者接收消息;
确认(ack,自动确认)接收到的消息;
RabbitMQ从队列中删除相应已经被确认的消息;
关闭信道;
关闭连接;

应用场景

工作队列模式
在这里插入图片描述
多个消费者会以轮询的方式从消息队列中获取消息进行消费。

订阅模式类型:
P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
C:消费者,消息的接受者,会一直等待消息到来。
Queue:消息队列,接收消息、缓存消息。
Exchange:交换机,图中的X。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有常见以下3种类型:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key 的队列
Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!
在这里插入图片描述

发布订阅模式

发布订阅模式:
1、每个消费者监听自己的队列。
2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息

1)声明一个交换机
channel.exchangeDeclare("exchangeName",BuiltinExchangeType.FANOUT);2)声明了两个队列
channel.queueDeclare("queueName1",true,false,false,null);
channel.queueDeclare("queueName2",true,false,false,null);
	(3)绑定交换机和队列之间的关系
channel.queueBind("queueName1","exchangeName","");
channel.queueBind("queueName2","exchangeName","");
	(4)发送消息
channel.basicPublish("exchangeName","",null,body);
	(5)接收消息
channel.basicConsume("queueName",true,consumer);

路由模式

路由模式特点:
队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
消息的发送方在 向 Exchange发送消息时,也必须指定消息的 RoutingKey。
Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

交换机的类型为:Direct,还有队列绑定交换机的时候需要指定routing key。
在这里插入图片描述

1)声明一个交换机
channel.exchangeDeclare("exchangeName",BuiltinExchangeType.DIRECT);2)声明了两个队列
channel.queueDeclare("queueName1",true,false,false,null);
channel.queueDeclare("queueName2",true,false,false,null);
(3)绑定交换机和队列之间的关系
channel.queueBind("queueName1","exchangeName","a");
channel.queueBind("queueName2","exchangeName","b");
channel.queueBind("queueName1","exchangeName","c");
channel.queueBind("queueName2","exchangeName","c");4)发送消息
channel.basicPublish("exchangeName","routingKey",null,body);
(5)接收消息
channel.basicConsume("queueName",true,consumer);

通配符模式

可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!

Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
通配符规则:
#:匹配一个或多个词
:匹配不多不少恰好1个词
举例:
item.#:能够匹配item.insert.abc 或者 item.insert
item.
:只能匹配item.insert
在这里插入图片描述

1)声明一个交换机
channel.exchangeDeclare("exchangeName",BuiltinExchangeType.TOPIC);2)声明了两个队列
channel.queueDeclare("queueName1",true,false,false,null);
channel.queueDeclare("queueName2",true,false,false,null);
(3)绑定交换机和队列之间的关系
channel.queueBind("queueName1","exchangeName","a.#");
channel.queueBind("queueName2","exchangeName","b.#");
channel.queueBind("queueName1","exchangeName","*.a.*");
channel.queueBind("queueName2","exchangeName","b.#.c");4)发送消息
channel.basicPublish("exchangeName","routingKey",null,body);
(5)接收消息
channel.basicConsume("queueName",true,consumer);

》ConnectionFactory
》Connection
》channel
》channel.exchangeDeclare
》channel.queueDeclare
》channel.queueBind()
》channel.basicPublish()
》channel.basicConsume()·

RabbitMQ工作模式:

1、简单模式 HelloWorld
一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)
2、工作队列模式 Work Queue
一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)
3、发布订阅模式 Publish/subscribe
需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列
4、路由模式 Routing
需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列
5、通配符模式 Topic
需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

**

Spring整合RabbitMQ

**

pom.xml
<dependencies>
    <!--junit单元测试驱动-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--导入spring的context坐标,context依赖core、beans、expression-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.5.RELEASE</version>
    </dependency>
     <!--导入spring集成junit的坐标-->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>
         <version>5.0.5.RELEASE</version>
     </dependency>
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>2.1.8.RELEASE</version>
    </dependency>
</dependencies>

生产者

applicationContext.xml
ConnectionFactory
<!--加载配置文件-->
<context:property-placeholder location="classpath:rabbitmq.properties"/>

<!-- 定义rabbitmq connectionFactory -->
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                           port="${rabbitmq.port}"
                           username="${rabbitmq.username}"
                           password="${rabbitmq.password}"
                           virtual-host="${rabbitmq.virtual-host}"/>
                           
<!--定义管理交换机、队列-->
<rabbit:admin connection-factory="connectionFactory"/>

Queue
<!--定义持久化队列,不存在则自动创建;不绑定到交换机则绑定到默认交换机
默认交换机类型为direct,名字为:"",路由键为队列的名称
-->
<rabbit:queue id="spring_queue" name="spring_queue" auto-declare="true"/>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~广播;所有队列都能收到消息~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!--定义广播交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true"/>

<!--定义广播交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_fanout_queue_2" name="spring_fanout_queue_2" auto-declare="true"/>

Exchange
<!--定义广播类型交换机;并绑定上述两个队列-->
<rabbit:fanout-exchange id="spring_fanout_exchange" name="spring_fanout_exchange" auto-declare="true">
    <rabbit:bindings>
        <rabbit:binding queue="spring_fanout_queue_1"/>
        <rabbit:binding queue="spring_fanout_queue_2"/>
    </rabbit:bindings>
</rabbit:fanout-exchange>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~通配符;*匹配一个单词,#匹配多个单词 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!--定义通配符交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_topic_queue_star" name="spring_topic_queue_star" auto-declare="true"/>
<!--定义通配符交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_topic_queue_well" name="spring_topic_queue_well" auto-declare="true"/>
<!--定义通配符交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_topic_queue_well2" name="spring_topic_queue_well2" auto-declare="true"/>


Exchange-Queue(Bingding)

<!--定义通配符类型交换机;并绑定上述队列-->
<rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange" auto-declare="true">
    <rabbit:bindings>
        <rabbit:binding pattern="heima.*" queue="spring_topic_queue_star"/>
        <rabbit:binding pattern="heima.#" queue="spring_topic_queue_well"/>
        <rabbit:binding pattern="itcast.#" queue="spring_topic_queue_well2"/>
    </rabbit:bindings>
</rabbit:topic-exchange>

rabbitTemplate
<!--定义rabbitTemplate对象操作可以在代码中方便发送消息-->
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>

消费者
applicationContext.xml

ConnectionFactory
<!--创建监听类-->
<bean id="springQueueListener" class="live.longmarch.rabbitmq.listener.SpringQueueListener"/>
<bean id="fanoutListener1" class="live.longmarch.rabbitmq.listener.FanoutListener1"/>
<bean id="fanoutListener2" class="live.longmarch.rabbitmq.listener.FanoutListener2"/>
<bean id="topicListenerStar" class="live.longmarch.rabbitmq.listener.TopicListenerStar"/>
<bean id="topicListenerWell" class="live.longmarch.rabbitmq.listener.TopicListenerWell"/>
<bean id="topicListenerWell2" class="live.longmarch.rabbitmq.listener.TopicListenerWell2"/>


<!--配置监听类所监听的队列-->
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
    <rabbit:listener ref="springQueueListener" queue-names="spring_queue"/>
    <rabbit:listener ref="fanoutListener1" queue-names="spring_fanout_queue_1"/>
    <rabbit:listener ref="fanoutListener2" queue-names="spring_fanout_queue_2"/>
    <rabbit:listener ref="topicListenerStar" queue-names="spring_topic_queue_star"/>
    <rabbit:listener ref="topicListenerWell" queue-names="spring_topic_queue_well"/>
    <rabbit:listener ref="topicListenerWell2" queue-names="spring_topic_queue_well2"/>
</rabbit:listener-container>

listener监听类 implements MessageListener
onMessage…
业务操作

public class SpringQueueListener implements MessageListener {
    public void onMessage(Message message) {
        try {
            String msg = new String(message.getBody(), "utf-8");

            System.out.printf("接收路由名称为:%s,路由键为:%s,队列名为:%s的消息:%s \n",
                    message.getMessageProperties().getReceivedExchange(),
                    message.getMessageProperties().getReceivedRoutingKey(),
                    message.getMessageProperties().getConsumerQueue(),
                    msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

读取applicationContext.xml配置文件,启动监听

总结:

MQ
Message Queue : 存储消息的一个容器

生产者、broker、消费者

MQ优点: 解耦、提速、削峰 [秒杀…]
MQ缺点: 维护高,可用性降低、复杂度提供、数据处理的一致性
如何选择MQ: 允许异步、投入和产出

技术---->做什么----->适合项目中的那个模块用----->项目
MQ的具体实现:
RabbitMQ(erlang AMQP协议)
ActiveMQ(java JMS接口)
RocketMQ(阿里)
Kafka
ZeroMQ

RabbitMQ的概念
Producer–>Connection(channel)–>virtualHost[Exchange–>binding(routingKey)–>queue]<–Connection(channel)<–consumer

RabbitMQ的使用
简单模式、工作队里模式、发布订阅模式、路由模式、通配符模式
RabbitMQ代码
ConnectionFactory(5要素)
Connection
Channel
Channel.queueDeclare(queueName,true,false,false,null)
Channel.exchangeDeclare(exchangeName,type) type: fanout direct topic
Channel.queueBind(queueName,exchange,routingKey);
Channel.basicPublish(exchange,routingKey,null,body.getBytes());
Consumer consumer = new DefaultConsumer(channel){
handleDelivery…
业务操作
}
Channel.basicConsume(queueName,true,consumer);

RabbitMQ整合Spring开发
pom.xml
生产者
applicationContext.xml
ConnectionFactory
Queue
Exchange
Exchange-Queue(Bingding)
rabbitTemplate
消费者
applicationContext.xml
ConnectionFactory
listener监听类 implements MessageListener
onMessage…
业务操作

发布了71 篇原创文章 · 获赞 1 · 访问量 1141

猜你喜欢

转载自blog.csdn.net/weixin_44993313/article/details/103943934