Java 互操作性Azure服务总线消息队列消息

Java 互操作性Azure服务总线消息队列消息,java,node.js,azure,message-queue,Java,Node.js,Azure,Message Queue,我有一个Java应用程序和一个NodeJS应用程序,它们都使用一个Azure服务总线消息队列 我在我的客户身上看到了一些奇怪的效果,如下所示 JAVA消息生成器(根据Azure JMS教程使用QPID库): 输出: 已发送JMSMessageID=ID:2414932965987073843的消息 NODEJS消息使用者: serviceBus.receiveQueueMessage(queue, {timeoutIntervalInS: timeOut, isReceiveAndDelete:

我有一个Java应用程序和一个NodeJS应用程序,它们都使用一个Azure服务总线消息队列

我在我的客户身上看到了一些奇怪的效果,如下所示

JAVA消息生成器(根据Azure JMS教程使用QPID库):

输出: 已发送JMSMessageID=ID:2414932965987073843的消息

NODEJS消息使用者:

serviceBus.receiveQueueMessage(queue, {timeoutIntervalInS: timeOut, isReceiveAndDelete: true}, function(err, message) {
if(message !==null)console.log(util.inspect(message, {showHidden: false, depth: null}));
});
输出:

{ body: '@\u0006string\b3http://schemas.microsoft.com/2003/10/Serialization/�\u001aTest AMQP message from JMS',
brokerProperties:
{ DeliveryCount: 1,
EnqueuedSequenceNumber: 5000004,
EnqueuedTimeUtc: 'Wed, 04 Nov 2015 21:28:21 GMT',
MessageId: '2414932965987073843',
PartitionKey: '89',
SequenceNumber: 59672695067659070,
State: 'Active',
TimeToLive: 1209600,
To: 'moequeue' },
contentType: 'application/xml; charset=utf-8' }
如果将其与通过serviceBus.sendQueueMessage()插入队列的消息进行比较,则属性如下所示:

{ body: 'test message',
brokerProperties:
{ DeliveryCount: 1,
EnqueuedSequenceNumber: 0,
EnqueuedTimeUtc: 'Wed, 04 Nov 2015 21:44:03 GMT',
MessageId: 'bc0a3d4f-15ba-434f-9fb0-1a3789885f8c',
PartitionKey: '734',
SequenceNumber: 37436171906517256,
State: 'Active',
TimeToLive: 1209600 },
contentType: 'text/plain',
customProperties:
{ message_number: 0,
sent_date: Wed Nov 04 2015 21:44:03 GMT+0000 (UTC) } }
因此,内容类型一开始就不同——为什么然后,第一条消息有效负载正文中的奇怪垃圾从何而来:@\u0006string\b3http://schemas.microsoft.com/2003/10/Serialization/�\u001a 这是序列化的结果吗?如何缓解这种情况

在此处也可以找到代码:
Azure服务总线支持两种不同的协议:AMQP和HTTP。使用qpid libs的Java/JMS正在使用ServiceBus的AMQP协议。但是,ServiceBus REST API包装在NodeJS-thur HTTP协议中

有关服务总线中AMQP支持的详细信息,请参阅

关于ServiceBus的其余API,请参阅

AMQP是一种二进制应用层协议,旨在高效 支持多种消息传递应用程序和通信 模式

但是HTTP是一种文本协议

消息格式如下所示,请参阅ARTIFACT的
消息格式
。可以参考AMQP规范

因此,用Java或NodeJS发送的消息被序列化为不同的结果

AMQP正文内容中格式化的内容
\uxxx
是Unicode字符

Unicode字符
\u0006
是确认控制字符,请参阅了解它

Unicode字符
\u001a
是替代控制字符,请参阅


它们限制了消息头中元数据的开始和结束。

我们遇到了完全相同的问题,尽管在使用基于Camel的生产者的更复杂的示例中遇到了同样的问题。由于环境的变化,我们开始遇到这些问题

这里的问题是REST服务在对节点客户端的HTTP响应进行编码时如何解释JMS消息

我们发现,出于某些原因(不完全清楚),JmsTextmessage被假定为“application/xml”类型,并且内容将被转发。因此,您在示例中获得了输出

如果改为使用JmsByteMessage,则内容将被解释为“应用程序/八位字节流”,并且在传输过程中不会损坏

因此,请尝试以下几点:

BytesMessage message = sendSession.createBytesMessage();
String body = "Test AMQP message from JMS";
message.writeBytes(body.getBytes(StandardCharsets.UTF_8));
sender.send(message);

我们使用它来传输要由Node.js客户端解释的JSON编码的数据。

我也遇到了同样的问题,消息体的前缀是“@\u0006string\b3”http://schemas.microsoft.com/2003/10/Serialization/\u0001”

我使用Nodejs和azure物联网设备mqttazure物联网设备包向物联网中心发送消息。我使用流分析作业从IoT hub接收消息并将其发布到队列。我使用Nodejs和amqp10包从队列接收事件

问题不是由我发送或接收消息的方式引起的。相反,问题在于流分析兼容性级别!兼容性级别1.0(至少在部署时是默认级别)使用将消息序列化为XML流的!Microsoft使用兼容级别1.1更改(修复)了此问题。因此,您可能只需要将流分析作业的兼容性级别(配置->兼容性级别)更改为1.1


请参阅::

了解,那么是否有一种方法可以“安全地”反序列化节点中的这些消息?我认为在所有客户机上都坚持相同的协议是一个好主意,但是现实可能不同,负载仍然需要可交换。@user3506080在发送方和接收方中使用不同的协议不是一个好主意。但是我认为如果真的有必要,你可以通过用特殊字符分割内容来安全地获得正确的信息。虽然信息在技术上是正确的,但它完全是错误的。AMQP是一种二进制传输协议,根本不对实际消息进行任何编码。消息的编码是什么。如果您将消息的类型更改为字节消息(JmsByteMessage),REST服务将把编码解释为“应用程序/八位字节流”,而不是“应用程序/xml”,并且您的消息在节点中是可读的。我理解这是什么意思,但是,它没有说明任何明确的解决方案。我的看法是,我们必须从u006删除到u001,然后再删除JSON.parse。是否有一个库可以为我们做到这一点(即使它很简单,还是坚持标准为好)?
                                                     Bare Message
                                                            |
                                      .---------------------+--------------------.
                                      |                                          |
 +--------+-------------+-------------+------------+--------------+--------------+--------+
 | header | delivery-   | message-    | properties | application- | application- | footer |
 |        | annotations | annotations |            | properties   | data         |        |
 +--------+-------------+-------------+------------+--------------+--------------+--------+
 |                                                                                        |
 '-------------------------------------------+--------------------------------------------'
                                             |
                                      Annotated Message
BytesMessage message = sendSession.createBytesMessage();
String body = "Test AMQP message from JMS";
message.writeBytes(body.getBytes(StandardCharsets.UTF_8));
sender.send(message);