zoukankan      html  css  js  c++  java
  • MSMQ实现自定义序列化存储

    MSMQ实现自定义序列化存储

    在使用MSMQ的时候一般只会使用默认的XML序列化来对消息进行存储,但XML存储的缺点是序列化体积相对比较大和效率上有点低.其实.net提供非常简单的方式让我们实现不同序列化方式来存储MSMQ信息,如json,protobuf等.为了能够让开发人员实现自定义序列化的消息存储,.NET提供了IMessageFormatter这样一个接口,只需要简单地实现这个接口就可以对MSMQ的消息进行处理.以下讲解如何实现json和protobuf的messageformater.

    IMessageFormatter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    // 摘要:
        //     从“消息队列”消息体序列化或反序列化对象。
        [TypeConverter(typeof(MessageFormatterConverter))]
        public interface IMessageFormatter : ICloneable
        {
            // 摘要:
            //     在类中实现时,确定格式化程序是否可以反序列化消息的内容。
            //
            // 参数:
            //   message:
            //     要检查的 System.Messaging.Message。
            //
            // 返回结果:
            //     如果格式化程序可以反序列化消息,则为 true;否则为 false。
            bool CanRead(Message message);
            //
            // 摘要:
            //     在类中实现时,读取给定消息中的内容并创建包含该消息中的数据的对象。
            //
            // 参数:
            //   message:
            //     The System.Messaging.Message to deserialize.
            //
            // 返回结果:
            //     反序列化的消息。
            object Read(Message message);
            //
            // 摘要:
            //     在类中实现时,将对象序列化到消息体中。
            //
            // 参数:
            //   message:
            //     System.Messaging.Message,它将包含序列化的对象。
            //
            //   obj:
            //     要序列化到消息中的对象。
            void Write(Message message, object obj);
        }

    接口非常简单,主要规范了MSMQ写入和读取的规则.

    Json Formater

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    public class JsonFormater<T> : IMessageFormatter
        {
     
            public bool CanRead(Message message)
            {
                return message.BodyStream != null && message.BodyStream.Length > 0;
            }
     
            [ThreadStatic]
            private static byte[] mBuffer;
     
            public object Read(Message message)
            {
                if(mBuffer== null)
                    mBuffer = new byte[4096];
                int count =(int)message.BodyStream.Length;
                message.BodyStream.Read(mBuffer, 0, count);
                return Newtonsoft.Json.JsonConvert.DeserializeObject(Encoding.UTF8.GetString(mBuffer, 0, count), typeof(T));
     
            }
     
            [System.ThreadStatic]
            private static System.IO.MemoryStream mStream;
     
            public void Write(Message message, object obj)
            {
                if (mStream == null)
                    mStream = new System.IO.MemoryStream(4096);
                mStream.Position = 0;
                mStream.SetLength(4095);
                string value = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
                int count = Encoding.UTF8.GetBytes(value, 0, value.Length, mStream.GetBuffer(), 0);
                mStream.SetLength(count);
                message.BodyStream = mStream;
            }
     
            public object Clone()
            {
                return this;
            }
        }

    Protobuf Formater

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class ProtobufFormater<T> : IMessageFormatter
        {
            public bool CanRead(Message message)
            {
                return message.BodyStream != null && message.BodyStream.Length > 0;
            }
     
            public object Read(Message message)
            {
                return ProtoBuf.Meta.RuntimeTypeModel.Default.Deserialize(message.BodyStream, null, typeof(T));
            }
     
            [System.ThreadStatic]
            private static System.IO.MemoryStream mStream ;
     
            public void Write(Message message, object obj)
            {
                if (mStream == null)
                    mStream = new System.IO.MemoryStream(4096);
                mStream.Position = 0;
                mStream.SetLength(0);
                ProtoBuf.Meta.RuntimeTypeModel.Default.Serialize(mStream, obj);
                message.BodyStream = mStream;
            }
     
            public object Clone()
            {
                return this;
            }
            
        }

    使用Formater

    使有自定义Formater比较简单,只需要指定MessageQueue的Formatter属性即可.

    1
    2
    MessageQueue queue = new MessageQueue(@".\private$\Test");
                queue.Formatter = new JsonFormater<User>();

    简单的测性能测试

    针对json,protobuf这两种自定义序列化和默认的XML序列化性能上有多大差异,各自进行100000条写入和读取的耗时情况.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    queue.Send(user);
                }
                sw.Stop();
                Console.WriteLine("MSMQ send xml formater:" + sw.Elapsed.TotalMilliseconds + "ms");
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    User result = (User)queue.Receive().Body;
                }
                sw.Stop();
                Console.WriteLine("MSMQ receive xml formater:" + sw.Elapsed.TotalMilliseconds + "ms");
     
                queue.Formatter = new JsonFormater<User>();
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    queue.Send(user);
                }
                sw.Stop();
                Console.WriteLine("MSMQ send Json formater:" + sw.Elapsed.TotalMilliseconds + "ms");
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    User result = (User)queue.Receive().Body;
                }
                sw.Stop();
                Console.WriteLine("MSMQ receive json formater:" + sw.Elapsed.TotalMilliseconds + "ms");
     
                queue.Formatter = new ProtobufFormater<User>();
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    queue.Send(user);
                }
                sw.Stop();
                Console.WriteLine("MSMQ send Protobuf formater:" + sw.Elapsed.TotalMilliseconds+"ms");
                sw.Reset();
                sw.Start();
                for (int i = 0; i < 100000; i++)
                {
                    User result = (User)queue.Receive().Body;
                }
                sw.Stop();
                Console.WriteLine("MSMQ receive Protobuf formater:" + sw.Elapsed.TotalMilliseconds + "ms");

    测试结果

    从测试来看还是protobuf效率上占优点:)

  • 相关阅读:
    一次心惊肉跳的服务器误删文件的恢复过程
    ThreadPoolExecutor使用详解
    Springboot学习笔记(一)-线程池的简化及使用
    springboot之异步调用@Async
    CentOS 7添加开机启动服务/脚本
    三分钟在任何电脑上使用 chrome os
    Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Nacos
    Nacos部署中的一些常见问题汇总
    Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo
    Spring Cloud Alibaba 新版本发布:众多期待内容整合打包加入!
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3110661.html
Copyright © 2011-2022 走看看