RabbitMQ 属性参数配置详情
01、SpringBoot 配置参数详解
1、application.yml
spring:
rabbitmq:
host: 127.0.0.1 #ip
port: 5672 #端口
username: guest #账号
password: guest #密码
virtualHost: #链接的虚拟主机
addresses: 127.0.0.1:5672 #多个以逗号分隔,与host功能一样。
requestedHeartbeat: 60 #指定心跳超时,单位秒,0为不指定;默认60s
publisherConfirms: true #发布确认机制是否启用
publisherReturns: #发布返回是否启用
connectionTimeout: #链接超时。单位ms。0表示无穷大不超时
### ssl相关
ssl:
enabled: #是否支持ssl
keyStore: #指定持有SSL certificate的key store的路径
keyStoreType: #key store类型 默认PKCS12
keyStorePassword: #指定访问key store的密码
trustStore: #指定持有SSL certificates的Trust store
trustStoreType: #默认JKS
trustStorePassword: #访问密码
algorithm: #ssl使用的算法,例如,TLSv1.1
verifyHostname: #是否开启hostname验证
### cache相关
cache:
channel:
size: #缓存中保持的channel数量
checkoutTimeout: #当缓存数量被设置时,从缓存中获取一个channel的超时时间,单位毫秒;如果为0,则总是创建一个新channel
connection:
mode: #连接工厂缓存模式:CHANNEL 和 CONNECTION
size: #缓存的连接数,只有是CONNECTION模式时生效
### listener
listener:
type: #两种类型,SIMPLE,DIRECT
## simple类型
simple:
concurrency: #最小消费者数量
maxConcurrency: #最大的消费者数量
transactionSize: #指定一个事务处理的消息数量,最好是小于等于prefetch的数量
missingQueuesFatal: #是否停止容器当容器中的队列不可用
## 与direct相同配置部分
autoStartup: #是否自动启动容器
acknowledgeMode: #表示消息确认方式,其有三种配置方式,分别是none、manual和auto;默认auto
prefetch: #指定一个请求能处理多少个消息,如果有事务的话,必须大于等于transaction数量
defaultRequeueRejected: #决定被拒绝的消息是否重新入队;默认是true(与参数acknowledge-mode有关系)
idleEventInterval: #container events发布频率,单位ms
##重试机制
retry:
stateless: #有无状态
enabled: #是否开启
maxAttempts: #最大重试次数,默认3
initialInterval: #重试间隔
multiplier: #对于上一次重试的乘数
maxInterval: #最大重试时间间隔
direct:
consumersPerQueue: #每个队列消费者数量
missingQueuesFatal:
#...其余配置看上方公共配置
## template相关
template:
mandatory: #是否启用强制信息;默认false
receiveTimeout: #`receive()`接收方法超时时间
replyTimeout: #`sendAndReceive()`超时时间
exchange: #默认的交换机
routingKey: #默认的路由
defaultReceiveQueue: #默认的接收队列
## retry重试相关
retry:
enabled: #是否开启
maxAttempts: #最大重试次数
initialInterval: #重试间隔
multiplier: #失败间隔乘数
maxInterval: #最大间隔
2、application.properties
############################ base ############################
spring.rabbitmq.host: 服务Host
spring.rabbitmq.port: 服务端口
spring.rabbitmq.username: 登陆用户名
spring.rabbitmq.password: 登陆密码
spring.rabbitmq.virtual-host: 连接到rabbitMQ的vhost
spring.rabbitmq.addresses: 指定client连接到的server的地址,多个以逗号分隔(优先取addresses,然后再取host)
spring.rabbitmq.requested-heartbeat: 指定心跳超时,单位秒,0为不指定;默认60s
spring.rabbitmq.publisher-confirms: 是否启用【发布确认】
spring.rabbitmq.publisher-returns: 是否启用【发布返回】
spring.rabbitmq.connection-timeout: 连接超时,单位毫秒,0表示无穷大,不超时
############################ ssl ############################
spring.rabbitmq.ssl.enabled: 是否支持ssl
spring.rabbitmq.ssl.key-store: 指定持有SSL certificate的key store的路径
spring.rabbitmq.ssl.key-store-password: 指定访问key store的密码
spring.rabbitmq.ssl.trust-store: 指定持有SSL certificates的Trust store
spring.rabbitmq.ssl.trust-store-password: 指定访问trust store的密码
spring.rabbitmq.ssl.trust-store-type: JKS:Trust store 类型
spring.rabbitmq.ssl.algorithm: ssl使用的算法,默认由rabiitClient配置,例如,TLSv1.1
spring.rabbitmq.ssl.validate-server-certificate=true:是否启用服务端证书验证
spring.rabbitmq.ssl.verify-hostname=true 是否启用主机验证
############################ cache ############################
spring.rabbitmq.cache.channel.size: 缓存中保持的channel数量
spring.rabbitmq.cache.channel.checkout-timeout: 当缓存数量被设置时,从缓存中获取一个channel的超时时间,单位毫秒;如果为0,则总是创建一个新channel
spring.rabbitmq.cache.connection.size: 缓存的连接数,只有是CONNECTION模式时生效
spring.rabbitmq.cache.connection.mode: 连接工厂缓存模式:CHANNEL 和 CONNECTION
############################ listener ############################
spring.rabbitmq.listener.type=simple: 容器类型.simple或direct
spring.rabbitmq.listener.simple.auto-startup: 是否启动时自动启动容器
spring.rabbitmq.listener.simple.acknowledge-mode: 表示消息确认方式,其有三种配置方式,分别是none、manual和auto;默认auto
spring.rabbitmq.listener.simple.concurrency: 最小的消费者数量
spring.rabbitmq.listener.simple.max-concurrency: 最大的消费者数量
spring.rabbitmq.listener.simple.prefetch: 指定一个请求能处理多少个消息,如果有事务的话,必须大于等于transaction数量.
spring.rabbitmq.listener.simple.transaction-size: 指定一个事务处理的消息数量,最好是小于等于prefetch的数量.
spring.rabbitmq.listener.simple.default-requeue-rejected: 决定被拒绝的消息是否重新入队;默认是true(与参数acknowledge-mode有关系)
spring.rabbitmq.listener.simple.missing-queues-fatal=true 若容器声明的队列在代理上不可用,是否失败; 或者运行时一个多多个队列被删除,是否停止容器
spring.rabbitmq.listener.simple.idle-event-interval: 多少长时间发布空闲容器时间,单位毫秒
spring.rabbitmq.listener.simple.retry.enabled: 监听重试是否可用
spring.rabbitmq.listener.simple.retry.max-attempts: 最大重试次数
spring.rabbitmq.listener.simple.retry.initial-interval: 第一次和第二次尝试发布或传递消息之间的间隔
spring.rabbitmq.listener.simple.retry.multiplier: 应用于上一重试间隔的乘数
spring.rabbitmq.listener.simple.retry.max-interval: 最大重试时间间隔
spring.rabbitmq.listener.simple.retry.stateless: 重试是有状态or无状态
spring.rabbitmq.listener.direct.acknowledge-mode= ack模式
spring.rabbitmq.listener.direct.auto-startup=true 是否在启动时自动启动容器
spring.rabbitmq.listener.direct.consumers-per-queue= 每个队列消费者数量.
spring.rabbitmq.listener.direct.default-requeue-rejected= 默认是否将拒绝传送的消息重新入队.
spring.rabbitmq.listener.direct.idle-event-interval= 空闲容器事件发布时间间隔.
spring.rabbitmq.listener.direct.missing-queues-fatal=false若容器声明的队列在代理上不可用,是否失败.
spring.rabbitmq.listener.direct.prefetch= 每个消费者可最大处理的nack消息数量.
spring.rabbitmq.listener.direct.retry.enabled=false 是否启用发布重试机制.
spring.rabbitmq.listener.direct.retry.initial-interval=1000ms # Duration between the first and second attempt to deliver a message.
spring.rabbitmq.listener.direct.retry.max-attempts=3 # Maximum number of attempts to deliver a message.
spring.rabbitmq.listener.direct.retry.max-interval=10000ms # Maximum duration between attempts.
spring.rabbitmq.listener.direct.retry.multiplier=1 # Multiplier to apply to the previous retry interval.
spring.rabbitmq.listener.direct.retry.stateless=true # Whether retries are stateless or stateful.
############################ template ############################
spring.rabbitmq.template.mandatory: 启用强制信息;默认false
spring.rabbitmq.template.receive-timeout: receive() 操作的超时时间
spring.rabbitmq.template.reply-timeout: sendAndReceive() 操作的超时时间
spring.rabbitmq.template.retry.enabled: 发送重试是否可用
spring.rabbitmq.template.retry.max-attempts: 最大重试次数
spring.rabbitmq.template.retry.initial-interval: 第一次和第二次尝试发布或传递消息之间的间隔
spring.rabbitmq.template.retry.multiplier: 应用于上一重试间隔的乘数
spring.rabbitmq.template.retry.max-interval: 最大重试时间间隔
02、创建队列附加参数详解
1、Web端查看
2、代码设置
SpringBoot 创建queue设置附加参数(附加参数类型为Map)
package com.example.config;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* 简单队列模式
**/
//@Configuration
public class QueueParamRabbitMQConfig {
@Bean
public Queue queue() {
/**
* durable:是否持久化,默认是false,持久化队列(内部会有一个actualName: 队列的真实名称,默认用name参数,如果name为空,则根据规则生成一个)
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
* arguments:设置队列的属性参数
* 1、x-message-ttl:消息的过期时间,单位:毫秒;
* 2、x-expires:队列过期时间,队列在多长时间未被访问将被删除,单位:毫秒;
* 3、x-max-length:队列最大长度,超过该最大值,则将从队列头部开始删除消息;
* 4、x-max-length-bytes:队列消息内容占用最大空间,受限于内存大小,超过该阈值则从队列头部开始删除消息;
* 5、x-overflow:设置队列溢出行为。这决定了当达到队列的最大长度时消息会发生什么。有效值是drop-head、reject-publish或reject-publish-dlx。仲裁队列类型仅支持drop-head;
* 6、x-dead-letter-exchange:死信交换器名称,过期或被删除(因队列长度超长或因空间超出阈值)的消息可指定发送到该交换器中;
* 7、x-dead-letter-routing-key:死信消息路由键,在消息发送到死信交换器时会使用该路由键,如果不设置,则使用消息的原来的路由键值
* 8、x-single-active-consumer:表示队列是否是单一活动消费者,true时,注册的消费组内只有一个消费者消费消息,其他被忽略,false时消息循环分发给所有消费者(默认false)
* 9、x-max-priority:队列要支持的最大优先级数;如果未设置,队列将不支持消息优先级;
* 10、x-queue-mode(Lazy mode):将队列设置为延迟模式,在磁盘上保留尽可能多的消息,以减少RAM的使用;如果未设置,队列将保留内存缓存以尽可能快地传递消息;
* 11、x-queue-master-locator:在集群模式下设置镜像队列的主节点信息。
*/
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 5000);
Queue queue = new Queue("ttl.direct.queue", true, false, false, args);
// 也可以用build模式创建
Queue build = QueueBuilder.durable("test.queue")
.exclusive()
.autoDelete()
.withArguments(args)
.build();
return build;
}
}
// Java 版本参数可直接参考上面SpringBoot即可
channel.queueDeclare("ttl-queue", false, false, false, arguments);
arguments:设置队列的属性参数
1、x-message-ttl:消息的过期时间,单位:毫秒;
2、x-expires:队列过期时间,队列在多长时间未被访问将被删除,单位:毫秒;
3、x-max-length:队列最大长度,超过该最大值,则将从队列头部开始删除消息;
4、x-max-length-bytes:队列消息内容占用最大空间,受限于内存大小,超过该阈值则从队列头部开始删除消息;
5、x-overflow:设置队列溢出行为。这决定了当达到队列的最大长度时消息会发生什么。
有效值是drop-head、reject-publish或reject-publish-dlx。仲裁队列类型仅支持drop-head;
6、x-dead-letter-exchange:死信交换器名称,过期或被删除(因队列长度超长或因空间超出阈值)的消息可指定发送到该交换器中;
7、x-dead-letter-routing-key:死信消息路由键,在消息发送到死信交换器时会使用该路由键,
如果不设置,则使用消息的原来的路由键值
8、x-single-active-consumer:表示队列是否是单一活动消费者,true时,注册的消费组内只有一个消费者消费消息,
其他被忽略,false时消息循环分发给所有消费者(默认false)
9、x-max-priority:队列要支持的最大优先级数;如果未设置,队列将不支持消息优先级;
10、x-queue-mode(Lazy mode):将队列设置为延迟模式,在磁盘上保留尽可能多的消息,以减少RAM的使用;
如果未设置,队列将保留内存缓存以尽可能快地传递消息;
11、x-queue-master-locator:在集群模式下设置镜像队列的主节点信息。
03、发送消息附加参数详解
1、Web 端查看
2、AMQP.BasicProperties
JAVA版:附加参数类型为:AMQP.BasicProperties
RabbitMQ发布消息的方法为:
void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;
其中 props 参数可为消息体赋予多种的功能特性。BasicProperties的属性有以下:
String contentType, //消息内容的类型
String contentEncoding, //消息内容的编码格式
Map<String,Object> headers,//header类型的交换机可以用到
Integer deliveryMode,//消息持久化 1 不持久化 2 持久化
Integer priority,//优先级
String correlationId, //关联id
String replyTo,//通常用于命名回调队列
String expiration,//设置过期消息过期时间
String messageId, //消息id
Date timestamp, //消息的时间戳
String type, //类型
String userId, //用户ID
String appId, //应用程序id
String clusterId //集群id
参考示例:
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("arg1", "aaa");
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
.deliveryMode(2) // 传送方式
.contentEncoding("UTF-8") // 编码方式
.expiration("10000") // 过期时间
.headers(headers) //自定义属性
.build();
RabbitMQ内部封装的几个方法:
public class MessageProperties {
/** Empty basic properties, with no fields set */
public static final BasicProperties MINIMAL_BASIC =
new BasicProperties(null, null, null, null,
null, null, null, null,
null, null, null, null,
null, null);
/** Empty basic properties, with only deliveryMode set to 2 (persistent) */
public static final BasicProperties MINIMAL_PERSISTENT_BASIC =
new BasicProperties(null, null, null, 2,
null, null, null, null,
null, null, null, null,
null, null);
/** Content-type "application/octet-stream", deliveryMode 1 (nonpersistent), priority zero */
public static final BasicProperties BASIC =
new BasicProperties("application/octet-stream",
null,
null,
1,
0, null, null, null,
null, null, null, null,
null, null);
/** Content-type "application/octet-stream", deliveryMode 2 (persistent), priority zero */
public static final BasicProperties PERSISTENT_BASIC =
new BasicProperties("application/octet-stream",
null,
null,
2,
0, null, null, null,
null, null, null, null,
null, null);
/** Content-type "text/plain", deliveryMode 1 (nonpersistent), priority zero */
public static final BasicProperties TEXT_PLAIN =
new BasicProperties("text/plain",
null,
null,
1,
0, null, null, null,
null, null, null, null,
null, null);
/** Content-type "text/plain", deliveryMode 2 (persistent), priority zero */
public static final BasicProperties PERSISTENT_TEXT_PLAIN =
new BasicProperties("text/plain",
null,
null,
2,
0, null, null, null,
null, null, null, null,
null, null);
}
3、MessageProperties
SpringBoot版:附加参数类型:MessageProperties
可以直接参考源码:org.springframework.amqp.core.MessageProperties,查看内部的字段即可,由于字段太多没有贴出来了。
参考示例:
/**
* Headers模式
*/
@Test
public void headersSend() {
MessageProperties messageProperties1 = new MessageProperties();
messageProperties1.setHeader("header1","value1");
messageProperties1.setHeader("header11","value11");
Message message1 = new Message(("Header模式—单个匹配").getBytes(), messageProperties1);
rabbitTemplate.convertAndSend("header_exchange","",message1);
MessageProperties messageProperties2 = new MessageProperties();
messageProperties2.setHeader("header2","value2");
messageProperties2.setHeader("header22","value22");
Message message2 = new Message(("Header模式—全部匹配").getBytes(), messageProperties2);
rabbitTemplate.convertAndSend("header_exchange","",message2);
}
/**
* TTL过期时间测试——对消息本身设置过期时间
* 测试发送后查看web页面,5秒后消息自动消失了
*/
@Test
public void ttlMessageDirectSend() {
MessagePostProcessor messagePostProcessor = message -> {
MessageProperties messageProperties = message.getMessageProperties();
messageProperties.setExpiration("5000");
messageProperties.setContentEncoding("UTF-8");
return message;
};
rabbitTemplate.convertAndSend("ttl_direct_exchange","ttl.message","TTL-消息过期时间", messagePostProcessor);
}
04、@RabbitListener 详解
case1:exchange_queue 已存在
package com.example.config;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
@Component
public class AutoCreateQueueExchange {
/**
* 队列和交换机已经存在,只用使用queues,消费指定的queue即可.
* 可以单独监听一个或者多个队列。如下只用其一即可
* queues参数值为对列名(queueName)
*/
//@RabbitListener(queues = {"exist.queue1", "exist.queue2"})
@RabbitListener(queues = "simple.queue")
public void receive1(String msg){
}
/**
* 单独声明队列
*/
//@RabbitListener(queuesToDeclare = {@Queue(value = "queue1"),@Queue(value = "queue2")})
@RabbitListener(queuesToDeclare = @Queue(value = "declare.queue"))
public void receive2(String msg){
}
}
case2:exchange_queue 不存在
/**
* 发布/订阅模式 Fanout
* @QueueBinding 注解的三个属性
* value: @Queue注解用于声明队列,value:queueName,durable: 队列是否持久化,autoDelete: 否自动删除
* exchange: @Exchange 注解,用于声明 exchange, type 指定消息投递策略,我们这里用的 fanout 方式
* key: 这个就是我们熟知的 routingKey,在fanout方式下是没有routingKey的
*/
@RabbitHandler
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "fanout.queue1",durable = "true", autoDelete = "false"),
exchange = @Exchange(value = "fanout.exchange1", type = ExchangeTypes.FANOUT)
)
})
public void receive3(String msg){
}
/**
* 路由模式 Direct
* @QueueBinding 注解的三个属性
* value: @Queue注解用于声明队列,value:queueName,durable: 队列是否持久化,autoDelete: 否自动删除
* exchange: @Exchange 注解,用于声明 exchange, type 指定消息投递策略,我们这里用的 fanout 方式
* key: 这个就是我们熟知的 routingKey,在fanout方式下是没有routingKey的
* 注意:由于@Exchange 中 type默认值就是DIRECT,所以可以省略:type = ExchangeTypes.DIRECT
*/
@RabbitHandler
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "direct.queue1", durable = "true", autoDelete = "false"),
exchange = @Exchange(value = "direct.exchange1"),
key = "direct.key1"
)
})
public void receive4(String msg){
}
/**
* 主题模式 Topic—单个申请
*/
@RabbitHandler
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "topic.queue1",autoDelete = "false"),
exchange = @Exchange(value = "topic.exchange1", type = ExchangeTypes.TOPIC),
key = "topic.key1"
)
})
public void receive5(String msg){
}
/**
* 主题模式 Topic—多个申请
*/
@RabbitHandler
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "topic.queue1",autoDelete = "false"),
exchange = @Exchange(value = "test.exchange1", type = ExchangeTypes.TOPIC),
key = "topic.key1"
),
@QueueBinding(
value = @Queue(value = "topic.queue2",autoDelete = "false"),
exchange = @Exchange(value = "test.exchange1", type = ExchangeTypes.TOPIC),
key = "topic.key2"
)
})
public void receive6(String msg){
}
/**
* Headers 模式
*/
@RabbitHandler
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "headers.queue1",autoDelete = "false"),
exchange = @Exchange(value = "headers.exchange1", type = ExchangeTypes.HEADERS),
arguments = {
@Argument(name = "x-match", value = "any"),
@Argument(name = "key-one", value = "1"),
@Argument(name = "key-two", value = "2")
}
)
})
public void receive7(String msg){
}
case3:延迟队列+死信队列声明
/**
* 声明延迟队列。并绑定死信交换机。
* 设置延迟队列消息超过5秒就过期,并且消息最大条数为3条。超过了也会成为死信消息。
* 并且开启了 消息手动确认ack模式
*/
@RabbitHandler
@RabbitListener(ackMode = "MANUAL",bindings = {
@QueueBinding(value = @Queue(value = "liveQueue", arguments = {
@Argument(name = "x-dead-letter-exchange", value = "deadExchange"),
@Argument(name = "x-dead-letter-routing-key", value = "deadKey"),
@Argument(name = "x-message-ttl", value = "5000", type = "java.lang.Integer"),
@Argument(name = "x-max-length",value = "3",type = "java.lang.Integer")
}),
exchange = @Exchange(value = "liveExchange"),
key = {"info", "error", "warning"}
)
})
public void onMessage1(String msg, Message message, Channel channel) throws IOException {
long consumerTag = message.getMessageProperties().getDeliveryTag();
try {
// 模拟消费消息, 回调接收ack是true 因为回调的ack根据exchange是否收到消息判断
int i = 1/new Random().nextInt(1);
System.out.println("收到消息:" + new String(message.getBody()));
channel.basicAck(consumerTag, false);
} catch (Exception e) {
// 消费异常消息会添加到死信队列
channel.basicNack(consumerTag, false, false);
}
}
/**
* 声明死信交换机和队列 并且绑定
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "deadQueue"),
exchange = @Exchange(value = "deadExchange"),
key = "deadKey"
)
})
public void onMessage2(Message message, Channel channel) throws IOException {
System.out.println("我是一条死信队列:" + message);
long consumerTag = message.getMessageProperties().getDeliveryTag();
channel.basicAck(consumerTag, true);
}
case4:手动 Ack + 并发消费
当消息很多,一个消费者吭哧吭哧的消费太慢,但是我的机器性能又杠杠的,这个时候我就希望并行消费,相当于同时有多个消费者来处理数据。要支持并行消费,如下设置即可
/**
* 手动ack:ackMode = "MANUAL"
* 注意:
* @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag
* 替代了 参数 Message message
* long deliveryTag = message.getMessageProperties().getDeliveryTag();
*/
@RabbitHandler
@RabbitListener(queues = "simple.queue", ackMode = "MANUAL")
public void consumerDoAck(String msg, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
Channel channel) throws IOException {
if (msg.contains("ok")) {
channel.basicAck(deliveryTag, false);
} else {
channel.basicNack(deliveryTag, false, true);
}
}
/**
* 并发消费。注意:concurrency = "4"属性,表示固定 4 个消费者;
*/
@RabbitHandler
@RabbitListener(queues = "simple.queue", concurrency = "4")
public void multiConsumer(String data) {
System.out.println("multiConsumer: " + data);
}
05、@RabbitListener+@RabbitHandler