一、前景概要
1. RabbitMQ 通讯模型
生产方通过通道与交换机连接发送消息,消费方通过通道与队列连接消费消息
2. RabbitMQ 通讯过程
- 生产方首先建立一个连接到消息中间件(Broker)中的Virtual Host的Connection对象,然后根据Connection对象建一个Channel对象,这就和中间件建立了连接。
- 建立队列或交换机。
- 生产方通过Channel对象来指定路由消息的交换机、消息的路由键、消息的属性、消息体、消息路由不成功的操作,具体参照Channel的方法。
- 交换机会将消息路由到对应的队列中,不同的交换机有不同的路由规则。
- 消费方也建立Connection和Channel。
- 通过Channel中的方法来指定消费的队列,处理消息,给出反馈等,具体参照Channel的方法。
注意:
交换机/队列并非说与哪个消息、通道或者生产者/消费者绑定了,只是生产者在发送消息时指定了消息的相应路由属性并指定了交换机,具体怎么路由就看交换机的类型(不同类型交换机会有不同的路由规则)和消息的某些属性(比如:路由键)了。消费方则是在消费时指定了消费哪个队列中的消息。
二、通道类Channel类方法说明
创建队列、发送消息、消费端接收、消费消息、反馈等都是这个类里的方法。也就是说基于这个建立的通道来完成的。
1. 创建队列-----queueDeclare()
生产方或消费方指定队列属性、并创建队列的方法。
// 声明(创建)队列,下面这些参数是队列属性参数
//如果没有一个名为queue的队列,则会创建该队列,如果有则不会创建
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
参数 | 说明 |
---|---|
queue | 队列名称 |
durabdle | 消息代理(RabbitMq软件)重启后,队列依旧存在,(持久化) |
exclusive | 只被一个连接(connection)使用,而且当连接关闭后队列即被删除 |
autoDelete | 当最后一个消费者退订后即被删除 |
arguments | 一些消息代理用他来完成类似与TTL的某些额外功能 |
定义交换机----exchangeDeclare()
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString1, String paramString2) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString, BuiltinExchangeType paramBuiltinExchangeType) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString1, String paramString2, boolean paramBoolean) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString, BuiltinExchangeType paramBuiltinExchangeType, boolean paramBoolean) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString1, String paramString2, boolean paramBoolean1, boolean paramBoolean2, Map<String, Object> paramMap) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString, BuiltinExchangeType paramBuiltinExchangeType, boolean paramBoolean1, boolean paramBoolean2, Map<String, Object> paramMap) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString1, String paramString2, boolean paramBoolean1, boolean paramBoolean2, boolean paramBoolean3, Map<String, Object> paramMap) throws IOException;
AMQP.Exchange.DeclareOk exchangeDeclare(String paramString, BuiltinExchangeType paramBuiltinExchangeType, boolean paramBoolean1, boolean paramBoolean2, boolean paramBoolean3, Map<String, Object> paramMap) throws IOException;
exchange | 交换机名称 |
type | 有四种类型,分别为:fanout,direct,topic,headers |
durable | 表示是否持久化,为true,表示是exchange的持久化,仅设置这一项不代表消息的持久化。 |
autoDelete | 当没有消费者消费的时候是否要删除exchange |
路由绑定----queueBind()
绑定交换机和队列,指定路由键,默认交换机不需要绑定,会默认连接所有队列。
Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException;
Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
参数 | 说明 |
---|---|
queue | 队列名称 |
routingKey | 即Bindingkey |
exchange | 交换机名称 |
arguments | 其它的一些参数 |
接触绑定-----queueUnbind()
Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException;
Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
参数参照queueBind()
.多个交换机之间绑定----exchangeBind()
用于多个交换机之间的绑定,可以交换机之间发送消息
Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException;
Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;
void exchangeBindNoWait(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;
参数 | 说明 |
---|---|
destination | 目标交换机名称 |
source | 源交换机名称 |
routingKey | 即交换机间的Bindingkey,和消息的routingkey匹配 |
arguments | 其它的一些参数 |
2. 发送消息----basicPublish()
basicPublish()是生产方创建连接后,设置路由消息的交换机、消息属性、消息内容、发送消息的一个方法,可以对等消费方的basicConsume()方法,消息的属性可以类比http协议的一些消息头、消息行,有哪些属性可以参考中文手册。
void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;
void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body)throws IOException;
void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;
参数 | 说明 |
---|---|
exchange | 交换机名称,指定交换机 ,没有指定则使用默认Default Exchage,参数可以直接写入"" |
routingKey | 消息的路由键,用于交换机依此找到对应的队列 |
mandatory | true:如果交换器无法根据自动的类型和路由键找到一个符合条件的队列,那么RabbitMq会调用Basic.Ruturn命令将消息返回给生产者; false:出现上述情况消息被直接丢弃 |
immediate | 如果交换器将消息路由到队列时,发现没有任何消费者,那么这个消息将不会存在该队列,当与路由匹配的所有队列都没有消费者时,会Basic.Return返回给生产者,3.0去掉了immediate参数。immediate和mandatory 都是消息传递过程中,不可达目的地时,将消息返回给生产者或直接丢弃的功能。 |
props | 消息的其它属性 |
body | 消息体 |
3. 消费消息----basicConsume()
消费方创建连接后,用来消费消息,并设置反馈方式,和前面的basicPublish()是对应的,前面生产,这个消费。
参数说明:
queue 队列名
autoAck 是否自动确认消息,true自动确认,false手动调用,自动就是当消息代理(broker)将消息发送给应用后
立即删除;手动就是待应用(application)发送一个确认回执(acknowledgement)后再删除消息,回执自己定义:channel.basicAck()。
consumerTag 消费者标签,用来区分多个消费者
noLocal 设置为true,表示不能将同一个Conenction中生产者发送的消息传递给这个Connection中的消费者
exclusive 是否排他
arguments 消费者的参数
callback 消费者 DefaultConsumer建立使用,重写其中的方法,其中有消费,反馈等方法的重写,见下面
String basicConsume(String queue, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback) throws IOException;
参数 | 说明 |
---|---|
queue | 要消费的队列名 |
autoAck | 是否自动确认消息,true自动确认,false手动调用; 自动:当消息代理(broker)将消息发送给应用后立即删除; 手动:待应用(application)发送一个确认回执(acknowledgement)后再删除消息,回执自己定义:需要使用channel.ack、channel.nack、channel.basicReject 进行消息应答 |
consumerTag | 消费者标签,用来区分多个消费者 |
noLocal | 为true:不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者 |
exclusive | 是否排它 |
arguments | |
callback | DefaultConsumer类对象 |
3.2 DefaultConsumer类
Consumer的实现类,作为basicConsume的一个参数,用来接收消息、指定消息如何处理等,每个方法都会指定参数String consumerTag,这个相当于消费方的唯一标识,用于锁定相应的消费方(consumer)具体参照Web | Rabbit MQ | 基础部分中的4.1。
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {}
public void handleCancelOk(String consumerTag) {}
public void handleCancel(String consumerTag) throws IOException {}
public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) {}
public void handleRecoverOk(String consumerTag) {}
handleDelivery
在接收到消息后会被调用,重写方法可以写处理相消息数据逻辑
其它方法好像也是相应时机来执行的,具体不详,另外basicC好像反馈basicConsume()中设置为手动确认,可以通过重写其中的一个方法而完成手动反馈逻辑。也可以调用channel.basicAck()
手动确认消息----basicAck()
void basicAck(long deliveryTag, boolean multiple) throws IOException;
参数 | 说明 |
---|---|
deliveryTag | 消息的index,消费下个消息会在这个值的基础上加1,当然是在consumerTag相同的情况下,如果是另一个consumerTag则又从1开始计,也就是说同一个消费者,或者理解为每次消费消息的是同一个线程,因为每次执行消费消息的并非是同一个线程在循环监听,底层原理没了解过,但大致可以猜一下。 |
multiple | 是否批量,若为true,则一次性回执所有小于paramLong的消息 |