【问题标题】:Azure ServiceBus Message Serialization/DeserializationAzure ServiceBus 消息序列化/反序列化
【发布时间】:2018-11-15 13:25:05
【问题描述】:

我正在使用 .NET Core 应用程序通过 Azure 服务总线队列发送对象,并让 Web 作业(.NET Core 也一样)接收它。

我的问题是如何序列化/反序列化以发送/接收对象?

我发现很多引用旧的 BroakerMessage.GetBody() 来接收消息,但没有引用新的 .NET Core 方法。请指教,谢谢。

发件人代码:

using Microsoft.Azure.ServiceBus;

MyClass object = new MyClass();
var message = new Message(object);
await queueClient.SendAsync(message);

收货人代码:

using Microsoft.Azure.ServiceBus;

public void ProcessQueueMessage([ServiceBusTrigger("queue")] Message message, TextWriter log)
{
}

【问题讨论】:

    标签: c# azure .net-core azureservicebus azure-webjobs


    【解决方案1】:

    可以使用 JSON 序列化来传输这些对象/实体。

    假设以下类是对象实例将被发送到 Azure 服务总线队列/从 Azure 服务总线队列接收的类型:

    public class Customer{ public string Name { get; set; } public string Email { get; set; } }
    

    --- 发送---

    在下面找到发送客户对象实例的示例代码(.NET Core 2.0 控制台应用程序):

    QueueClient queueClient = new QueueClient(connectionString, queueName);
    string messageBody = JsonConvert.SerializeObject(obj);
    Message message = new Message(Encoding.UTF8.GetBytes(messageBody))
    {
        SessionId = sessionId
    };
    await queueClient.SendAsync(message);
    

    --- 接收 ---

    在下面找到一个 Azure 函数(服务总线队列触发器/.NET Standard 2.0)示例代码来接收消息并对其进行反序列化:

    [FunctionName("ServiceBusQueueFunction")]
    public static void Run([ServiceBusTrigger("taskqueue", Connection = "ServiceBusConnectionString")] Message message, TraceWriter log)
    {
        Customer customer = JsonConvert.DeserializeObject<Customer>(Encoding.UTF8.GetString(message.Body));
    }
    

    针对上述示例使用/测试了以下 NuGet 包:

    • Microsoft.Azure.ServiceBus(版本 3.0.2)。
    • Newtonsoft.Json(版本 11.0.2)。

    考虑阅读:在下面找到 JSON.NET 的性能提示文章: https://www.newtonsoft.com/json/help/html/Performance.htm


    设计原理:在最新的 Microsoft.Azure.ServiceBus 中删除了内置 POCO 序列化支持。这是因为“虽然这种隐藏的序列化魔法很方便,但应用程序应该明确控制对象序列化并将其对象图转换为流,然后再将它们包含到消息中,并在接收端执行相反的操作。这会产生可互操作的结果。”

    https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messages-payloads

    【讨论】:

    • 非常感谢,你是救命稻草,为此我被困了几个小时
    • 你真的测试过这个吗? Deserialize 对我不起作用,因为我的 message.Body 有一堆不是 json 的废话。这是我的消息创建代码: var queueBody = new QueueBody { Name = $"JSmith{i}" };字符串 messageBody = JsonConvert.SerializeObject(queueBody); var message = new Message { Body = Encoding.UTF8.GetBytes(messageBody), ContentType = "application/json" };
    • 但是如果接收者不知道消息是Customer,那么可以从哪里获取消息类型以便动态决定反序列化到哪个类型?
    • 对我也不起作用。我在接收文本的开头得到 @\fbase64Binary\b3http://schemas.microsoft.com/2003/10/Serialization/�\u0002\u0001{ 并在此行失败:JsonConvert.DeserializeObject(body) ;错误“解析值时遇到意外字符:@。”
    【解决方案2】:

    如何序列化/反序列化以发送/接收对象?

    请参考demo代码一击:

    发送消息:

    var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(obj));
    await  queueClient.SendAsync(new Message { Body = body, ContentType = "text/plain" });
    

    在 .net 核心 WebJob 中

    var body = Encoding.UTF8.GetString(message.Body);
    var obj = JsonConvert.DeserializeObject<T>(body);
    

    测试结果:

    【讨论】:

    • 反序列化前有什么办法知道消息类型吗?
    【解决方案3】:

    这些都不适合我,因为:

    当我们尝试将消息正文解析为 JSON 时出现异常,因为我们收到的消息正文是

    "@\u0006string\b3http://schemas.microsoft.com/2003/10/Serialization/?\u000b{ \"a\": \"1\"}"
    

    这是因为“代理消息通过使用带有二进制 XmlDictionaryWriter 的 DataContractSerializer 从给定对象初始化 BrokeredMessage 类的新实例。”

    参考:https://www.bfcamara.com/post/84113031238/send-a-message-to-an-azure-service-bus-queue-with

    所以我改用这篇博文:https://abhishekrlal.com/2012/03/30/formatting-the-content-for-service-bus-messages/

    示例 1:使用字符串

    使用字符串和默认(DataContract + Binary)序列化程序创建 BrokeredMessage 时:

    BrokeredMessage stringDefaultMessage = new BrokeredMessage("default string");
    

    您可以通过以下方式收到此消息:

    string s = receiveMessage.GetBody<string>();
    

    【讨论】:

      猜你喜欢
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 1970-01-01
      • 2012-05-16
      • 2017-01-16
      相关资源
      最近更新 更多