Reliable Collection-Objektserialisierung in Azure Service Fabric

Reliable Collection repliziert und speichert seine Elemente, um sicherzustellen, dass sie über Computer- und Stromausfälle hinaus erhalten bleiben. Sowohl zum Replizieren als auch zum Speichern von Elementen müssen diese von Reliable Collections serialisiert werden.

Reliable Collection ruft das geeignete Serialisierungsprogramm für einen bestimmten Typ von Reliable State Manager ab. Reliable State Manager enthält integrierte Serialisierungsprogramme und lässt die Registrierung benutzerdefinierter Serialisierungsprogramme für einen bestimmten Typ zu.

Integrierte Serialisierungsprogramme

Reliable State Manager enthält integrierte Serialisierungsprogramme für einige allgemeine Typen, sodass diese standardmäßig effizient serialisiert werden können. Für andere Typen weicht Reliable State Manager auf die Verwendung von DataContractSerializer aus. Integrierte Serialisierungsprogramme sind effizienter, da sich ihre Typen nicht ändern und daher keine Informationen über den Typ (z.B. den Typnamen) hinzugefügt werden müssen.

Reliable State Manager verfügt über integrierte Serialisierungsprogramme für die folgenden Typen:

  • Guid
  • bool
  • byte
  • sbyte
  • byte[]
  • char
  • Zeichenfolge
  • Decimal
  • double
  • float
  • INT
  • uint
  • long
  • ulong
  • short
  • ushort

Benutzerdefinierte Serialisierung

Benutzerdefinierte Serialisierungsprogramme werden häufig zum Steigern der Leistung oder zum Verschlüsseln der Daten über das Netzwerk und auf dem Datenträger verwendet. Neben anderen Gründen sind benutzerdefinierte Serialisierungsprogramme häufig effizienter als generische Serialisierungsprogramme, da sie Informationen über den Typ nicht serialisieren müssen.

IReliableStateManager.TryAddStateSerializerIReliableStateManager.TryAddStateSerializerT wird verwendet, um einen benutzerdefinierten Serialisierer für den angegebenen Typ T zu registrieren. Diese Registrierung sollte bei der Erstellung der StatefulServiceBase erfolgen, um sicherzustellen, dass vor Beginn der Wiederherstellung alle Reliable Collections Zugriff auf den entsprechenden Serialisierer haben, um ihre persistierten Daten zu lesen.

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

Hinweis

Benutzerdefinierte Serialisierungsprogramme erhalten Vorrang vor integrierten Serialisierungsprogrammen. Wenn z.B. ein benutzerdefiniertes Serialisierungsprogramm für „int“ registriert ist, wird es anstelle des integrierten Serialisierungsprogramm für „int“ zum Serialisieren von ganzen Zahlen verwendet.

Implementieren eines benutzerdefinierten Serialisierungsprogramms

Ein benutzerdefiniertes Serialisierungsprogramm muss die IStateSerializer<T>-Schnittstelle implementieren.

Hinweis

IStateSerializer<T> umfasst Schreib- und Leseüberladungen, die einen zusätzlichen T-Wert verwenden, den Basiswert. Diese API ist für die differenzielle Serialisierung bestimmt. Aktuell ist das Feature der differenziellen Serialisierung nicht verfügbar. Daher werden diese beiden Überladungen nicht aufgerufen, solange die differenzielle Serialisierung nicht verfügbar gemacht und aktiviert wurde.

Es folgt ein Beispiel für einen benutzerdefinierten Typ „OrderKey“, der vier Eigenschaften enthält.

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
}

Im Folgenden finden Sie ein Beispiel für das Implementieren von IStateSerializer<OrderKey>. Beachten Sie, dass die Lese-/Schreibüberladungen, die den BaseValue erfassen, zur Aufwärtskompatibilität die entsprechende Überladung aufrufen.

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);
  }
}

Upgradefähigkeit

Bei einem parallelen Anwendungsupgrade wird das Upgrade auf eine Teilmenge von Knoten angewendet. Dabei werden die einzelnen Upgradedomänen nacheinander abgearbeitet. Während dieses Vorgangs weisen einige Upgradedomänen die neuere Version Ihrer Anwendung auf und andere Upgradedomänen die ältere Version Ihrer Anwendung. Während der Einführung muss die neue Version der Anwendung die alte Version Ihrer Daten sowie die alte Version der Anwendung die neue Version der Daten lesen können. Wenn das Datenformat nicht aufwärts- und abwärtskompatibel ist, kann das Upgrade nicht erfolgreich durchgeführt werden, oder es gehen möglicherweise sogar Daten verloren oder werden beschädigt.

Wenn Sie das integrierte Serialisierungsprogramm verwenden, brauchen Sie sich nicht um die Kompatibilität zu kümmern. Wenn Sie jedoch ein benutzerdefiniertes Serialisierungsprogramm oder „DataContractSerializer“ verwenden, müssen die Daten uneingeschränkt abwärts- und aufwärtskompatibel sein. Das heißt, jede Version des Serialisierungsprogramms muss in der Lage sein, jede beliebige Version des Typs zu serialisieren und zu deserialisieren.

Data Contract-Benutzer sollten die klar definierten Versionsregeln zum Hinzufügen, Entfernen und Ändern von Feldern befolgen. Data Contract unterstützt außerdem die Behandlung von unbekannten Feldern, die Hookfunktion für den Serialisierungs- und Deserialisierungsvorgang und den Umgang mit der Klassenvererbung. Weitere Informationen finden Sie unter Verwenden von Datenverträgen.

Benutzer von benutzerdefinierten Serialisierungsprogrammen sollten die Richtlinien des verwendeten Serialisierungsprogramms befolgen, um Abwärts- und Aufwärtskompatibilität zu gewährleisten. Eine übliche Methode, um sicherzustellen, dass sämtliche Versionen unterstützt werden, besteht darin, Größeninformationen am Anfang hinzuzufügen und nur optionale Eigenschaften hinzuzufügen. Auf diese Weise kann jede Version so viel lesen wie möglich und den Rest des Streams überspringen.

Nächste Schritte