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

Serializace založená na BinaryFormatter není bezpečná, proto pro 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 použil k serializaci výjimek BinaryFormatter. Od verze ServiceFabric v9.0 je serializace dat na základě kontraktů pro výjimky vzdálené komunikace k dispozici jako funkce výslovného souhlasu. Doporučujeme, abyste se rozhodli pro serializaci výjimek vzdálené komunikace DataContract podle kroků v tomto článku.

Podpora serializace výjimek vzdálené komunikace na základě BinaryFormatter bude v budoucnu zastaralá.

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

Poznámka

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

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

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

    • Bezstavová služba

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

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new[]
          {
              new ServiceReplicaListener(serviceContext =>
                  new FabricTransportServiceRemotingListener(
                      serviceContext,
                      this,
                      new FabricTransportRemotingListenerSettings
                      {
                          ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
                      }),
                  "ServiceEndpointV2")
          };
      }
      
    • ActorService
      Pokud chcete povolit serializaci výjimek vzdálené komunikace DataContract ve službě objektu actor, přepište 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 původní výjimka obsahuje 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ýjimek vzdálené komunikace DataContract v klientovi pomocí při FabricTransportRemotingSettings.ExceptionDeserializationTechnique 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);
      });
      
    • Objekt 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 přenosu dat (DTO) na straně služby. Objekt DTO se převede zpět na výjimku na straně klienta. Uživatelé se musí zaregistrovat ExceptionConvertor , aby mohli převést požadované výjimky na objekty DTO a naopak.

    Rozhraní implementuje převaděče pro následující seznam výjimek. Pokud kód služby uživatele závisí na výjimkách mimo následující seznam pro implementaci opakování a zpracování výjimek, uživatelé musí implementovat a zaregistrovat převaděče pro tyto výjimky.

    • Všechny výjimky Service Fabric odvozené z System.Fabric.FabricException
    • SystemExceptions odvozené z System.SystemException
      • System.AccessViolationException
      • System.AppDomainUnloadedException
      • System.ArgumentException
      • System.ArithmeticException
      • 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řevodiče na straně služby pro vlastní výjimku

Následující příklad představuje referenční IExceptionConvertor implementaci na straně služby a klienta pro dobře známý typ výjimky , CustomException.

  • Vlastní výjimka

    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í vzdálené komunikace volání 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 out parametr. Hodnota True by měla být vrácena, pokud je původní typ výjimky 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 se předává jako parametr spolu TryConvertFromServiceException s převedeným parametrem innerException[s]. Pokud je skutečný typ ServiceException.ActualExceptionTypevýjimky , známý typ, měl by převodník vytvořit skutečný objekt výjimky z ServiceException a innerException[s].

  • IExceptionConvertor registrace na straně služby :

    Chcete-li zaregistrovat 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")
          };
      }
      
    • Stavová služba

      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í 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 pro výjimku, převedená (skutečná) výjimka je zabalena uvnitř AggregateException a vyvolána v rozhraní API vzdálené komunikace (proxy). Pokud se architektuře nepodaří najít convertor, 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 za účelem povolení serializace kontraktů dat pro výjimky vzdálené komunikace

Existující služby musí k upgradu dodržovat následující objednávku (nejprve služba). Při nedodržení tohoto pořadí může dojít k nesprávnému chování při logice opakování a zpracování výjimek.

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

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

Další kroky