无法 JSON 解析从 Node.js 应用程序中的 Azure 服务总线收到的消息

Can't JSON parse message received from Azure Service Bus in Node.js app

这是我的 JS 代码,用于从 Azure 服务总线接收消息

function receiveMessage(serviceBusTopic, serviceBusSubscriber, callback) {
  serviceBus.receiveSubscriptionMessage(serviceBusTopic, serviceBusSubscriber,
{ isPeekLock: true }, function (error, lockedMessage) {

if (!error) {
  try {
    const receivedMessage = JSON.parse(lockedMessage.body);
    console.log('receivedMessage', receivedMessage);
    if (!_.isEqual(receivedMessage.Type, messageType.USERPROFILES_USER_UPDATED)) {
      return;
    }
    //Message received and locked
    callback(receivedMessage);
    serviceBus.deleteMessage(lockedMessage, function (deleteError) {
      if (!deleteError) {
        // Message deleted
        console.log('message has been deleted.');
      }
    });
  }
  catch (error) {
    console.log('Start debugging');
    console.log(lockedMessage.body);
  }

当我收到一条消息时,它的编码很奇怪,JSON.parse 引发异常。

lockedMessage 输出为:

{ body: '@\fbase64Binary\b3http://schemas.microsoft.com/2003/10/Serialization/�s\u0002{"Type":"SomeEvent"�\u0001}',
   brokerProperties: 
{ DeliveryCount: 9,
  EnqueuedSequenceNumber: 0,
  EnqueuedTimeUtc: 'Thu, 16 Nov 2017 23:50:16 GMT',
  LockToken: '6e3e311f-0fe9-4366-844d-18046fd000db',
  LockedUntilUtc: 'Fri, 17 Nov 2017 00:10:46 GMT',
  MessageId: 'nil',
  PartitionKey: '1d84084f-65af-4a33-bb30-62d97d85557d',
  SequenceNumber: 61643019899633670,
  SessionId: '1d84084f-65af-4a33-bb30-62d97d85557d',
  State: 'Active',
  TimeToLive: 1566804.069 },
   location: '',
   contentType: 'application/xml; charset=utf-8',
   customProperties: { 'strict-transport-security': NaN, connection: NaN } }

消息来自 .NET Core 服务,该服务使用以下代码发送:

            var payload = JsonConvert.SerializeObject(SomeEvent);
            var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
            serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
            topicClient.SendAsync(serviceBusMessage).Wait();

为什么 Node.js 无法解析邮件?另一个 .NET 应用程序可以毫无问题地接收相同的消息。

为避免这种情况,您需要在从 .NET Core 服务发送消息时将 ContentType 设置为 text/plain。所以它应该是这样的:

var payload = JsonConvert.SerializeObject(SomeEvent);
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload))
{
    ContentType = "text/plain"
};
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
topicClient.SendAsync(serviceBusMessage).Wait();

在此 article 中,他们解释了 .NET 的问题和解决方案。

更新:

经过一番探索,当我使用 .NET Core 或 .NET 通过标准库 Microsoft.Azure.ServiceBus 发送消息时,无论是否指定 ContentType 都不会发生这种情况。

这是我发送消息的 C# 代码:

class Program
{
    static void Main(string[] args)
    {
        string connectionString = "Endpoint=sb://...";
        var client = new TopicClient(connectionString, "MyTopic");
        var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
        var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
        serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");

        client.SendAsync(serviceBusMessage).Wait();

    }

    private class DemoMessage
    {
        public DemoMessage()
        {
        }

        public string Title { get; set; }
    }
} 

这是我的 Node.js 接收消息的代码:

var azure = require('azure');

var serviceBusService = azure.createServiceBusService("Endpoint=sb://...");

serviceBusService.receiveSubscriptionMessage('MyTopic', 'sub1', { isPeekLock: true }, function(error, lockedMessage) {
    if(!error) {

        console.log(lockedMessage);

        serviceBusService.deleteMessage(lockedMessage, function (deleteError){
            if(!deleteError){
                // Message deleted
                console.log('message has been deleted.');
            }
        })
    }
});   

lockedMessage 输出为:


这仅在我使用 .NET 和 SDK WindowsAzure.ServiceBus 时发生,代码如下:

class Program
{
    static void Main(string[] args)
    {
        string connectionString = "Endpoint=sb://...";
        var client = TopicClient.CreateFromConnectionString(connectionString, "MyTopic");
        var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
        var serviceBusMessage = new BrokeredMessage(Encoding.UTF8.GetBytes(payload));
        serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");

        client.Send(serviceBusMessage);

    }

    private class DemoMessage
    {
        public DemoMessage()
        {
        }

        public string Title { get; set; }
    }
}

现在,lockedMessage 输出是:

所以,我认为您收到的消息是从另一个 .NET 客户端发送的,我建议您在 Node.js.

中测试之前清除主题中的所有消息

我也运行关注这个问题。如果您使用的是流分析,则其兼容性级别可能是导致此问题的原因。流分析兼容级别 1.0 使用 XML 序列化程序生成您看到的 XML 标记。兼容级别 1.1 "fixes" 这个问题。

在这里查看我之前的回答: