Azure Service Fabric 中的 Reliable Collection 对象序列化Reliable Collection object serialization in Azure Service Fabric

Reliable Collections 通过复制和保留项目,确保这些项目在机器故障和电力中断时能够持久。Reliable Collections' replicate and persist their items to make sure they are durable across machine failures and power outages. 若要复制和保留项目,Reliable Collections 需要对其进行串行化。Both to replicate and to persist items, Reliable Collections' need to serialize them.

Reliable Collections 从可靠状态管理器获取与给定类型对应的串行化程序。Reliable Collections' get the appropriate serializer for a given type from Reliable State Manager. 可靠状态管理器包含内置序列化程序,允许针对给定类型注册自定义串行化程序。Reliable State Manager contains built-in serializers and allows custom serializers to be registered for a given type.

内置串行化程序Built-in Serializers

可靠状态管理器包含针对一些常见类型的内置串行化程序,以便在默认情况下对其进行高效串行化。Reliable State Manager includes built-in serializer for some common types, so that they can be serialized efficiently by default. 对于其他类型,可靠状态管理器回退为使用 DataContractSerializerFor other types, Reliable State Manager falls back to use the DataContractSerializer. 内置串行化程序更高效,因为它们知道其类型无法更改,且它们无需包含类型名称等有关类型的信息。Built-in serializers are more efficient since they know their types cannot change and they do not need to include information about the type like its type name.

可靠状态管理器拥有针对以下类型的内置串行化程序:Reliable State Manager has built-in serializer for following types:

  • GuidGuid
  • boolbool
  • 字节byte
  • sbytesbyte
  • byte[]byte[]
  • charchar
  • 字符串string
  • Decimaldecimal
  • doubledouble
  • FLOATfloat
  • intint
  • uintuint
  • longlong
  • ulongulong
  • shortshort
  • ushortushort

自定义序列化Custom Serialization

自定义串行化程序通常用于提高性能,或用于在网络传输时以及在磁盘上加密数据。Custom serializers are commonly used to increase performance or to encrypt the data over the wire and on disk. 自定义串行化程序通常比通用序列化程序更高效,因为它们不需要串行化有关类型的信息。Among other reasons, custom serializers are commonly more efficient than generic serializer since they don't need to serialize information about the type.

IReliableStateManager.TryAddStateSerializer<T> 用于为给定类型 T 注册自定义串行化程序。此注册应在 StatefulServiceBase 构造内发生,以确保在开始恢复前,所有 Reliable Collections 都有权访问相关串行化程序来读取其保留的数据。IReliableStateManager.TryAddStateSerializer<T> is used to register a custom serializer for the given type T. This registration should happen in the construction of the StatefulServiceBase to ensure that before recovery starts, all Reliable Collections have access to the relevant serializer to read their persisted data.

public StatefulBackendService(StatefulServiceContext context)
  : base(context)
  {
    if (!this.StateManager.TryAddStateSerializer(new OrderKeySerializer()))
    {
      throw new InvalidOperationException("Failed to set OrderKey custom serializer");
    }
  }

备注

自定义串行化程序优先于内置串行化程序。Custom serializers are given precedence over built-in serializers. 例如,如果为 int 注册了自定义串行化程序,则会使用它来串行化整数,而不使用 int 的内置串行化程序。For example, when a custom serializer for int is registered, it is used to serialize integers instead of the built-in serializer for int.

如何实现自定义串行化程序How to implement a custom serializer

自定义串行化程序需要实现 IStateSerializer<T> 接口。A custom serializer needs to implement the IStateSerializer<T> interface.

备注

IStateSerializer<T> 包含读取和写入重载,可接受名为基值的附加 T。IStateSerializer<T> includes an overload for Write and Read that takes in an additional T called base value. 此 API 用于差分序列化。This API is for differential serialization. 当前未公开差分序列化功能。Currently differential serialization feature is not exposed. 因此,在公开和启用差分序列化前,不会调用这两个重载。Hence, these two overloads are not called until differential serialization is exposed and enabled.

以下是名为 OrderKey 的自定义类型示例,它包含四个属性Following is an example custom type called OrderKey that contains four properties

public class OrderKey : IComparable<OrderKey>, IEquatable<OrderKey>
{
    public byte Warehouse { get; set; }

    public short District { get; set; }

    public int Customer { get; set; }

    public long Order { get; set; }

    #region Object Overrides for GetHashCode, CompareTo and Equals
    #endregion
}

以下是 IStateSerializer<OrderKey> 的实现示例。Following is an example implementation of IStateSerializer<OrderKey>. 请注意,接受 baseValue 的读取和写入重载调用各自的重载来实现向前兼容。Note that Read and Write overloads that take in baseValue, call their respective overload for forwards compatibility.

public class OrderKeySerializer : IStateSerializer<OrderKey>
{
  OrderKey IStateSerializer<OrderKey>.Read(BinaryReader reader)
  {
      var value = new OrderKey();
      value.Warehouse = reader.ReadByte();
      value.District = reader.ReadInt16();
      value.Customer = reader.ReadInt32();
      value.Order = reader.ReadInt64();

      return value;
  }

  void IStateSerializer<OrderKey>.Write(OrderKey value, BinaryWriter writer)
  {
      writer.Write(value.Warehouse);
      writer.Write(value.District);
      writer.Write(value.Customer);
      writer.Write(value.Order);
  }

  // Read overload for differential de-serialization
  OrderKey IStateSerializer<OrderKey>.Read(OrderKey baseValue, BinaryReader reader)
  {
      return ((IStateSerializer<OrderKey>)this).Read(reader);
  }

  // Write overload for differential serialization
  void IStateSerializer<OrderKey>.Write(OrderKey baseValue, OrderKey newValue, BinaryWriter writer)
  {
      ((IStateSerializer<OrderKey>)this).Write(newValue, writer);
  }
}

可升级性Upgradability

应用程序滚动升级过程中,升级应用于部分节点,一次一个升级域。In a rolling application upgrade, the upgrade is applied to a subset of nodes, one upgrade domain at a time. 在此过程中,一些升级域将位于较新版本的应用程序上,而一些升级域将位于较旧版本的应用程序上。During this process, some upgrade domains will be on the newer version of your application, and some upgrade domains will be on the older version of your application. 在滚动更新期间,新版本的应用程序必须能够读取旧版本的数据,并且旧版本的应用程序必须能够读取新版本的数据。During the rollout, the new version of your application must be able to read the old version of your data, and the old version of your application must be able to read the new version of your data. 如果数据格式不向前和向后兼容,则升级可能会失败(或更糟),甚至可能丢失数据。If the data format is not forward and backward compatible, the upgrade may fail, or worse, data may be lost or corrupted.

如果使用内置串行化程序,无需担心兼容性问题。If you are using built-in serializer, you do not have to worry about compatibility. 但是,如果使用自定义串行化程序或 DataContractSerializer,数据必须能够无限向后和向前兼容。However, if you are using a custom serializer or the DataContractSerializer, the data have to be infinitely backwards and forwards compatible. 换而言之,串行化程序的每个版本都需要能够序列化和反序列化类型的任何版本。In other words, each version of serializer needs to be able to serialize and de-serialize any version of the type.

数据协定用户应遵循用于添加、删除和更改字段的定义完善的版本控制规则。Data Contract users should follow the well-defined versioning rules for adding, removing, and changing fields. 数据协定还支持处理未知字段、挂接到序列化和反序列化进程以及处理类继承。Data Contract also has support for dealing with unknown fields, hooking into the serialization and deserialization process, and dealing with class inheritance. 有关详细信息,请参阅使用数据协定For more information, see Using Data Contract.

自定义串行化程序用户应遵循其使用的串行化程序的指导原则,以确保它向前和向后兼容。Custom serializer users should adhere to the guidelines of the serializer they are using to make sure it is backwards and forwards compatible. 支持所有版本的常用方法是在开头添加大小信息,并且仅添加可选属性。Common way of supporting all versions is adding size information at the beginning and only adding optional properties. 这样一来,每个版本都可以读取尽可能多的数据并跳过数据流的其余部分。This way each version can read as much it can and jump over the remaining part of the stream.

后续步骤Next steps