Udostępnij za pośrednictwem


Serializacja obiektów Reliable Collection w usłudze Azure Service Fabric

Replikowanie i utrwalanie elementów niezawodnych kolekcji w celu zapewnienia ich trwałości w przypadku awarii maszyn i awarii zasilania. Zarówno w celu replikowania, jak i utrwalania elementów, należy je serializować w kolekcji Reliable Collections.

Zestawy Reliable Collections uzyskują odpowiedni serializator dla danego typu z menedżera niezawodnego stanu. Reliable State Manager zawiera wbudowane serializatory i umożliwia zarejestrowanie niestandardowych serializatorów dla danego typu.

Wbudowane serializatory

Niezawodny menedżer stanu zawiera wbudowany serializator dla niektórych typowych typów, dzięki czemu można je domyślnie serializować. W przypadku innych typów funkcja Reliable State Manager powraca do używania elementu DataContractSerializer. Wbudowane serializatory są bardziej wydajne, ponieważ wiedzą, że ich typy nie mogą się zmieniać i nie muszą zawierać informacji o typie, takich jak jego nazwa typu.

Program Reliable State Manager ma wbudowany serializator dla następujących typów:

  • Identyfikator GUID
  • bool
  • byte
  • sbyte
  • byte[]
  • char
  • string
  • decimal
  • double
  • liczba zmiennoprzecinkowa
  • int
  • uint
  • długi
  • ulong
  • short
  • ushort

Serializacja niestandardowa

Niestandardowe serializatory są często używane do zwiększania wydajności lub szyfrowania danych za pośrednictwem przewodu i na dysku. Między innymi niestandardowe serializatory są często bardziej wydajne niż serializator ogólny, ponieważ nie muszą serializować informacji o typie.

IReliableStateManager.TryAddStateSerializer<T służy do rejestrowania niestandardowego serializatora dla danego typu T> . Ta rejestracja powinna nastąpić w budowie bazy statefulServiceBase, aby upewnić się, że przed rozpoczęciem odzyskiwania wszystkie kolekcje Reliable Collections mają dostęp do odpowiedniego serializatora w celu odczytania ich utrwalone dane.

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

Uwaga

Niestandardowe serializatory mają pierwszeństwo przed wbudowanymi serializatorami. Na przykład po zarejestrowaniu niestandardowego serializatora dla int jest używany do serializacji liczb całkowitych zamiast wbudowanego serializatora dla int.

Jak zaimplementować niestandardowy serializator

Niestandardowy serializator musi zaimplementować interfejs IStateSerializer<T> .

Uwaga

IStateSerializer<T> zawiera przeciążenie dla zapisu i odczytu, które przyjmuje dodatkową wartość T nazywaną wartością bazową. Ten interfejs API służy do serializacji różnicowej. Obecnie funkcja serializacji różnicowej nie jest uwidoczniona. W związku z tym te dwa przeciążenia nie są wywoływane, dopóki serializacja różnicowa nie zostanie uwidoczniona i włączona.

Poniżej znajduje się przykładowy typ niestandardowy o nazwie OrderKey, który zawiera cztery właściwości

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
}

Poniżej przedstawiono przykładową implementację elementu IStateSerializer<OrderKey>. Należy pamiętać, że przeciążenia odczytu i zapisu, które przyjmują wartość baseValue, wywołają ich odpowiednie przeciążenie w celu zapewnienia zgodności z usługą Forwards.

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

Możliwość stosowania upgradability

W ramach uaktualnienia aplikacji stopniowej uaktualnienie jest stosowane do podzestawu węzłów— jednej domeny uaktualnienia naraz. W trakcie tego procesu niektóre domeny uaktualniania będą znajdować się w nowszej wersji aplikacji, a niektóre domeny uaktualnienia będą znajdować się w starszej wersji aplikacji. Podczas wdrażania nowa wersja aplikacji musi być w stanie odczytać starą wersję danych, a stara wersja aplikacji musi być w stanie odczytać nową wersję danych. Jeśli format danych nie jest zgodny z poprzednimi wersjami, uaktualnienie może zakończyć się niepowodzeniem lub co gorsza, dane mogą zostać utracone lub uszkodzone.

Jeśli używasz wbudowanego serializatora, nie musisz martwić się o zgodność. Jeśli jednak używasz niestandardowego serializatora lub modułu DataContractSerializer, dane muszą być nieskończenie wsteczne i zgodne z przodu. Innymi słowy, każda wersja serializatora musi być w stanie serializować i de serializować dowolną wersję typu.

Użytkownicy kontraktu danych powinni przestrzegać dobrze zdefiniowanych reguł przechowywania wersji w celu dodawania, usuwania i zmieniania pól. Kontrakt danych ma również obsługę obsługi nieznanych pól, podłączania do procesu serializacji i deserializacji oraz radzenia sobie z dziedziczeniem klas. Aby uzyskać więcej informacji, zobacz Using Data Contract (Korzystanie z kontraktu danych).

Niestandardowi użytkownicy serializatora powinni przestrzegać wytycznych serializatora, których używają, aby upewnić się, że jest on do tyłu i do przodu zgodny. Typowym sposobem obsługi wszystkich wersji jest dodanie informacji o rozmiarze na początku i dodanie tylko opcjonalnych właściwości. Dzięki temu każda wersja może odczytywać tyle, ile może i przeskakuje pozostałą część strumienia.

Następne kroki