[TOC] #### 1. 前言 --- 前面几讲我们一直在聊队列、生产者、消费者,这一讲我们把目光放到消息本身 我们已经知道消息长这样: ```php $message = new AMQPMessage(json_encode([ 'user_id' => 1, 'order_id' => 1001, ])); ``` 查看 `AMQPMessage` 类的构造函数,可以发现它是支持传入第二个参数的 body 里面是业务数据,但消息除了 body,还能携带一些属性信息,这些属性用于告诉 RabbitMQ「这条消息应该怎么处理」 ```php public function __construct($body = '', $properties = array()) { $this->setBody($body); if (!empty($properties) && is_array($properties)) { $this->properties = array_intersect_key($properties, self::$propertyDefinitions); } } ``` 生活中的例子:你寄快递,包裹里面是你要寄的东西(body),但包裹外面还要贴一张快递单 + 是普通件还是加急件 + 需不需要签收确认 + 超时几天自动退回 这些信息不是包裹本身,但快递公司需要它们来处理这个包裹,消息的属性就是「快递单」 没有属性,RabbitMQ 只知道「有条消息」,不知道「该怎么处理这条消息」 #### 2. 最常用的两个属性 --- delivery_mode(投递模式):告诉 RabbitMQ 这条消息需不需要持久化 ```php // 前面我们已经在做 “消息持久化” 的时候用过这个属性了 $message = new AMQPMessage(json_encode($data), [ 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT ]); ``` | 类的常量 | 值 | 含义 | | ------------ | ------------ | ------------ | | DELIVERY_MODE_NON_PERSISTENT | 1 | 非持久化(默认),存在内存里 | | DELIVERY_MODE_PERSISTENT | 2 | 持久化,写到磁盘上 | 上一讲我们说过,重要业务一定要设成持久化,否则 RabbitMQ 重启后消息会丢 content_type(内容类型) 告诉消费者消息体是什么格式: ```php $message = new AMQPMessage(json_encode($data), [ 'content_type' => 'application/json' ]); ``` 这不是强制的,RabbitMQ 不会检查你传的是不是真的 JSON,但它能帮助消费者知道该怎么解析消息 就像快递单上写着「易碎品」,快递员看到就知道要轻拿轻放 代码示例: ```php $data = ['user_id' => 1, 'order_id' => 1001]; $message = new AMQPMessage(json_encode($data), [ 'content_type' => 'application/json', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT, ]); $channel->basic_publish($message, '', 'order_queue'); ``` 实际开发中,这两个属性基本是标配,其它的属性根据业务需要选择性使用 #### 3. 还有哪些属性 --- 除了上面两个,RabbitMQ 还提供了很多其他属性,比如: + 优先级:高优先级的消息可以先被消费 + 过期时间:超过指定时间没被消费的消息自动删除 + 消息唯一标识:给每条消息一个 ID,方便追踪 + 请求关联ID:用于把请求和响应对应起来 + 时间戳:记录消息发送的时间 这些属性不是每条消息都要用,但在特定场景下很有用,比如优先级和过期时间,我们后面会有专门的章节来讲 现在只需要知道:消息不仅有 body,还可以携带很多额外信息,这些信息会影响 RabbitMQ 如何存储、路由和投递消息 #### 4. 消费者怎么读取属性 --- 消费者收到消息后,不只能读 body,也能读属性: ```php $callback = function ($msg) { // 读取 body $data = json_decode($msg->body, true); // 读取属性 echo "内容类型:{$msg->get('content_type')}\n"; // 消息处理完成 $msg->ack(); }; ``` #### 5. 本文小结 --- 消息除了业务数据(body),还能携带属性信息,属性就像快递单,告诉 RabbitMQ 这条消息应该怎么处理 最常用的两个属性: | 属性 | 作用 | | ------------ | ------------ | | delivery_mode | 是否持久化 | | content_type | 内容格式 | 其它属性(优先级、过期时间、消息ID等)在特定场景下使用,后面会单独讲解 记住一个认知:消息不只是数据,还有一层「元信息」在影响它的处理方式 到这里,Producer、Consumer、Queue、消息这四个核心概念我们都讲过了 下一讲开始,我们进入 RabbitMQ 最重要的一个组件:Exchange 交换机