Delen via


Serialisatieoverzicht van uitzondering voor externe toegang

Serialisatie op basis van BinaryFormatter is niet veilig, dus gebruik BinaryFormatter niet voor gegevensverwerking. Zie Deserialisatierisico's in het gebruik van BinaryFormatter en gerelateerde typen voor meer informatie over de gevolgen voor de beveiliging.

Azure Service Fabric heeft BinaryFormatter gebruikt voor het serialiseren van uitzonderingen. Vanaf ServiceFabric v9.0 is serialisatie op basis van gegevenscontracten voor externe externe uitzonderingen beschikbaar als opt-in-functie. We raden u aan om te kiezen voor serialisatie van externe datacontractuitzonderingen door de stappen in dit artikel te volgen.

Ondersteuning voor serialisatie van externe communicatie op basis van BinaryFormatter wordt in de toekomst afgeschaft.

Serialisatie van gegevenscontracten inschakelen voor externe uitzonderingen

Notitie

Serialisatie van gegevenscontracten voor externe uitzonderingen is alleen beschikbaar voor externe communicatie van V2/V2_1-services.

Serialisatie van gegevenscontracten inschakelen voor externe uitzonderingen:

  1. Schakel serialisatie van uitzondering voor externe communicatie van DataContract in aan de servicezijde met behulp van FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique tijdens het maken van de externe listener.

    • StatelessService

      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
      Als u serialisatie van externe datacontract-uitzonderingen wilt inschakelen voor de actorservice, overschrijft CreateServiceReplicaListeners() u door uit te breiden ActorService.

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

    Als de oorspronkelijke uitzondering meerdere niveaus van binnenuitzondering heeft, kunt u het aantal niveaus van interne uitzonderingen dat moet worden geserialiseerd, bepalen door in te stellen FabricTransportRemotingListenerSettings.RemotingExceptionDepth.

  2. Schakel serialisatie van uitzondering voor externe communicatie van DataContract in op de client met behulp van FabricTransportRemotingSettings.ExceptionDeserializationTechnique tijdens het maken van de clientfactory.

    • ServiceProxyFactory maken

      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. Serialisatie van uitzondering voor externe communicatie van DataContract converteert een uitzondering naar het gegevensoverdrachtobject (DTO) aan de servicezijde. De DTO wordt weer geconverteerd naar een uitzondering aan de clientzijde. Gebruikers moeten zich registreren ExceptionConvertor om de gewenste uitzonderingen te converteren naar DTO-objecten en omgekeerd.

    Het framework implementeert convertors voor de volgende lijst met uitzonderingen. Als gebruikersservicecode afhankelijk is van uitzonderingen buiten de volgende lijst voor de implementatie van nieuwe pogingen en het verwerken van uitzonderingen, moeten gebruikers convertors implementeren en registreren voor dergelijke uitzonderingen.

    • Alle Service Fabric-uitzonderingen die zijn afgeleid van System.Fabric.FabricException
    • SystemExceptions afgeleid van 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

Voorbeeld van implementatie van een conversieprogramma aan de servicezijde voor een aangepaste uitzondering

Het volgende voorbeeld is referentie-implementatie IExceptionConvertor aan de service - en clientzijde voor een bekend uitzonderingstype, 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 implementatie aan de servicezijde :

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

De werkelijke uitzondering die is waargenomen tijdens de uitvoering van de externe aanroep wordt doorgegeven als invoer aan TryConvertToServiceException. Als het type uitzondering een bekende is, TryConvertToServiceException moet de oorspronkelijke uitzondering worden geconverteerd naar ServiceException en geretourneerd als een out-parameter. Er moet een true-waarde worden geretourneerd als het oorspronkelijke uitzonderingstype een bekend type is en de oorspronkelijke uitzondering is geconverteerd naar ServiceException. Anders is de waarde false.

Een lijst met interne uitzonderingen op het huidige niveau moet worden geretourneerd door GetInnerExceptions().

  • IExceptionConvertor implementatie aan de clientzijde :

    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 wordt doorgegeven als een parameter aan TryConvertFromServiceException samen met geconverteerd innerException[s]. Als het werkelijke uitzonderingstype, ServiceException.ActualExceptionType, een bekend type is, moet de convertor een werkelijk uitzonderingsobject maken van ServiceException en innerException[s].

  • IExceptionConvertor registratie aan de servicezijde :

    Als u conversies wilt registreren, CreateServiceInstanceListeners moet worden overschreven en moet de lijst met klassen worden doorgegeven tijdens het maken van IExceptionConvertor het RemotingListener exemplaar.

    • StatelessService

      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 registratie aan de clientzijde :

    Als u conversies wilt registreren, moet de lijst met IExceptionConvertor klassen worden doorgegeven terwijl u het ClientFactory exemplaar maakt.

    • ServiceProxyFactory maken

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

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

Notitie

Als het framework de conversieor voor de uitzondering vindt, wordt de geconverteerde (werkelijke) uitzondering erin AggregateException verpakt en wordt deze gegenereerd bij de externe API (proxy). Als het framework de convertor niet kan vinden, ServiceExceptionwordt , die alle details van de werkelijke uitzondering bevat, erin AggregateException verpakt en gegenereerd.

Een bestaande service upgraden om serialisatie van gegevenscontracten in te schakelen voor externe uitzonderingen

Bestaande services moeten de volgende volgorde volgen (Service eerst) om een upgrade uit te voeren. Als u deze volgorde niet volgt, kan dit leiden tot wangedrag in de logica voor opnieuw proberen en het verwerken van uitzonderingen.

  1. Implementeer de klassen aan de servicezijdeExceptionConvertor voor de gewenste uitzonderingen, indien van toepassing. Werk de registratielogica voor IExceptionConvertorexterne listener bij met ExceptionSerializationTechnique en de lijst met klassen. Werk de bestaande service bij om de serialisatiewijzigingen van de uitzondering toe te passen.

  2. Implementeer de klassen aan de clientzijdeExceptionConvertor voor de gewenste uitzonderingen, indien van toepassing. Werk de logica voor het maken van ProxyFactory bij met ExceptionSerializationTechnique en de lijst met IExceptionConvertor klassen. Upgrade de bestaande client om de serialisatiewijzigingen van de uitzondering toe te passen.

Volgende stappen