Sdílet prostřednictvím


Přehled serializace výjimek vzdálené komunikace

Serializace založená na BinaryFormatter není zabezpečená, proto ke zpracování dat nepoužívejte BinaryFormatter. Další informace o dopadech na zabezpečení najdete v tématu Rizika deserializace při použití BinaryFormatter a souvisejících typů.

Azure Service Fabric k serializaci výjimek použil BinaryFormatter. Počínaje verzí ServiceFabric v9.0 je jako opt-in k dispozici serializace založená na kontraktech dat pro výjimky vzdálené komunikace. Doporučujeme, abyste se rozhodli pro serializaci výjimky vzdálené komunikace DataContract podle kroků v tomto článku.

Podpora serializace výjimek vzdálené komunikace založené na BinaryFormatter bude v budoucnu zastaralá.

Povolení serializace kontraktů dat pro výjimky vzdálené komunikace

Poznámka:

Serializace kontraktů dat pro výjimky vzdálené komunikace je k dispozici pouze pro vzdálené komunikace V2/V2_1 služby.

Povolení serializace kontraktů dat pro výjimky vzdálené komunikace:

  1. Povolte serializaci výjimky vzdálené komunikace data na straně služby pomocí FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique při vytváření naslouchacího procesu vzdálené komunikace.

    • Bezstavová služba

      protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
      {
          return new[]
          {
              new ServiceInstanceListener(serviceContext =>
                  new FabricTransportServiceRemotingListener(
                      serviceContext,
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      }),
                   "ServiceEndpointV2")
          };
      }
      
    • StatefulService

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new[]
          {
              new ServiceReplicaListener(serviceContext =>
                  new FabricTransportServiceRemotingListener(
                      serviceContext,
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      }),
                  "ServiceEndpointV2")
          };
      }
      
    • ActorService
      Chcete-li povolit serializaci výjimky vzdálené komunikace DataContract ve službě actor, přepsání CreateServiceReplicaListeners() rozšířením ActorService.

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new List<ServiceReplicaListener>
          {
              new ServiceReplicaListener(_ =>
              {
                  return new FabricTransportActorServiceRemotingListener(
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      });
              },
              "MyActorServiceEndpointV2")
          };
      }
      

    Pokud má původní výjimka více úrovní vnitřních výjimek, můžete řídit počet úrovní vnitřních výjimek, které mají být serializovány nastavením FabricTransportRemotingListenerSettings.RemotingExceptionDepth.

  2. Povolte serializaci výjimky vzdálené komunikace data v klientovi pomocí FabricTransportRemotingSettings.ExceptionDeserializationTechnique při vytváření objektu pro vytváření klienta.

    • Vytvoření serviceProxyFactory

      var serviceProxyFactory = new ServiceProxyFactory(
      (callbackClient) =>
      {
          return new FabricTransportServiceRemotingClientFactory(
              new FabricTransportRemotingSettings
              {
                  ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
              },
              callbackClient);
      });
      
    • ActorProxyFactory

      var actorProxyFactory = new ActorProxyFactory(
      (callbackClient) =>
      {
          return new FabricTransportActorRemotingClientFactory(
              new FabricTransportRemotingSettings
              {
                  ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
              },
              callbackClient);
      });
      
  3. Serializace výjimky vzdálené komunikace DataContract převede výjimku na objekt pro přenos dat (DTO) na straně služby. DTO se převede zpět na výjimku na straně klienta. Uživatelé se musí zaregistrovat ExceptionConvertor k převodu požadovaných výjimek na objekty DTO a naopak.

    Architektura implementuje převody pro následující seznam výjimek. Pokud kód uživatelské služby závisí na výjimkách mimo následující seznam pro zpracování opakování a zpracování výjimek, uživatelé musí pro tyto výjimky implementovat a zaregistrovat převodce.

    • Všechny výjimky Service Fabric odvozené od System.Fabric.FabricException
    • SystemExceptions odvozené z System.SystemException
      • System.AccessViolationException
      • System.AppDomainUnloadedException
      • System.ArgumentException
      • System.AritmeticException
      • System.ArrayTypeMismatchException
      • System.BadImageFormatException
      • System.CannotUnloadAppDomainException
      • System.Collections.Generic.KeyNotFoundException
      • System.ContextMarshalException
      • System.DataMisalignedException
      • System.ExecutionEngineException
      • System.FormatException
      • System.IndexOutOfRangeException
      • System.InsufficientExecutionStackException
      • System.InvalidCastException
      • System.InvalidOperationException
      • System.InvalidProgramException
      • System.IO.InternalBufferOverflowException
      • System.IO.InvalidDataException
      • System.IO.IOException
      • System.MemberAccessException
      • System.MulticastNotSupportedException
      • System.NotImplementedException
      • System.NotSupportedException
      • System.NullReferenceException
      • System.OperationCanceledException
      • System.OutOfMemoryException
      • System.RankException
      • System.Reflection.AmbiguousMatchException
      • System.Reflection.ReflectionTypeLoadException
      • System.Resources.MissingManifestResourceException
      • System.Resources.MissingSatelliteAssemblyException
      • System.Runtime.InteropServices.ExternalException
      • System.Runtime.InteropServices.InvalidComObjectException
      • System.Runtime.InteropServices.InvalidOleVariantTypeException
      • System.Runtime.InteropServices.MarshalDirectiveException
      • System.Runtime.InteropServices.SafeArrayRankMismatchException
      • System.Runtime.InteropServices.SafeArrayTypeMismatchException
      • System.Runtime.Serialization.SerializationException
      • System.StackOverflowException
      • System.Threading.AbandonedMutexException
      • System.Threading.SemaphoreFullException
      • System.Threading.SynchronizationLockException
      • System.Threading.ThreadInterruptedException
      • System.Threading.ThreadStateException
      • System.TimeoutException
      • System.TypeInitializationException
      • System.TypeLoadException
      • System.TypeUnloadedException
      • System.UnauthorizedAccessException
      • System.ArgumentNullException
      • System.IO.FileNotFoundException
      • System.IO.DirectoryNotFoundException
      • System.ObjectDisposedException
      • System.AggregateException

Ukázková implementace převodu na straně služby pro vlastní výjimku

Následující příklad je odkaz IExceptionConvertor implementace na straně služby a klienta pro dobře známý typ výjimky, CustomException.

  • CustomException

    class CustomException : Exception
    {
        public CustomException(string message, string field1, string field2)
            : base(message)
        {
            this.Field1 = field1;
            this.Field2 = field2;
        }
    
        public CustomException(string message, Exception innerEx, string field1, string field2)
            : base(message, innerEx)
        {
            this.Field1 = field1;
            this.Field2 = field2;
        }
    
        public string Field1 { get; set; }
    
        public string Field2 { get; set; }
    }
    
  • IExceptionConvertor implementace na straně služby :

    class CustomConvertorService : Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.IExceptionConvertor
    {
        public Exception[] GetInnerExceptions(Exception originalException)
        {
            return originalException.InnerException == null ? null : new Exception[] { originalException.InnerException };
        }
    
        public bool TryConvertToServiceException(Exception originalException, out ServiceException serviceException)
        {
            serviceException = null;
            if (originalException is CustomException customEx)
            {
                serviceException = new ServiceException(customEx.GetType().FullName, customEx.Message);
                serviceException.ActualExceptionStackTrace = originalException.StackTrace;
                serviceException.ActualExceptionData = new Dictionary<string, string>()
                    {
                        { "Field1", customEx.Field1 },
                        { "Field2", customEx.Field2 },
                    };
    
                return true;
            }
    
            return false;
        }
    }
    

Skutečná výjimka zjištěná během provádění volání vzdálené komunikace je předána jako vstup do TryConvertToServiceException. Pokud je typ výjimky dobře známý, TryConvertToServiceException měl by převést původní výjimku na ServiceException a vrátit ji jako výstupní parametr. Hodnota true by měla být vrácena, pokud původní typ výjimky je dobře známý a původní výjimka je úspěšně převedena na ServiceException. V opačném případě je hodnota false.

Seznam vnitřních výjimek na aktuální úrovni by měl vrátit GetInnerExceptions().

  • IExceptionConvertor implementace na straně klienta :

    class CustomConvertorClient : Microsoft.ServiceFabric.Services.Remoting.V2.Client.IExceptionConvertor
    {
        public bool TryConvertFromServiceException(ServiceException serviceException, out Exception actualException)
        {
            return this.TryConvertFromServiceException(serviceException, (Exception)null, out actualException);
        }
    
        public bool TryConvertFromServiceException(ServiceException serviceException, Exception innerException, out Exception actualException)
        {
            actualException = null;
            if (serviceException.ActualExceptionType == typeof(CustomException).FullName)
            {
                actualException = new CustomException(
                    serviceException.Message,
                    innerException,
                    serviceException.ActualExceptionData["Field1"],
                    serviceException.ActualExceptionData["Field2"]);
    
                return true;
            }
    
            return false;
        }
    
        public bool TryConvertFromServiceException(ServiceException serviceException, Exception[] innerExceptions, out Exception actualException)
        {
            throw new NotImplementedException();
        }
    }
    

ServiceException je předán jako parametr TryConvertFromServiceException spolu s převedeným innerException[s]. Je-li skutečný typ výjimky , ServiceException.ActualExceptionTypeje známý, convertor by měl vytvořit skutečný objekt výjimky z ServiceException a innerException[s].

  • IExceptionConvertor registrace na straně služby :

    Chcete-li registrovat převodce, CreateServiceInstanceListeners musí být přepsán a seznam IExceptionConvertor tříd musí být předán při vytváření RemotingListener instance.

    • Bezstavová služba

      protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
      {
          return new[]
          {
              new ServiceInstanceListener(serviceContext =>
                  new FabricTransportServiceRemotingListener(
                      serviceContext,
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      },
                      exceptionConvertors: new[]
                      {
                          new CustomConvertorService(),
                      }),
                   "ServiceEndpointV2")
          };
      }
      
    • StatefulService

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new[]
          {
              new ServiceReplicaListener(serviceContext =>
                  new FabricTransportServiceRemotingListener(
                      serviceContext,
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      },
                      exceptionConvertors: new []
                      {
                          new CustomConvertorService(),
                      }),
                  "ServiceEndpointV2")
          };
      }
      
    • ActorService

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new List<ServiceReplicaListener>
          {
              new ServiceReplicaListener(_ =>
              {
                  return new FabricTransportActorServiceRemotingListener(
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      },
                      exceptionConvertors: new[]
                      {
                          new CustomConvertorService(),
                      });
              },
              "MyActorServiceEndpointV2")
          };
      }
      
  • IExceptionConvertor registrace na straně klienta :

    Chcete-li zaregistrovat převodce, musí být při vytváření ClientFactory instance předán seznam IExceptionConvertor tříd.

    • Vytvoření serviceProxyFactory

      var serviceProxyFactory = new ServiceProxyFactory(
      (callbackClient) =>
      {
         return new FabricTransportServiceRemotingClientFactory(
             new FabricTransportRemotingSettings
             {
                 ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
             },
             callbackClient,
             exceptionConvertors: new[]
             {
                 new CustomConvertorClient(),
             });
      });
      
    • Vytvoření objektu ActorProxyFactory

      var actorProxyFactory = new ActorProxyFactory(
      (callbackClient) =>
      {
          return new FabricTransportActorRemotingClientFactory(
              new FabricTransportRemotingSettings
              {
                  ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
              },
              callbackClient,
              exceptionConvertors: new[]
              {
                  new CustomConvertorClient(),
              });
      });
      

Poznámka:

Pokud architektura najde převéstel výjimky, převedená (skutečná) výjimka je zabalena uvnitř AggregateException a je vyvolána v rozhraní API vzdálené komunikace (proxy). Pokud se rozhraní nepodaří najít převéstel, pak ServiceException, který obsahuje všechny podrobnosti o skutečné výjimce, je zabalen uvnitř AggregateException a je vyvolán.

Upgrade existující služby, aby bylo možné povolit serializaci kontraktů dat pro výjimky vzdálené komunikace

Existující služby musí při upgradu postupovat podle následujícího pořadí (Služba jako první). Selháním tohoto pořadí může dojít k nesprávnému chování v logice opakování a zpracování výjimek.

  1. Implementujte třídy na straně ExceptionConvertor služby pro požadované výjimky, pokud existuje. Aktualizujte logiku registrace naslouchacího procesu vzdálené komunikace IExceptionConvertorpomocí ExceptionSerializationTechnique seznamu tříd. Upgradujte existující službu, aby se použily změny serializace výjimek.

  2. Implementujte třídy na straně ExceptionConvertor klienta pro požadované výjimky, pokud existuje. Aktualizujte logiku vytváření ProxyFactory pomocí ExceptionSerializationTechnique seznamu tříd a seznamem IExceptionConvertor tříd. Upgradujte existujícího klienta, aby použil změny serializace výjimek.

Další kroky