Übersicht über Remotingausnahmeserialisierung
BinaryFormatter-basierte Serialisierung ist nicht sicher, verwenden Sie BinaryFormatter daher nicht für die Datenverarbeitung. Weitere Informationen zu den Sicherheitsauswirkungen finden Sie unter Deserialisierungsrisiken bei der Verwendung von BinaryFormatter und verwandten Typen.
Service Fabric nutzte früher BinaryFormatter zum Serialisieren von Ausnahmen. Ab ServiceFabric v9.0 wird datenvertragbasierte Serialisierung für Remotingausnahmen als wählbare Option verfügbar gemacht. Es wird empfohlen, DataContract-Remotingausnahmeserialisierung zu aktivieren, indem Sie die Schritte in diesem Artikel ausführen.
Unterstützung für BinaryFormatter-basierte Remotingausnahmenserialisierung wird in Zukunft als veraltet markiert.
Aktivieren von Datenvertragsserialisierung für Remotingausnahmen
Hinweis
Datenvertragsserialisierung für Remotingausnahmen ist nur für V2/V2.1-Remotingdienste verfügbar.
So aktivieren Sie Datenvertragsserialisierung für Remotingausnahmen:
Aktivieren Sie DataContract-Remotingausnahmeserialisierung auf der Dienstseite, indem Sie
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
verwenden, während Sie den Remotinglistener erstellen.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
Um DataContract-Remotingausnahmeserialisierung für den Actordienst zu aktivieren, überschreiben SieCreateServiceReplicaListeners()
, indem SieActorService
erweitern.protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
Wenn die ursprüngliche Ausnahme mehrere Ebenen innerer Ausnahmen aufweist, können Sie die Anzahl der Ebenen von inneren Ausnahmen, die serialisiert werden sollen, durch Festlegen von
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
steuern.Aktivieren Sie DataContract-Remotingausnahmeserialisierung auf dem Client mithilfe von
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
während des Erstellens der Clientfactory.Erstellen von 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); });
DataContract-Remotingausnahmeserialisierung konvertiert eine Ausnahme auf der Dienstseite in das Datenübertragungsobjekt (DTO). Das DTO wird auf der Clientseite zurück in eine Ausnahme konvertiert. Benutzer müssen
ExceptionConvertor
registrieren, um die gewünschten Ausnahmen in DTO-Objekte zu konvertieren und umgekehrt.Das Framework implementiert Konverter für die folgende Liste von Ausnahmen. Wenn der Benutzerdienstcode von Ausnahmen außerhalb der folgenden Liste für die Wiederholungsimplementierung und Ausnahmebehandlung abhängt, müssen Benutzer Konverter für diese Ausnahmen implementieren und registrieren.
- Alle von
System.Fabric.FabricException
abgeleiteten Service Fabric-Ausnahmen - Von
System.SystemException
abgeleitete SystemExceptions- 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
- Alle von
Beispielimplementierung eines dienstseitigen Konverters für eine benutzerdefinierte Ausnahme
Das folgende Beispiel ist eine Referenzimplementierung von IExceptionConvertor
auf der Dienst- und Clientseite für einen bekannten Ausnahmetyp: 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
-Implementierung auf der Dienstseite: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; } }
Die tatsächliche Ausnahme, die während der Ausführung des Remotingaufrufs beobachtet wird, wird als Eingabe an TryConvertToServiceException
übergeben. Wenn der Typ der Ausnahme eine bekannt ist, sollte TryConvertToServiceException
die ursprüngliche Ausnahme in ServiceException
konvertieren und als Out-Parameter zurückgeben. Der Wert TRUE sollte zurückgegeben werden, wenn der ursprüngliche Ausnahmetyp bekannt ist und die ursprüngliche Ausnahme erfolgreich in eine ServiceException
konvertiert wird. Andernfalls ist der Wert „false“.
Eine Liste der inneren Ausnahmen auf der aktuellen Ebene sollte von GetInnerExceptions()
zurückgegeben werden.
IExceptionConvertor
-Implementierung auf der Clientseite: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
wird als Parameter zusammen mit der konvertierten innerException[s]
an TryConvertFromServiceException
übergeben. Wenn der Typ der tatsächlichen Ausnahme (ServiceException.ActualExceptionType
) bekannt ist, sollte der Konverter ein tatsächliches Ausnahmeobjekt aus der ServiceException
und den innerException[s]
erstellen.
IExceptionConvertor
-Registrierung auf der Dienstseite:Um Konvertierungen zu registrieren, muss
CreateServiceInstanceListeners
überschrieben werden, und die Liste derIExceptionConvertor
-Klassen muss beim Erstellen derRemotingListener
-Instanz übergeben werden.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
-Registrierung auf der Clientseite:Um Konverter zu registrieren, muss die Liste der
IExceptionConvertor
-Klassen beim Erstellen derClientFactory
-Instanz übergeben werden.Erstellen von ServiceProxyFactory
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Erstellen von ActorProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Hinweis
Wenn das Framework den Konverter für die Ausnahme findet, wird die konvertierte (tatsächliche) Ausnahme von AggregateException
umschlossen und an der Remoting-API (Proxy) ausgelöst. Wenn das Framework den Konverter nicht finden konnte, wird die ServiceException
, die alle Details der tatsächlichen Ausnahme enthält, von AggregateException
umschlossen und ausgelöst.
Upgrade eines vorhandenen Diensts zum Aktivieren von Datenvertragsserialisierung für Remotingausnahmen
Vorhandene Dienste müssen die folgende Reihenfolge beachten (Dienst zuerst), um das Upgrade zu erhalten. Die Nichteinhaltung der Reihenfolge kann zu Fehlverhalten in der Wiederholungslogik und der Ausnahmebehandlung führen.
Implementieren Sie die dienstseitigen
ExceptionConvertor
-Klassen für die gewünschten Ausnahmen (falls vorhanden). Aktualisieren Sie die Registrierungslogik des Remotinglisteners mitExceptionSerializationTechnique
und der Liste derIExceptionConvertor
-Klassen. Führen Sie ein Upgrade des vorhandenen Diensts aus, um die Serialisierungsänderungen der Ausnahme anzuwenden.Implementieren Sie die clientseitigen
ExceptionConvertor
-Klassen für die gewünschten Ausnahmen (falls vorhanden). Aktualisieren Sie die ProxyFactory-Erstellungslogik mitExceptionSerializationTechnique
und einer Liste mitIExceptionConvertor
-Klassen. Führen Sie ein Upgrade des vorhandenen Clients aus, um die Ausnahmeserialisierungsänderungen anzuwenden.