从计算机术语层面来说,RabbitMQ 模型更像是一种交换机模型。
Queue
:队列,是RabbitMQ
的内部对象,用于存储消息。
RabbitMQ
中消息只能存储在队列中,这一点和Kafka
相反。Kafka
将消息存储在topic
(主题)这个逻辑层面,而相对应的队列逻辑只是topic
实际存储文件中的位移标识。
RabbitMQ
不支持队列层面的广播消费。
Exchange
:交换器,生产者将消息发送到Exchange,由交换器将消息路由到一个或者多个队列中,如果路由不到,则会返回给生产者或者丢弃消息。
RabbitMQ
中的交换器有四种类型:
它会吧消息路由到那些 BindingKey
和 RoutingKey
完全匹配的队列中。
它会把所有发送到该交换器的消息路由到所有与该路由器绑定的队列中。
它与 direct 类型的交换器相似,也是将消息路由到 BindingKey 和 RouingKey 相匹配的队列中,但这里的匹配规则有些不同:
com.rabbitmq.client
、java.util.concurrent
;举个栗子:
headers
类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中 headers
属性进行匹配。headers
类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。
由使用过程发现,无论生产者或者消费者都需要和 RabbitMQ Broker 建立连接,这个连接(Connection)就是一条 TCP 连接,一旦 TCP 连接建立起来,客户端紧接着可以创建一个 AMQP 信道(Channel),每个信道都会被指派一个唯一ID。
信道是建立在 Connection 之上的虚拟连接,RabbitMQ 处理的每条 AMQP 指令都是通过信道完成的。
代码清单
channel.exchangeDeclare(exchangeName,"direct",true);
String queueName = channel.queueDeclare().getQueue();
// or 声明队列
channel.queueDeclare(queueName,true,false,false,null);
channel.queueBind(queueName,exchangeName,routingKey);
exchangeDeclare
有多个重载方法,这些重载方法都是由下面这个方法中缺省的某些参数构成的。
Exchange.DeclareOk exchangeDeclare(String exchange,
String type,
boolean durable,
boolean autoDelete,
boolean internal,
Map<String, Object> arguments) throws IOException;
Queue.DeclareOk queueDeclare() throws IOException;
Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
Map<String, Object> arguments) throws IOException;
x-message-ttl
、 x-expires
、 x-max-length
、 x-max-length-bytes
、 x-dead-letter-exchange
、 x-dead-letter-routing-key
、 x-max-priority
等;注意要点
生产者和消费者都能够使用 queueDeclare 来声明一个队列,但是如果消费者在同一个信道上订阅了另一个队列,就无法再声明队列了。必须先取消订阅,然后将信道置为“传输”模式,之后才能声明队列。
Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException;
Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
void queueBindNoWait(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
不仅可以将队列和交换器绑定起来,也可以将已经绑定的关系解除;
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;
不仅可以将交换器与队列绑定,也可以将交换器与交换器进行绑定,用法如出一辙。
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;