Omówienie serializacji wyjątków komunikacji zdalnie
Serializacja oparta na binaryFormatter nie jest bezpieczna, więc nie używaj klasy BinaryFormatter do przetwarzania danych. Aby uzyskać więcej informacji na temat implikacji zabezpieczeń, zobacz Deserializacja ryzyka w użyciu klasy BinaryFormatter i powiązanych typów.
Usługa Azure Service Fabric używa narzędzia BinaryFormatter do serializacji wyjątków. Począwszy od usługi ServiceFabric w wersji 9.0, serializacja oparta na umowie danych na potrzeby wyjątków komunikacji równorzędnej jest dostępna jako funkcja zgody. Zalecamy, aby wybrać serializacji wyjątków remoting usługi DataContract, wykonując kroki opisane w tym artykule.
Obsługa serializacji wyjątków remoting opartych na programie BinaryFormatter zostanie wycofana w przyszłości.
Włączanie serializacji kontraktu danych dla wyjątków komunikacji zdalnie
Uwaga
Serializacja kontraktu danych dla wyjątków komunikacji równorzędnej jest dostępna tylko w przypadku usług komunikacji równorzędnej v2/V2_1.
Aby włączyć serializacji kontraktu danych dla wyjątków komunikacji zdalnie:
Włącz serializację wyjątków komunikacji zdalną dataContract po stronie usługi przy użyciu
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
podczas tworzenia odbiornika komunikacji zdalnie.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") }; }
AktorService
Aby włączyć serializację wyjątków remoting usługi DataContract w usłudzeCreateServiceReplicaListeners()
aktora, przesłoń przez rozszerzenieActorService
.protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
Jeśli oryginalny wyjątek ma wiele poziomów wyjątków wewnętrznych, można kontrolować liczbę poziomów wyjątków wewnętrznych, które mają być serializowane, ustawiając wartość
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
.Włącz serializację wyjątków komunikacji zdalną usługi DataContract na kliencie przy użyciu
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
polecenia podczas tworzenia fabryki klienta.Tworzenie elementu ServiceProxyFactory
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient); });
AktorProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient); });
Serializacja wyjątków komunikacji wirtualnej DataContract konwertuje wyjątek do obiektu transferu danych (DTO) po stronie usługi. Obiekt DTO jest konwertowany z powrotem na wyjątek po stronie klienta. Użytkownicy muszą zarejestrować się
ExceptionConvertor
, aby przekonwertować żądane wyjątki na obiekty DTO i na odwrót.Struktura implementuje konwertery dla następującej listy wyjątków. Jeśli kod usługi użytkownika zależy od wyjątków spoza poniższej listy na potrzeby implementacji ponawiania i obsługi wyjątków, użytkownicy muszą implementować i rejestrować konwertery dla takich wyjątków.
- Wszystkie wyjątki usługi Service Fabric pochodzące z
System.Fabric.FabricException
- Wyjątek SystemExceptions pochodzący 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
- Wszystkie wyjątki usługi Service Fabric pochodzące z
Przykładowa implementacja konwertora po stronie usługi dla wyjątku niestandardowego
Poniższy przykład to implementacja referencyjna IExceptionConvertor
po stronie usługi i klienta dla dobrze znanego typu wyjątku . CustomException
Wyjątek 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
implementacja po stronie usługi :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; } }
Rzeczywisty wyjątek zaobserwowany podczas wykonywania wywołania komunikacji telefonicznej jest przekazywany jako dane wejściowe do TryConvertToServiceException
. Jeśli typ wyjątku jest dobrze znany, TryConvertToServiceException
należy przekonwertować oryginalny wyjątek na ServiceException
i zwrócić go jako parametr wyjściowy. Wartość true powinna zostać zwrócona, jeśli oryginalny typ wyjątku jest dobrze znany, a oryginalny wyjątek został pomyślnie przekonwertowany na ServiceException
. W przeciwnym razie wartość to false.
Lista wyjątków wewnętrznych na bieżącym poziomie powinna być zwracana przez GetInnerExceptions()
.
IExceptionConvertor
implementacja po stronie 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
parametr jest przekazywany jako parametr wraz TryConvertFromServiceException
z przekonwertowanym innerException[s]
elementem . Jeśli rzeczywisty typ wyjątku, ServiceException.ActualExceptionType
, jest znany, konwertujący powinien utworzyć rzeczywisty obiekt wyjątku z ServiceException
i innerException[s]
.
IExceptionConvertor
rejestracja po stronie usługi :Aby zarejestrować konwertery, należy je zastąpić,
CreateServiceInstanceListeners
a listaIExceptionConvertor
klas musi zostać przekazana podczas tworzeniaRemotingListener
wystąpienia.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") }; }
AktorService
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
rejestracja po stronie klienta :Aby zarejestrować konwertery
IExceptionConvertor
, lista klas musi zostać przekazana podczas tworzeniaClientFactory
wystąpienia.Tworzenie elementu ServiceProxyFactory
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Tworzenie aktoraProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Uwaga
Jeśli struktura znajdzie konwerter dla wyjątku, przekonwertowany (rzeczywisty) wyjątek jest owinięty wewnątrz AggregateException
i jest zgłaszany do interfejsu API komunikacji wirtualnej (proxy). Jeśli platforma nie może odnaleźć konwertora, to ServiceException
, który zawiera wszystkie szczegóły rzeczywistego wyjątku, jest opakowany wewnątrz AggregateException
i jest zgłaszany.
Uaktualnianie istniejącej usługi w celu włączenia serializacji kontraktów danych na potrzeby wyjątków komunikacji zdalnie
Aby uaktualnić istniejące usługi, należy wykonać następującą kolejność (najpierw usługa). Niepowodzenie wykonania tej kolejności może spowodować niewłaściwe zachowanie logiki ponawiania prób i obsługi wyjątków.
Zaimplementuj klasy po stronie
ExceptionConvertor
usługi dla żądanych wyjątków, jeśli istnieją. Zaktualizuj logikę rejestracji odbiornika komunikacji zdalnie za pomocąExceptionSerializationTechnique
polecenia i listęIExceptionConvertor
klas. Uaktualnij istniejącą usługę, aby zastosować zmiany serializacji wyjątków.Zaimplementuj klasy po stronie
ExceptionConvertor
klienta dla żądanych wyjątków, jeśli istnieją. Zaktualizuj logikę tworzenia proxyFactory za pomocąExceptionSerializationTechnique
polecenia i listęIExceptionConvertor
klas. Uaktualnij istniejącego klienta, aby zastosować zmiany serializacji wyjątków.