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 klasy BinaryFormatter do serializacji wyjątków. Począwszy od usługi ServiceFabric w wersji 9.0, serializacja oparta na kontrakcie danych dla wyjątków komunikacji równorzędnej jest dostępna jako funkcja zgody. Zalecamy, aby wybrać serializacji wyjątków komunikacji zdalnie usługi DataContract, wykonując kroki opisane w tym artykule.
Obsługa serializacji wyjątków komunikacji zdalnie opartej na programie BinaryFormatter zostanie wycofana w przyszłości.
Włączanie serializacji kontraktu danych dla wyjątków komunikacji zdalniej
Uwaga
Serializacja kontraktu danych dla wyjątków komunikacji wirtualnej jest dostępna tylko w przypadku usług komunikacji zdalniej w wersji 2/V2_1.
Aby włączyć serializacji kontraktu danych dla wyjątków komunikacji zdalnie:
Włącz serializację wyjątków remotingu dataContract po stronie usługi przy użyciu
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
podczas tworzenia odbiornika komunikacji zdalniej.Bezstanowa usługa
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
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 do serializacji przez ustawienie
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
.Włącz serializacji wyjątków komunikacji zdalniej 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); });
ActorProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient); });
Serializacja wyjątku 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 konwertory 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 do obsługi ponawiania prób i obsługi wyjątków, użytkownicy muszą zaimplementować i zarejestrować 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 metody 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 zostanie pomyślnie przekonwertowany na ServiceException
. W przeciwnym razie wartość to false.
Lista wyjątków wewnętrznych na bieżącym poziomie powinna zostać zwrócona 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 do TryConvertFromServiceException
parametru wraz 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 rejestrować konwertery, należy je zastąpić,
CreateServiceInstanceListeners
a listaIExceptionConvertor
klas musi zostać przekazana podczas tworzeniaRemotingListener
wystąpienia.Bezstanowa usługa
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
rejestracja po stronie klienta :Aby zarejestrować konwertery, należy przekazać listę
IExceptionConvertor
klas 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 opakowany wewnątrz AggregateException
i jest zgłaszany do interfejsu API komunikacji wirtualnej (proxy). Jeśli platforma nie może odnaleźć konwertera, 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 kontraktu danych dla wyjątków komunikacji sieciowej
Aby uaktualnić istniejące usługi, należy wykonać następującą kolejność (najpierw usługa). Błąd 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ą poleceniaExceptionSerializationTechnique
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 serwera ProxyFactory za pomocą poleceniaExceptionSerializationTechnique
i listęIExceptionConvertor
klas. Uaktualnij istniejącego klienta, aby zastosować zmiany serializacji wyjątków.