RabbitMQ第二弹 交换器和队列

下面介绍RabbitMQ架构的核心概念。
a)Broker
b)生产者Producer
c)消费者Consumer
d)连接Connection与信道Channel
e)交换器Exchange
f)队列Queue
g)路由键RoutingKey
h)绑定Binding
2、四种交换器类型
交换器的作用是将消息路由到队列中,而不同的交换器类型具有不同的路由规则。RabbitMQ常用的交换器类型有fanout 、direct、topic 、headers 这四种,AMQP 协议里还有另外两种类型:system 和自定义。
a)fanout扇形交换器
-
将消息路由到所有与该交换器绑定的队列中。
b)direct直连交换器
-
将消息路由到BindingKey和RoutingKey完全匹配的队列中。
c)topic主题交换器
-
BindingKey和RoutingKey可以使用点号分隔为多个单词。
-
BindingKey可以使用#和*两种特殊字符,#用于匹配一个单词,*用于匹配多个单词(可以是0个)。
d)headers交换器
-
headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配,headers 类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。
3、RabbitMQ Java客户端实战
在上面的核心概念中,介绍了RabbitMQ的交换器和队列,以及交换器与队列是存在绑定关系的,下面用RabbitMQ的Java客户端演示一下如何创建交换器、队列以及将交换器和队列绑定起来。
<dependency>
<groupld>com.rabbitmq</groupld>
<artifactld>amqp-client</artifactid>
<version>5.7.3</version>
</dependency>
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class RabbitMQClient {
private Connection conn;
{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.216.132");
factory.setPort(5672);
factory.setUsername("bobo");
factory.setPassword("ok");
// VirtualHost相当于一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互隔离的。exchange、queue、message不能互通;
// 在RabbitMQ中,权限控制是以vhost为单位的,当创建一个用户时,用户通常会被指派给至少一个vhost,且只能访问被指派的vhost内的队列、交换器和绑定关系等;
factory.setVirtualHost("/");
try {
// 也可以通过uri的方式连接
// factory.setUri("amqp://bobo:ok@192.168.216.132:5672");
this.conn = factory.newConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
public Channel getChannel() throws Exception {
Channel channel = this.conn.createChannel();
return channel;
}
public static void main(String[] args) throws Exception {
RabbitMQClient mqClient = new RabbitMQClient();
// 获取channel
Channel channel = mqClient.getChannel();
// 关闭连接
channel.getConnection().close();
}
}
然后,我们再使用客户端API依次声明交换器、队列以及将交换器与队列绑定起来,如下代码所示。
// 声明交换器
channel.exchangeDeclare("bobo-exchange-a", BuiltinExchangeType.DIRECT,true);
// 声明队列
String queueName = channel.queueDeclare("bobo-queue-a",true,false,false,null).getQueue();
// 将队列和交换器绑定
channel.queueBind(queueName,"bobo-exchange-a","bindingkey-a");
运行上面的代码,然后在RabbitMQ管理界面中可以看到创建好的交换器与队列,如下图所示。
4、交换器与队列API
上面的代码中channel对象有三个重要的方法:exchangeDeclare、queueDeclare、queueBind,下面学习一下如何使用这些方法。
声明一个交换器使用exchangeDeclare方法,该参数如下:
-
exchange:交换器名称,多次声明同一名称的交换器不会覆盖,而是抛异常;
-
type:交换器类型;
-
durable:是否持久化;持久化可以将交换器存到磁盘;
-
autoDelete:是否自动删除;自动删除的前提是至少有一个队列或者交换器与这个交换器绑定,之后所有与这个交换器绑定的队列或交换器都与此解绑才会自动删除;
-
internal:是否内置的;生产者无法直接发送消息到内置交换器中,只能通过交换器路由到交换器这种方式;
-
argument:配置其它参数;
exchangeDeclareNoWait方法:
-
不建议使用;在声明完一个交换器后,由于不需要等待服务器返回,实际服务器还并未完成交换器的创建,那么此时生产者紧接着使用这个交换器,必然会发生异常;
exchangeDeclarePassive方法:
-
实际不创建交换器,只用于检测交换器是否存在,如果不存在则抛出异常;
exchangeDelete方法:
-
删除交换器;
声明一个队列使用queueDeclare方法,该方法参数如下:
-
queue:队列名称;
-
durable:是否持久化;
-
exclusive:是否排它(排它队列),如果是,则该队列仅对首次声明它的连接可见,并在连接断开时自动删除,即不同connection之间不能共用,但同一connection的不同channel可共用;
-
autoDelete:是否自动删除,自动删除的前提是至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时才会自动删除;
-
arguments:队列的其它参数;
注意,生产者和消费者都能够使用queueDeclare来声明一个队列,但是如果消费者在同一个channel上订阅了另一个队列,就无法再声明队列了。必须先取消订阅,然后将channel置为传输模式之后才能声明队列。
如果queueDeclare方法不传任何参数,则队列的名称自动生成,且该队列为非持久、排它、自动删除的。
queueDeclareNoWait方法:
-
类似exchangeDeclareNoWait方法;
queueDeclarePassive方法:
-
类似exchangeDeclarePassive方法;
queueDelete(queueName)方法:
-
删除队列;
queuePurge方法:
-
清空队列内容而不删除队列;
最后再看一下绑定与解绑方法。
// 将队列和交换器绑定
channel.queueBind("queueName","exchangeName","bindingkey");
// 将队列和交换器解绑
channel.queueUnbind("queueName","exchangeName","bindingkey");
// 将交换器与交换器绑定
channel.exchangeBind("exchangeName-to","exchangeName-from","bindingkey");
原文始发于微信公众号(初心JAVA):RabbitMQ第二弹 交换器和队列