Avro(Microsoft)缺少派生类型成员的序列化

时间:2015-04-03 19:31:21

标签: avro

我正在评估微软实施Avro的性能,起初我认为我的性能非常出色,直到我意识到它只是没有序列化整个消息; - )

在下文中,有一个简单的消息层次结构,用[DataContract](基础和两个派生类型)修饰。所有成员都使用[DataMember]属性进行修饰。我从基本消息类型创建一个序列化程序并序列化派生消息列表,但它似乎只序列化/反序列化基类成员。结果中缺少所有派生的消息成员。

我错过了什么吗?我的应用程序将需要混合消息类型。

FWIW我没有在二进制文件中看到第二个派生类型的任何字符串,所以我怀疑派生类型成员没有被序列化。

Thanks, Greg


class Program
{
    [DataContract(Name = "SideType", Namespace = "AvroMessage")]
    public enum EventType
    {
        Unknown = 0,
        One = 1,
        Two = 2
    }

    [DataContract(Name = "MessageBase", Namespace = "AvroMessage")]
    public class MessageBase
    {
        [DataMember(Name = "Subtype")]
        public string Subtype;

        [DataMember(Name = "Timestamp")]
        public DateTime Timestamp;

        [DataMember(Name = "GroupName")]
        public string GroupName;

        public override bool Equals(object obj)
        {
            MessageBase other = obj as MessageBase;
            if (other == null) return false;

            return Subtype == other.Subtype &&
                   Timestamp == other.Timestamp &&
                   GroupName == other.GroupName;
        }
    }

    [DataContract(Name = "SubMessage1", Namespace = "AvroMessage")]
    public class SubMessage1 : MessageBase
    {
        [DataMember(Name = "Volume")]
        public int Volume;

        [DataMember(Name = "Count")]
        public int Count;

        [DataMember(Name = "DetectedSide")]
        public EventType Event;

        public override bool Equals(object obj)
        {
            SubMessage1 other = obj as SubMessage1;
            if (other == null) return false;

            return Subtype == other.Subtype &&
                   Timestamp == other.Timestamp &&
                   GroupName == other.GroupName &&
                   Event == other.Event &&
                   Volume == other.Volume &&
                   Count == other.Count;
        }
    }

    [DataContract(Name = "SubMessage2", Namespace = "AvroMessage")]
    public class SubMessage2 : MessageBase
    {
        [DataMember(Name = "Name1")]
        public string Name1;

        [DataMember(Name = "Volume1")]
        public int Volume1;

        [DataMember(Name = "Name2")]
        public string Name2;

        [DataMember(Name = "Volume2")]
        public int Volume2;

        [DataMember(Name = "PriceMove")]
        public double PriceMove;

        public override bool Equals(object obj)
        {
            SubMessage2 other = obj as SubMessage2;
            if (other == null) return false;

            return Subtype == other.Subtype &&
                   Timestamp == other.Timestamp &&
                   GroupName == other.GroupName &&
                   Volume1 == other.Volume1 &&
                   Name1 == other.Name1 &&
                   Volume2 == other.Volume2 &&
                   Name2 == other.Name2 &&
                   PriceMove == other.PriceMove;
        }
    }

    public class MessageFactory
    {
        public static IEnumerable<MessageBase> CreateMessages(int number)
        {
            Random ran = new Random();

            List<MessageBase> retval = new List<MessageBase>();
            for (int i = 0; i < number; i++)
            {
                if (ran.Next(2) == 0)
                {
                    SubMessage1 sub1 = new SubMessage1();
                    sub1.Timestamp = DateTime.Now;
                    sub1.GroupName = "Group" + DateTime.Now.Millisecond.ToString();
                    sub1.Subtype = "SubMessag1";
                    sub1.Volume = ran.Next(10000);
                    sub1.Count = ran.Next(100);
                    if (ran.Next(2) == 0)
                    {
                        sub1.Event = EventType.One;
                    }
                    else
                    {
                        sub1.Event = EventType.Two;
                    }
                    retval.Add(sub1);
                }
                else
                {
                    SubMessage2 sub2 = new SubMessage2();
                    sub2.Timestamp = DateTime.Now;
                    sub2.GroupName = "Group" + DateTime.Now.Millisecond.ToString();
                    sub2.Subtype = "SubMessag2";
                    sub2.Volume1 = ran.Next(1000);
                    sub2.PriceMove = ran.NextDouble() * 100 - 50;
                    sub2.Volume2 = ran.Next(1000);
                    sub2.Name1 = "Contract" + (DateTime.Now.Millisecond + ran.Next(5)).ToString();
                    sub2.Name2 = "Contract" + DateTime.Now.Millisecond.ToString();
                    retval.Add(sub2);
                }
            }
            return retval;
        }

    }

    public static void TestAvro(int count)
    {
        bool correct = false;
        long serTicks = 0;
        long deserTicks = 0;

        Stopwatch sw = new Stopwatch();
        sw.Reset();

        var serializer = Microsoft.Hadoop.Avro.AvroSerializer.Create<MessageBase>();
        MessageBase[] messages = new MessageBase[count];
        using (var file = File.Create(@"C:\test_avro.bin"))
        {
            int i = 0;
            foreach (var message in MessageFactory.CreateMessages(count))
            {
                messages[i++] = message;
                sw.Start();
                serializer.Serialize(file, message);
                sw.Stop();
            }
        }

        serTicks = sw.ElapsedTicks;
        sw.Reset();

        List<int> badMessages = new List<int>();
        using (var file = File.OpenRead(@"C:\test_avro.bin"))
        {
            for (int i = 0; i < count; i++)
            {
                sw.Start();
                MessageBase message = serializer.Deserialize(file);
                sw.Stop();

                SubMessage1 m1 = message as SubMessage1;
                SubMessage2 m2 = message as SubMessage2;

                bool areNull = (m1 == null) && (m2 == null);   // Always true

                if (!messages[i].Equals(message)) badMessages.Add(i);
            }
        }

        deserTicks = sw.ElapsedTicks;
        correct = badMessages.Count == 0;

        long size = (new FileInfo(@"C:\test_proto.bin")).Length;

        Console.WriteLine(String.Format("Correct: {0}, Time Out: {1}, , Time In: {2}, , Size: {3}", correct, serTicks, deserTicks, size));
    }

    static void Main(string[] args)
    {
        TestAvro(10000);
        Console.ReadLine();
    }
}

1 个答案:

答案 0 :(得分:1)

我的错 - 我忘记了基类的KnownType属性,每个派生类型都有一个属性。如果包含属性,它就可以工作。