Panoramica della serializzazione delle eccezioni di comunicazione remota
La serializzazione basata su BinaryFormatter non è sicura, quindi non usare BinaryFormatter per l'elaborazione dei dati. Per altre informazioni sulle implicazioni relative alla sicurezza, vedere Rischi di deserializzazione nell'uso di BinaryFormatter e dei tipi correlati.
Azure Service Fabric usa BinaryFormatter per serializzare le eccezioni. A partire da ServiceFabric v9.0, la serializzazione basata sul contratto dati per le eccezioni di comunicazione remota è disponibile come funzionalità di consenso esplicito. È consigliabile optare per la serializzazione delle eccezioni remote DataContract seguendo la procedura descritta in questo articolo.
Il supporto per la serializzazione delle eccezioni basate su BinaryFormatter sarà deprecato in futuro.
Abilitare la serializzazione del contratto dati per le eccezioni di comunicazione remota
Nota
La serializzazione del contratto dati per le eccezioni remote è disponibile solo per i servizi remoti V2/V2_1.
Per abilitare la serializzazione del contratto dati per le eccezioni di comunicazione remota:
Abilitare la serializzazione delle eccezioni remote DataContract sul lato Servizio usando
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
durante la creazione del listener di comunicazione remota.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
Per abilitare la serializzazione delle eccezioni remote DataContract nel servizio actor, eseguire l'override diCreateServiceReplicaListeners()
estendendoActorService
.protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
Se l'eccezione originale ha più livelli di eccezioni interne, è possibile controllare il numero di livelli di eccezioni interne da serializzare impostando
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
.Abilitare la serializzazione delle eccezioni remote DataContract nel Client usando
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
durante la creazione della factory client.Creazione di 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 serializzazione dell'eccezione remota DataContract converte un'eccezione nell'oggetto di trasferimento dati (DTO) sul lato servizio. L'oggetto DTO viene convertito nuovamente in un'eccezione sul lato client. Gli utenti devono registrare
ExceptionConvertor
per convertire le eccezioni desiderate in oggetti DTO e viceversa.Il framework implementa i convertitori per l'elenco di eccezioni seguente. Se il codice del servizio utente dipende dalle eccezioni esterne all'elenco seguente per l'implementazione e la gestione delle eccezioni, gli utenti devono implementare e registrare i convertitori per tali eccezioni.
- Tutte le eccezioni di Service Fabric derivate da
System.Fabric.FabricException
- SystemExceptions derivate da
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
- Tutte le eccezioni di Service Fabric derivate da
Implementazione di esempio di un convertitore lato servizio per un'eccezione personalizzata
L'esempio seguente è un'implementazione IExceptionConvertor
del riferimento sul lato Servizio e Client per un tipo di eccezione noto, 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; } }
Implementazione
IExceptionConvertor
del lato Servizio: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'eccezione effettiva osservata durante l'esecuzione della chiamata remota viene passata come input a TryConvertToServiceException
. Se il tipo dell'eccezione è noto, TryConvertToServiceException
deve convertire l'eccezione originale in ServiceException
e restituirla come parametro in uscita. Un valore true deve essere restituito se il tipo di eccezione originale è noto e l'eccezione originale viene convertita correttamente in ServiceException
. In caso contrario, il valore è false.
Un elenco di eccezioni interne a livello corrente deve essere restituito da GetInnerExceptions()
.
Implementazione
IExceptionConvertor
del lato 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
viene passato come parametro a TryConvertFromServiceException
insieme ai innerException[s]
convertiti. Se il tipo di eccezione effettivo, ServiceException.ActualExceptionType
, è noto, il convertitore deve creare un oggetto eccezione effettivo da ServiceException
e innerException[s]
.
Registrazione
IExceptionConvertor
sul lato Servizio:Per registrare i convertitori, è necessario eseguire l'override di
CreateServiceInstanceListeners
e passare l'elenco delle classiIExceptionConvertor
durante la creazione dell'istanza diRemotingListener
.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") }; }
Registrazione
IExceptionConvertor
sul lato Client:Per registrare i convertitori, è necessario passare l'elenco delle classi
IExceptionConvertor
durante la creazione dell'istanza diClientFactory
.ServiceProxyFactory creation
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
ActorProxyFactory creation
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Nota
Se il framework trova il convertitore per l'eccezione, l'eccezione convertita (effettiva) viene sottoposta a wrapping all'interno di AggregateException
e viene generata nell'API remota (proxy). Se il framework non riesce a trovare il convertitore, ServiceException
, che contiene tutti i dettagli dell'eccezione effettiva, viene sottoposto a wrapping all'interno di AggregateException
e viene generato.
Aggiornare un servizio esistente per abilitare la serializzazione del contratto dati per le eccezioni remote
Per eseguire l'aggiornamento, i servizi esistenti devono attenersi all'ordine seguente (Prima il servizio). Se non si segue questo ordine, potrebbe verificarsi un comportamento errato nella logica di retry e nella gestione delle eccezioni.
Implementare le classi lato Servizio
ExceptionConvertor
per le eccezioni desiderate, se presenti. Aggiornare la logica di registrazione del listener remoto conExceptionSerializationTechnique
e l'elenco delle classiIExceptionConvertor
. Aggiornare il servizio esistente per applicare le modifiche alla serializzazione delle eccezioni.Implementare le classi lato Client
ExceptionConvertor
per le eccezioni desiderate, se presenti. Aggiornare la logica di creazione di ProxyFactory conExceptionSerializationTechnique
e l'elenco delle classiIExceptionConvertor
. Aggiornare il client esistente per applicare le modifiche alla serializzazione delle eccezioni.