1.声明
当前内容为本人学习和复习之用,当前内容包括消息属性和负载的介绍,主要用于理解消息中的组成部分
2.官方的Message Attributes and Payload介绍
-
Messages in the AMQP 0-9-1 model have attributes. Some attributes are so common that the AMQP 0-9-1 specification defines them and application developers do not have to think about the exact attribute name. Some examples are
1.1 Content type
1.2. Content encoding
1.3 Routing key
1.4Delivery mode (persistent or not)
1.5 Message priority
1.6 Message publishing timestamp
1.7 Expiration period
1.8 Publisher application id
AMQP 0-9-1 模型中的消息具有属性。一些属性是常见的,AMQP在规范中定义了他们,应用开发人员并不需要考虑确切的属性名称,例如他们是:
1.上下文类型(类似Http中的Content-type)
2.上下文编码(类似Http中的Content-encoding)
3.路由键
4.投放模式(是否持久化)
5.消息优先级
6.消息投放的时间戳
7.有效期
8.投放消息的程序id
从这里我们看到了上下文类型和上下文编码,这个肯定就是Http传输过程需要使用的
投放模式,这个肯定就是消息持久化的设定(一般要保证消息的传递必须开启持久化、并且队列持久化、Exchange持久化)
Some attributes are used by AMQP brokers, but most are open to interpretation by applications that receive them. Some attributes are optional and known as headers. They are similar to X-Headers in HTTP. Message attributes are set when a message is published.
一些属性是AMQP代理者使用的,但是大多数都是由接收他们的程序来解释的。一些属性是可以选的就像headers.他们通常预HTTP上面的X-Headers类似。消息属性是在消息被推送的时候设置的
就是说,消息是生产者发送的,并且可以在生产者设置,但是有些属性是发送后就自动生成的
Messages also have a payload (the data that they carry), which AMQP brokers treat as an opaque byte array. The broker will not inspect or modify the payload. It is possible for messages to contain only attributes and no payload. It is common to use serialisation formats like JSON, Thrift, Protocol Buffers and MessagePack to serialize structured data in order to publish it as the message payload. Protocol peers typically use the “content-type” and “content-encoding” fields to communicate this information, but this is by convention only.
消息也有payload(通常他们被称为数据),在AMQP代理中是一个byte数组.代理者知识接收但是不能修改这个数据
。消息可能只有一些属性可以没有数据。数据通常都是被序列化为JSON、Thrift、协议流和消息包,通过序列化数据结构。协议通过content-type和content-encoding字段来传递消息,这个只是约定
Messages may be published as persistent, which makes the broker persist them to disk. If the server is restarted the system ensures that received persistent messages are not lost. Simply publishing a message to a durable exchange or the fact that the queue(s) it is routed to are durable doesn’t make a message persistent: it all depends on persistence mode of the message itself. Publishing messages as persistent affects performance (just like with data stores, durability comes at a certain cost in performance).
消息能被发布为持久化,代理将持久化他们到磁盘,如果服务器重启,这个协同将会重新接收消息并不会丢失。简单的将消息推送到持久化exchange或者在一个持久化队列中,那么这个消息不会是持久化的。他全部依赖消息设定的模式。持久化消息通常消耗性能(就像数据存储一样会消耗性能)
从这里发现,如果只是设定exchange和queue持久化,但是发布消息的时候没有设定消息持久化,那么消息将在重启后消失,如果需要持久化消息必须设定模式(默认直接发送不会持久化消息)
3.分析如何使用消息持久化
通过查看当前的官方文档查看消息属性:消息属性
分析以前调用的发送消息的方法:basicPublish
void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;
发现了BasicProperties props,说明这些配置必定在props中,只要在发送的时候在props中将Delivery mode设定为1为持久化、设定为2表示瞬时
通过查看BasicProperties源码发现这个实际上就是需要通过Builder方式创建
4.开始测试持久化消息和瞬时消息
开启消息持久化的配置,直接为当前的RabbitMqUtils中添加该方法
创建枚举表示消息的类型
public enum MessageType {
PERSISTENT(2), TRANSIENT(1);
private MessageType(int value) {
this.value = value;
}
private final int value;
public int getValue() {
return this.value;
}
}
public boolean send(final String exchange/* , String queue */, final String routingKey, boolean durable,
BasicProperties props, final String msg) {
try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { //
// channel.queueDeclare(queue, durable, false, false, null);
channel.basicPublish(exchange, routingKey, props, msg.getBytes());
return true;
} catch (IOException | TimeoutException e) {
e.printStackTrace();
return false;
}
}
1.创建发送瞬时消息的生产者
@Test
public void sendNoDurableMsg() {
RabbitMqUtils mqUtils = new RabbitMqUtils();
BasicProperties.Builder builder = new BasicProperties.Builder();
builder.deliveryMode(MessageType.TRANSIENT.getValue());
BasicProperties props = builder.build();
mqUtils.send("test", "", true, props, "你好世界===>瞬时消息");
}
2.创建发送持久化消息的生产者
public static void main(String[] args) {
RabbitMqUtils mqUtils = new RabbitMqUtils();
BasicProperties.Builder builder = new BasicProperties.Builder();
builder.deliveryMode(MessageType.PERSISTENT.getValue());
BasicProperties props = builder.build();
mqUtils.send("test", "", true, props, "你好世界===>持久化消息");
}
3.常见消息消费者
public class PrefetchingMessages3Test {
public static void main(String[] args) throws Exception {
RabbitMqUtils mqUtils = new RabbitMqUtils();
Connection connection = mqUtils.getConnection();
Channel channel = connection.createChannel();
// 开启自动确认
channel.basicConsume("hello", false, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
// 限定消费的条数
System.out.println("消费者3开始处理消息====>" + new String(body, "utf-8"));
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
}
}
4.启动两个生产者观察ui界面
发现有两个消息,一个持久化
5.重启RabbitMQ查看ui界面
发现只有一个数据了
6.启动消费者
消费成功
5.总结
1.发送消息的时候如果想要持久化必须开启deliveryMode=2
,默认消息就是瞬时的
2.在发送消息到持久化exchange和持久化queue的时候,需要小心消息丢失的问题
3.消息在发送的时候会自动打上一些属性,所谓的负载(其实就是传递的数据)
以上纯属个人见解,如有问题请联系本人!