Vue d’ensemble de la sérialisation des exceptions de communication à distance
La sérialisation basée sur BinaryFormatter n’est pas sécurisée. N’utilisez donc pas BinaryFormatter pour le traitement des données. Pour plus d’informations sur les implications de sécurité, consultez Les risques de désérialisation dans l’utilisation de BinaryFormatter et de types associés.
Service Fabric utilisait BinaryFormatter pour sérialiser des exceptions. À partir de ServiceFabric v9.0, la sérialisation basée sur le contrat de données pour les exceptions de communication à distance est mise à disposition en tant que fonctionnalité facultative. Nous vous recommandons d’opter pour la sérialisation de l’exception de communication à distance DataContract en suivant les étapes décrites dans cet article.
La prise en charge de la sérialisation de l’exception de la communication à distance basée sur BinaryFormatter sera dépréciée à l’avenir.
Activation de la sérialisation du contrat de données pour les exceptions de la communication à distance
Notes
La sérialisation du contrat de données pour les exceptions de la communication à distance n’est disponible que pour les services de communication à distance V2/V2_1.
Pour activer la sérialisation du contrat de données pour les exceptions de la communication à distance
Activez la sérialisation de l’exception de communication à distance DataContract côté Service à l’aide de
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
lors de la création de l’écouteur de communication à distance.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
Pour activer la sérialisation de l’exception de communication à distance DataContract sur le service des acteurs, remplacezCreateServiceReplicaListeners()
en étendantActorService
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
Si l’exception d’origine comporte plusieurs niveaux d’exceptions internes, vous pouvez contrôler le nombre de niveaux d’exceptions internes à sérialiser en définissant
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
.Activer la sérialisation de l’exception de communication à distance DataContract sur le Client en utilisant
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
lors de la création de la fabrique clienteCréation de 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); });
La sérialisation de l’exception de communication à distance DataContract convertit une exception en objet de transfert de données (DTO) côté service. Le DTO est converti en exception côté client. Les utilisateurs doivent inscrire
ExceptionConvertor
pour convertir les exceptions souhaitées en objets DTO et vice versa.L’infrastructure implémente les converteurs pour la liste suivante d’exceptions. Si le code du service utilisateur dépend d’exceptions qui ne figurent pas dans la liste ci-dessous pour l’implémentation de nouvelles tentatives, la gestion des exceptions, etc., l’utilisateur doit implémenter et inscrire des outils de conversion pour ces exceptions.
- Toutes les exceptions Service Fabric dérivées de
System.Fabric.FabricException
- SystemExceptions dérivées de
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
- Toutes les exceptions Service Fabric dérivées de
Exemple d’implémentation de l’outil de conversion côté service pour une exception personnalisée
Vous trouverez ci-dessous une implémentation IExceptionConvertor
de référence côté Service et Client pour un type d’exception bien connu 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
Implémentation du côté Service :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; } }
L’exception réelle observée lors de l’exécution de l’appel de communication à distance est passée en tant qu’entrée TryConvertToServiceException
. Si le type de l’exception est bien connu, TryConvertToServiceException
doit convertir l’exception d’origine en ServiceException
et la retourner en tant que paramètre de sortie. Une valeur vraie doit être renvoyée si le type d'exception d'origine est bien connu et si l'exception d'origine est convertie avec succès en ServiceException
. Sinon, la valeur est false.
Une liste d’exceptions internes au niveau actuel doit être retournée par GetInnerExceptions()
.
IExceptionConvertor
Implémentation du côté Client :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
est passé en tant que paramètre à TryConvertFromServiceException
ainsi que l’élément innerException[s]
converti. Si le type d’exception réel ,ServiceException.ActualExceptionType
, est connu, l’outil de conversion doit créer un objet d’exception réel à partir de ServiceException
et de innerException[s]
.
IExceptionConvertor
Inscription côté Service :Pour inscrire des converteurs,
CreateServiceInstanceListeners
vous devez être remplacés et la liste des classes doit être passée pendant la création deIExceptionConvertor
l’instanceRemotingListener
.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
Inscription côté Client :Pour inscrire des converteurs, la liste des
IExceptionConvertor
classes doit être passée pendant que vous créez l’instanceClientFactory
.Création de ServiceProxyFactory
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Création de ActorProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Notes
Si le framework trouve le convertisseur pour l'exception, l'exception convertie (réelle) est enveloppée dans AggregateException
et est lancée à l'API de remoting (proxy). Si le framework ne parvient pas à trouver l’outil de conversion, ServiceException
qui contient tous les détails de l’exception réelle est encapsulé dans AggregateException
et levé.
Mettre à niveau un service existant pour activer la sérialisation des contrats de données pour les exceptions de communication à distance
Les services existants doivent suivre l’ordre ci-dessous (en commençant par Service) pour la mise à niveau. Le non-respect de cet ordre peut entraîner un mauvais comportement dans la logique de relance et le traitement des exceptions.
Implémentez les
ExceptionConvertor
côté Service pour les exceptions souhaitées, le cas échéant. Mettez à jour la logique d’inscription de l’écouteur de communication à distance avecExceptionSerializationTechnique
et la liste des classesIExceptionConvertor
. Mettre à niveau le service existant pour appliquer les modifications de sérialisation des exceptions.Implémentez les
ExceptionConvertor
côté Client pour les exceptions souhaitées, le cas échéant. Mettez à jour la logique de création de ProxyFactory avecExceptionSerializationTechnique
et la liste des classesIExceptionConvertor
. Mettre à niveau le client existant pour appliquer les modifications de sérialisation des exceptions