• Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证


    上一篇:Window Azure ServiceBus Messaging消息队列技术系列2-编程SDK入门  http://www.cnblogs.com/tianqing/p/5944573.html

    介绍了Azure Service Bus的编程SDK(主要的编程接口)

    本文中我们以实际的使用场景来说明Azure Messaging是否支持以及如何编码实现:消息的收发顺序保证

    消息的收发在实际业务中往往是有顺序的:发送时1-2-3-4-5,接收时也必须是1-2-3-4-5,即FIFO特性。

    在本文的Demo中,我们模拟销售订单消息队列异步处理场景,消息体是一条SalesOrder,顺序发送,顺序接收。

    1. 我们还是使用上篇博客中在Windows Azure的Portal上建立好的NameSpaceservicebustest

    销售订单队列名称:OrderQueue

    2.简单封装一个Service Bus的工具类:ServiceBusUtils: 用于创建队列、删除队列、创建QueueClient、创建BrokerdMessage

    using Microsoft.ServiceBus;
    using Microsoft.ServiceBus.Messaging;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace AzureMessaging.FIFO
    {
        /// <summary>
        /// ServiceBus工具类
        /// </summary>
        class ServiceBusUtils
        {
            //Namespace名称
            private static readonly string namespaceName = "servicebustest";
    
            /// <summary>
            /// 创建队列
            /// </summary>
            /// <param name="queueName">队列名称</param>
            /// <param name="isSession">是否支持会话</param>
            public void CreateQueue(string queueName, bool isSession = true)
            {
                var namespaceClient = NamespaceManager.Create();
                if (namespaceClient.QueueExists(queueName))
                {
                    namespaceClient.DeleteQueue(queueName);
                }
    
                var queue = new QueueDescription(queueName) { RequiresSession = isSession };
                namespaceClient.CreateQueue(queue);
            }
    
            /// <summary>
            /// 删除队列
            /// </summary>
            /// <param name="queueName">队列名称</param>        
            public void DeleteQueue(string queueName)
            {
                var namespaceClient = NamespaceManager.Create();
                if (namespaceClient.QueueExists(queueName))
                {
                    namespaceClient.DeleteQueue(queueName);
                }
            }
    
    
            /// <summary>
            /// 创建队列客户端
            /// </summary>
            /// <returns>队列客户端</returns>
            public QueueClient GetQueueClient(string queueName, bool isSession = false, ReceiveMode mode = ReceiveMode.ReceiveAndDelete)
            {
                return QueueClient.Create(queueName, mode);
            }
            /// <summary>
            /// 创建队列客户端
            /// </summary>
            /// <returns>队列客户端</returns>
            public QueueClient GetReceiveQueueClient(string queueName, ReceiveMode mode = ReceiveMode.PeekLock)
            {
                var namespaceClient = NamespaceManager.Create();
                return QueueClient.Create(queueName, mode);
            }
    
            /// <summary>
            /// 构造消息
            /// </summary>
            /// <param name="serializableObject">可序列化的对象</param>
            /// <returns>消息</returns>
            public BrokeredMessage Create(Object serializableObject)
            {
                var serializer = new DataContractSerializer(serializableObject.GetType(), 
                    new DataContractSerializerSettings() { IgnoreExtensionDataObject = true, PreserveObjectReferences = false });
                var message = new BrokeredMessage(serializableObject);
                message.Properties.Add("Type", serializableObject.GetType().ToString());
    
                return message;
            }
        }
    }

    2. 示例SalesOrder实体类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace AzureMessaging.FIFO
    {
        /// <summary>
        /// 销售订单类
        /// </summary>
        public class SalesOrder
        {
            /// <summary>
            /// 订单ID
            /// </summary>
            public string OrderID { get; set; }
    
            /// <summary>
            /// 订单编号
            /// </summary>
            public string Code { get; set; }
    
            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime CreateTime { get; set; }
    
            /// <summary>
            /// 总价格
            /// </summary>
            public Decimal TotalPrice { get; set; }
    
            /// <summary>
            /// 产品ID
            /// </summary>
            public int ProductID { get; set; }
        }
    }

    3. 消息顺序发送

    向OrderQueue发送10条消息订单消息,输出每条消息的顺序号以及MessageID

    private static readonly string queueName = "OrderQueue";
        /// <summary>
            /// 发送消息
            /// </summary>
            private static void MessageSend()
            {
                var sbUtils = new ServiceBusUtils();
    
                //创建队列
                sbUtils.CreateQueue(queueName, false);
    
                //顺序发送消息到OrderQueue
                var queueSendClient = sbUtils.GetQueueClient(queueName);
                for (int i = 0; i < 10; i++)
                {
                    var order = new SalesOrder() { OrderID = i.ToString(), Code = "SalesOrder_" + i, CreateTime = DateTime.Now, ProductID = 17967, TotalPrice = new decimal(19999) };
                    var message = sbUtils.Create(order);
                    queueSendClient.Send(message);
                    Console.WriteLine(string.Format("Send {0} Message: {1}", i, message.MessageId));
                }
    
                Console.WriteLine("Send Completed!");
            }

    程序输出:

    4. 消息顺序接收

    消费OrderQueue中的消息,验证消息的接收顺序

    private static readonly string queueName = "OrderQueue";
     /// <summary>
            /// 接收消息
            /// </summary>
            private static void MessageReceive()
            {
                int index = 0;
                BrokeredMessage msg = null;
                var sbUtils = new ServiceBusUtils();
                var queueReveiveClient = sbUtils.GetReceiveQueueClient(queueName, ReceiveMode.ReceiveAndDelete);
                while ((msg = queueReveiveClient.Receive(TimeSpan.FromMilliseconds(3))) != null)
                {
                    Console.WriteLine(string.Format("Received {0} Message: {1}", index, msg.MessageId));
                    index++;
                }
    
                ////删除队列
                //sbUtils.DeleteQueue(queueName);
    
                Console.WriteLine("Receive Completed!");
            }

    程序输出:

    可以看出,Azure Messaging中ServiceBus对消息的收发是有顺序保证的。

    下一篇我们继续其他特性的验证和介绍。

    周国庆

    2017/3/9

  • 相关阅读:
    SQLServer数据库中开启CDC导致“事务日志空间被占满,原因为REPLICATION”的原因分析和解决办法
    译:SQL Server的Missing index DMV的 bug可能会使你失去理智---慎重看待缺失索引DMV中的信息
    SQLServer中间接实现函数索引或者Hash索引
    MySQL缓存分类和配置
    MySQL系统变量配置基础
    MySQL索引统计信息更新相关的参数
    Sql Server优化---统计信息维护策略
    SQL Server 用角色(Role)管理数据库权限
    sp_executesql 或者 EXECUTE 执行动态sql的权限问题
    关于T-SQL重编译那点事,内联函数和表值函数在编译生成执行计划的区别
  • 原文地址:https://www.cnblogs.com/tianqing/p/6527106.html
Copyright © 2020-2023  润新知