RabbitMQ的API参数细节-2

2021-04-05 11:14:44 浏览数 (1)

1. 通道绑定对应消息队列和发布消息

参数1:queue表示队列的名称

生产者代码:

代码语言:javascript复制
// 通道绑定对应消息队列
// 参数1:队列名称,如果队列不存在会自动创建
// 参数2:用来定义队列特性是否要持久化
// 参数3:是否独占队列,表示只有当前连接可用该队列
// 参数4:是否在消费完成后自动删除队列
// 参数5:额外附加参数
channel.queueDeclare("hello", false, false, false, null);

// 发布消息
// 参数1:交换器名称
// 参数2:队列名称
// 参数3:传递消息额外设置
// 参数4:消息的具体内容
String message = "hello rabbitmq";
channel.basicPublish("", "hello", null, message.getBytes());

注意:如果hello队列不存在,则会自动创建。

代码运行后,观察RabbitMQ管理器,消息队列创建成功

如果此时改变通道绑定对应消息队列

代码语言:javascript复制
// 通道绑定对应消息队列
// 由hello改为chage
channel.queueDeclare("change", false, false, false, null);

// 发布消息
String message = "hello rabbitmq";
channel.basicPublish("", "hello", null, message.getBytes());

代码运行后,观察RabbitMQ管理器,change消息队列创建成功,但是消息跑错地方了

如果要往change消息队列发送消息,则应该修改如下:

代码语言:javascript复制
String message = "hello rabbitmq";
channel.basicPublish("", "change", null, message.getBytes());

结论:

  • 同一个通道可以向不同的队列发送消息
  • basicPublish才是决定消息去什么通道,而不是queueDeclare

2. 队列持久化

参数2:durable 表示队列特性是否要持久化,这里设置为 false,重启RabbitMQ后,所有队列将丢失

代码语言:javascript复制
// 通道绑定对应消息队列
// 参数1:队列名称,如果队列不存在会自动创建
// 参数2:用来定义队列特性是否要持久化
// 参数3:是否独占队列,表示只有当前连接可用该队列
// 参数4:是否在消费完成后自动删除队列
// 参数5:额外附加参数
channel.queueDeclare("hello", false, false, false, null);

重启MQ服务

代码语言:javascript复制
systemctl restart rabbitmq-server

观察RabbitMQ管理器,发现hello消息队列丢失了

现在将hello消息队列设置成持久化

代码语言:javascript复制
channel.queueDeclare("hello", true, false, false, null);

可以看到Features显示为D(durable),表示设置成持久化,此时再重启MQ服务,消息队列不会丢失,但消息丢失了。

结论:

  • 如果消息队列不设置持久化,重启MQ服务后,没设置持久化的消息队列将会丢失
  • 如果消息队列设置了持久化,但没有设置消息持久化,重启MQ服务后,队列不会丢失,但消息会丢失

消息持久化

从上面我们可以看到,消息队列设置了持久化,但没有设置消息持久化,重启MQ服务后,队列不会丢失,但消息会丢失,怎么解决这个问题呢?

代码语言:javascript复制
// 发布消息
// 参数1:交换器名称
// 参数2:队列名称
// 参数3:传递消息额外设置
// 参数4:消息的具体内容
String message = "hello rabbitmq";
//channel.basicPublish("", "hello", null, message.getBytes());

// MessageProperties.PERSISTENT_TEXT_PLAIN 重启后,消息也要持久化
channel.basicPublish("", "hello", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

注意:

  • 一开始所有的消息是存储在内存中的
  • 当停止的时候,消息才会持久化到硬盘中
  • 当启动的时候,将硬盘中的消息读取到内存中

重启MQ服务后,队列和消息恢复成功

生产者与消费者通道绑定的参数一致性

生产者:

代码语言:javascript复制
// 通道绑定对应消息队列
// 参数1:队列名称,如果队列不存在会自动创建
// 参数2:用来定义队列特性是否要持久化
// 参数3:是否独占队列,表示只有当前连接可用该队列
// 参数4:是否在消费完成后自动删除队列
// 参数5:额外附加参数
channel.queueDeclare("hello", true, false, false, null);

消费者:

代码语言:javascript复制
channel.queueDeclare("hello", false, false, false, null);

通过观察发现,此时的参数2是不一致的,如果此时消费者进行消费,会出现ShutdownSignalException异常:

代码语言:javascript复制
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for queue 'hello' in vhost '/ems': received 'false' but current is 'true', class-id=50, method-id=10)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:502)
	at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:293)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:141)
	... 3 more

消费者只有参数一致才能成功消费

代码语言:javascript复制
channel.queueDeclare("hello", true, false, false, null);

输出结果

代码语言:javascript复制
输出队列中的内容>>>>>>>>>hello rabbitmq

3. 独占队列

参数3:exclusive 表示是否独占队列,如果设置为true,表示只有当前连接可以访问该消息队列,其他连接拒绝访问。

当然,在很多场景下,都是设置为false,允许多个连接访问同一个队列。

代码语言:javascript复制
// 通道绑定对应消息队列
// 参数1:队列名称,如果队列不存在会自动创建
// 参数2:用来定义队列特性是否要持久化
// 参数3:是否独占队列,表示只有当前连接可用该队列
// 参数4:是否在消费完成后自动删除队列
// 参数5:额外附加参数
channel.queueDeclare("hello", true, false, false, null);

4. 自动删除

参数4:autoDelete 表示是否在消费完成后自动删除队列

代码语言:javascript复制
channel.queueDeclare("hello", true, false, true, null);

当我结束消费者程序后,观察RabbitMQ管理器

注意:如果设置为自动删除队列,是消费者程序结束后才执行自动删除,如果程序未结束,则不会执行自动删除

0 人点赞