rabbitmq发送消息格式注意

事故缘由

消息没有声明content_type属性,致使获取数据时失败

生产端

生产端用PHP语言开发,没有声明属性的content_type为text/plain,那么AMQP代理在底层就会默认将其视为字节数组。

消费端

消费端是由Java进行开发,由于没有声明content_type,Java开发的应用程序框架可能就将这个payload视为字节数组去处理,显然就会出错了。由于以前的约定是string格式,而不是字节数组。

AMQPMessage1.png

正确的作法应该在生产者投递消息的时候,加上消息属性“content_type”,并声明为text/plainweb

$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程序使用的框架,可能部分框架接口会把数据格式预处理成字符串,有些可能处理成字节数组,我猜最原始的形式也是字节数组)app


总结经验

可能不少时候会忽略掉这个content_type,只记得把消息定义成持久化。由于单纯考虑PHP生产,PHP消费的状况不须要处理,多是PHP底层的框架就已经实现了(可能AMQP扩展包就实现把payload默认转为字符串,你也能够看到在MQ管控台里get message的时候,会有个“Encoding: auto string/base64”的字样)。框架

AMQPMessage2.png

因此涉及多系统的开发的时候(尤为多种不一样程序语言),务一定义有效负载content_type属性。其实涉及数据通讯交互的场景里,都须要声明这样的一种契约,养成一个良好的习惯。post


有效负载

在这里也了解一下有效负载。首先要知道AMQPMessage消息包括两部分,1消息属性 2有效负载。可类比http请求头和请求体理解。学习

1消息属性

列的是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',
2有效负载

(即web UI管控台里显示的payload),其实就是消息体的组成部分,可是在AMQP里面它不叫body,叫payload,但你能够理解为是消息体的意思。this

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

写在最后

写的都是一些本身在开发过程遇到的问题,绝非官方确切解释,有不对的地方欢迎指正并讨论,互相学习互相进步,才是目的。
相关文章
相关标签/搜索