MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发)。MQ是一种应用程序对应用程序的通信方法。应用程序通过读写入队和出队的消息来通信,无需专用连接来链接它们。
消息传递是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,一般应用于远程过程调用的技术。
排队指的是应用程序通过队列来通信。应用队列避免接收和发送数据的同时进行。
二、特点:
MQ是消费者-生产者模型的代表。一端往消息队列中写入消息,另一端可以读取或者订阅队列中的消息。MQ遵循的是AMQP协议(高级消息队列协议:使得遵从该规范的客户端应用和消息中间件服务器的全功能互操作成为可能)的具体实现和产品。
三、应用:
在使用MQ时,我们不需要实时的返回信息。获取信息和返回信息进行异步处理。例如:在项目中,我们需要从汽车系统中利用CAN总线实时的获取汽车的相关信息,但是没有必要给汽车返回信息。如,获取汽车的轮胎气压,但是我们不需要给汽车一个返回的信息或结果。
C#项目要利用RabbitMQ来获取实时数据的话,需要先安装客户端的库文件:RabbitMQ.Client.dll,下载地址如下:
四、RabbitMQ的结构图:
五、基本概念:
Broker:消息队列服务器实体。
Exchange:消息交换机,指定消息按照什么规则,路由到哪个队列。可以理解成具有路由表的程序。每个消息都有一个成为路由键(routing key)的属性。交换机中有一系列的绑定(binding)即路由规则。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。消息一直在里面,直到有客户端(消费者)连接到这个队列并且将其取走为止。队列是有消费者通过程序建立的。
Binding:绑定,作用:把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
Vhost(virtualhost):虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
注1:比较重要的四个:vhost,exchange,queue,binding。一个虚拟主机持有一组交换机、队列和绑定。
注2:消费者程序要负责创建交换机们(不止一个)?因为每个交换机在自己独立的进程当中执行,增加多个交换机就是增加多个进程,可以充分利用服务器上的CPU的核来提高效率。(一个8核服务上,可以用5核来创建5个交换机,剩余的3个用来处理消息。)
注3:一个绑定(binding)就是一个基于路由键将交换机和队列连接起来的路由规则。
六、消息队列的使用过程大概如下:
(1)客户端连接到消息队列服务器,打开一个channel。
(2)客户端声明一个exchange,并设置相关属性。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routingkey,在exchange和queue之间建立好绑定关系。
(5)客户端投递消息到exchange。
说明:exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
七、Exchange(交换机的类型)的类型:
1)Direct交换机:
(处理路由键)完全根据key进行投递。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。
绑定时设置了routing key为“abc”,那么客户端提交的消息,只有设置了key为“abc”的才会投递到队列。
2)Topic交换机:
(将路由键和某模式进行匹配)此时队列需要绑定到一个模式上,对key进行模式匹配后进行投递。
“#”匹配一个或多个词,“*”匹配正好一个词。“abc.#”匹配“abc.def.ghi”,“abc.*”只匹配“abc.def”。
3)Fanout交换机:(不处理路由键)不需要key值,采用广播模式,消息进来时,投递到与该交换机绑定的所有队列。
八、队列消息的持久化:
1、为什么会有持久化?
花费大量时间来创建队列,,交换机和绑定,如果服务器出现意外或外界故障,那么队列,交换机和绑定就会清空。RabbitMQ重启之后就会清空原来的东西。因此在创建队列和交换机时就会指定一个标志durable来控制。当然,durable表示的含义:含有该标志的队列和交换机在重启之后会重新建立,而不是,在队列中的消息会重启后恢复。
2、消息队列持久化包括3个部分:
(1)exchange持久化,在声明时指定durable => 1;
(2)queue持久化,在声明时指定durable => 1;
(3)消息持久化,在投递时指定delivery_mode=> 2(1是非持久化,2表示persistent,持久化);
如果exchange和queue都是持久化的,那么它们之间的binding也是持久化的。如果exchange和queue两者之间有一个持久化,一个非持久化,就不允许建立绑定。
说明:delivery mode(投递模式)
3、绑定(binding)的持久化: