??RabbitMQ是消息代理:它接受并转发消息。可以将它视为邮局:当你投递邮件到一个邮箱,邮递员终究会将邮件递交给你的收件人。以此类推,RabbitMQ可以是一个邮箱,一个邮局和一个邮递员。
??RabbitMQ与邮局之间的主要区别在于,它不处理纸张,而是接收,存储和转发数据消息的二进制数据。
??2.1 生产者(producer)与消费者(consumer)
??生产者与消费者是RabbitMQ通信过程中的两个重要的角色,相当于邮件的发送方与接收方,而RabbitMQ充当的角色就是传递消息的第三方,也就是说它是不能产生数据的。在实际应用中,生产者和消费者也是可以角色互相转换的,所以当我们应用程序连接到 RabbitMQ 服务器时,必须要明确我是生产者还是消费者。
??2.2 连接(Connections)
??生产者生产消息之后,发布到RabbitMQ之前,需要先连接RabbitMQ服务器吧,RabbitMQ支持的所有协议都是基于TCP的,并且为了提高效率而采用长期连接(每个协议操作不会打开新连接)。一个客户端库连接使用单个TCP连接。
??2.3 通道(Channels)
??建立完连接之后,客户端会基于该TCP连接的基础之上,开辟一条AMQP通道,客户端执行的每个协议操作都在通道上发生,通道存在于连接中,而不是单独存在的。关闭连接后,其上的所有通道也将关闭。
??我们也可以在一条连接中开辟一条或多条AMQP通道,每条通道都会有一个唯一的ID来确保通道之间互不干预
??2.4 队列(Queues)
??队列是RabbitMQ服务器中消息的终点,类似于一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
??2.5 交换机(Exchanges)
??交换机用于接收生产者发送的消息,并且能处理消息,例如将消息递交给某个队列、递交给所有队列、或者将消息丢弃,它主要应用的有三种类型:
?a、Fanout:广播(扇形),将消息交给所有绑定到交换机的队列
?b、Direct:定向(直连),把消息交给符合指定routing_key 的队列
?c、Topic:通配符(主题),把消息交给符合routing pattern(路由模式) 的队列
??2.1 simple简单模式
??生产者与消费者为一对一的关系,一条消息只能被一个消费者消费,如果此时没有消费者,那么消息会被暂时缓存在queue中,直至被消费
??2.2 work工作模式
??在work模型下,生产者与消费者为一对多的关系,多个消费者可以绑定到一个队列,共同消费队列中的消息
??queue可以实现负载均衡,生产者将消息放入queue中后,RabbitMQ会通过轮询的方式,实现消息的分配
??通过消息确认机制(Acknowlege)实现。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:
手动ACK:消息接收后,不会发送ACK,需要手动调用
??这就要取决于消息的重要性,如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便,反之,如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除,如果此时消费者宕机,那么消息就丢失了。
??2.3 订阅模型-Fanout
??X表示交换机;在广播模式下,消息发送流程是这样的:
??2.4 订阅模型-Direct
在Direct模型下:
routing_key
(路由key)routing_key
。routing_key
进行判断,只有队列的routing_key
与消息的 routing_key
完全一致,才会接收到消息??2.5 订阅模型-Topic
??Topic类型的Exchange与Direct相比,都是可以根据routing_key把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定routing_key的时候使用通配符!通配符规则:
??#
:可以替代零个或多个单词。
??*
:可以代替一个单词
图解:
*.orange.*
的routing_key,它能匹配到以orange为中心,前后各一个单词的路由,例如:item.orange.insert
,但是该item.orange.insert.one
路由就不能被匹配C2:消费者,其所在队列Q2绑定了lazy.#
的routing_key,它能匹配到任何以lazy.#
开头的路由
//获取连接
Connection connection = ConnectionUtil.getConnection();
//建立通道
Channel channel = connection.createChannel();
//交换机持久化 ,第三个参数代表是否持久化
channel.exchangeDeclare(EXCHANGE_NAME,"EXCHANGE_TYPE",true);
//队列持久化 ,第二个参数代表是否持久化
channel.queueDeclare(QUEUE_NAME,true,false,false,null);
//消息持久化 ,第三个参数代表是否持久化
channel.basicPublish(EXCHANGE_NAME,routing_key,MessageProperties.PERSISTENT_TEXT_PLAIN,MESSAGE_TEXT.getBYtes());
原文:https://www.cnblogs.com/kaischoolmate/p/12104551.html