消息没有声明content_type属性,导致获取数据时失败
生产端用PHP语言开发,没有声明属性的content_type为text/plain,那么AMQP代理在底层就会默认将其视为字节数组。
消费端是由Java进行开发,因为没有声明content_type,Java开发的应用程序框架可能就将这个payload视为字节数组去处理,显然就会出错了。因为之前的约定是string格式,而不是字节数组。
正确的做法应该在生产者投递消息的时候,加上 消息属性“content_type”,并声明为text/plain
$message = new AMQPMessage($this->body, ['content_type' => 'text/plain', 'delivery_mode' => 2]); $this->channel->basic_publish($message, $this->bindings[$this->action]['exchangeName']);
其实加上这个 'content_type' => 'text/plain'
,应该就是让PHP告诉rabbitmq,以 字符串
的格式去存储消息,这样Java端的底层框架才能将数据正确转换为有效的字符串去处理,否则默认当成 字节数组
处理。
(当然这个得看Java程序使用的框架,可能部分框架接口会把数据格式预处理成字符串,有些可能处理成字节数组,我猜最原始的形式也是字节数组)
可能很多时候会忽略掉这个content_type,只记得把消息定义成持久化。因为单纯考虑PHP生产,PHP消费的情况不需要处理,可能是PHP底层的框架就已经实现了(可能AMQP扩展包就实现把payload默认转为字符串,你也可以看到在MQ管控台里get message的时候,会有个“Encoding: auto string/base64”的字样)。
所以涉及多系统的开发的时候(尤其多种不同程序语言),务必定义 有效负载
的 content_type
属性。其实涉及数据通信交互的场景里,都需要声明这样的一种契约,养成一个良好的习惯。
在这里也了解一下有效负载。首先要知道AMQPMessage消息包括两部分,1消息属性 2有效负载。可类比http请求头和请求体理解。
列的是PHP版本的AMQP包定义属性名,其他程序语言可能定义不一样,但是在AMQP的范畴里是一致的)
'content_type' => 'shortstr', 'content_encoding' => 'shortstr', 'application_headers' => 'table_object', # 即web UI管控台里显示的header 'delivery_mode' => 'octet', 'priority' => 'octet', 'correlation_id' => 'shortstr', 'reply_to' => 'shortstr', 'expiration' => 'shortstr', 'message_id' => 'shortstr', 'timestamp' => 'timestamp', 'type' => 'shortstr', 'user_id' => 'shortstr', 'app_id' => 'shortstr', 'cluster_id' => 'shortstr',
(即web UI管控台里显示的payload),其实就是消息体的组成部分,但是在AMQP里面它不叫body,叫payload,但你可以理解为是消息体的意思。
AMQP代理将其视为不透明的字节数组(byte[]),也就是AMQP代理不会检查或者修改消息的有效负载。 AMQP消息可能只包含属性而没有有效负载,可能只有有效负载而没有属性,或者两者都没有,都是有可能的。 一般当没有设定content_type属性时,底层程序处理有效负载的默认类型应该就是字节数组(推断,没有真实测试验证)。 通常会使用序列化格式(如JSON,Thrift,Protocol Buffers和MessagePack)来序列化和结构化数据, 以便将其作为消息有效负载发布。在一般约定下,消息属性中的Content type和Content encoding一般可以表明其序列化的方式。 一般开发程序应用时会把生产者和消费者解耦开来,这里面可能牵涉到同一种程序语言和不同程序语言的问题。 有可能生产者是PHP开发,消费者程序由Java开发、Python开发等。这个时候声明消息的Content_type就尤为重要了。 这是一种契约,当发布消息没有对消息内容进行描述时,应用程序会倾向使用一种隐式契约去处理,这可能就会导致错误的产生。
https://www.jianshu.com/p/48c57d3a6acd https://juejin.im/post/5e3e1e54518825496452a31e https://blog.csdn.net/Sadlay/article/details/86716028?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
写的都是一些自己在开发过程遇到的问题,绝非官方确切解释,有不对的地方欢迎指正并讨论,互相学习互相进步,才是目的。