Información general sobre la serialización de excepciones de comunicación remota
La serialización basada en BinaryFormatter no es segura, por lo que no use BinaryFormatter para el procesamiento de datos. Para más información sobre las implicaciones de seguridad, consulte Riesgos de deserialización en el uso de BinaryFormatter y tipos relacionados.
Azure Service Fabric utilizó BinaryFormatter para serializar excepciones. A partir de ServiceFabric v9.0, la serialización basada en el contrato de datos para excepciones de comunicación remota está disponible como una característica opcional. Se recomienda optar por la serialización de excepciones de comunicación remota de DataContract, siguiendo los pasos de este artículo.
La compatibilidad con la serialización de excepciones de comunicación remota basada en BinaryFormatter quedará en desuso en el futuro.
Habilitar la serialización de contratos de datos para excepciones de comunicación remota
Nota:
La serialización de contratos de datos para excepciones de comunicación remota solo está disponible para los servicios de comunicación remota V2/V2_1.
Para habilitar la serialización de contratos de datos para excepciones de comunicación remota:
Habilite la serialización de excepciones de comunicación remota de DataContract en el lado del Servicio mediante la instrucción
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
al crear el agente de escucha de comunicación 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
Para habilitar la serialización de excepciones de comunicación remota de DataContract en el servicio del actor, invalideCreateServiceReplicaListeners()
mediante la ampliación deActorService
.protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
Si la excepción original tiene varios niveles de excepciones internas, puede controlar el número de niveles de las excepciones internas que se van a serializar estableciendo
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
.Habilite la serialización de excepciones de comunicación remota de DataContract en el Cliente mediante la instrucción
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
al crear la fábrica de cliente.Creación 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 serialización de excepciones de comunicación remota de DataContract convierte una excepción al objeto de transferencia de datos (DTO) en el lado del servicio. El DTO se convierte de nuevo en una excepción en el lado del cliente. Los usuarios deben registrar
ExceptionConvertor
para convertir las excepciones deseadas en objetos DTO y viceversa.El marco implementa los convertidores en la siguiente lista de excepciones. Si el código de servicio del usuario depende de excepciones que no están en la siguiente lista para la implementación de reintentos y el control de excepciones, los usuarios deben implementar y registrar los convertidores para dichas excepciones.
- Todas las excepciones de Service Fabric derivadas de
System.Fabric.FabricException
- Excepciones del sistema derivadas 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
- Todas las excepciones de Service Fabric derivadas de
Implementación de muestra del convertidor del lado del servicio pq4q una excepción personalizada
El ejemplo siguiente muestra la implementación de referencia IExceptionConvertor
en el lado del Servicio y del Cliente para un tipo de excepción muy conocido: 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; } }
Implementación de
IExceptionConvertor
en el lado del Servicio: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; } }
La excepción como tal observada durante la ejecución de la llamada de comunicación remota se pasa como entrada a TryConvertToServiceException
. Si el tipo de excepción es uno bien conocido, TryConvertToServiceException
debe convertir la excepción original en ServiceException
y devolverla como parámetro de salida. Se debe devolver un valor “true” si el tipo de excepción original es conocido y si la excepción original se convierte correctamente en ServiceException
. En caso contrario, el valor es false.
Una lista de excepciones internas en el nivel actual debe devolverse mediante GetInnerExceptions()
.
Implementación de
IExceptionConvertor
en el lado del Cliente: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
se pasa como parámetro a TryConvertFromServiceException
junto con innerException[s]
convertido. Si el tipo de excepción como tal, ServiceException.ActualExceptionType
, es conocido, el convertidor debe crear un objeto de excepción como tal a partir de ServiceException
y innerException[s]
.
Registro de
IExceptionConvertor
en el lado del Servicio:Para registrar los convertidores,
CreateServiceInstanceListeners
se debe invalidar y se debe pasar la lista de clasesIExceptionConvertor
mientras crea la instanciaRemotingListener
.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") }; }
Registro de
IExceptionConvertor
en el lado del Cliente:Para registrar los convertidores, se debe pasar la lista de clases
IExceptionConvertor
mientras crea la instanciaClientFactory
.Creación de ServiceProxyFactory
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Creación de ActorProxyFactory
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
Nota
Si el marco encuentra el convertidor para la excepción, la excepción convertida como tal se ajusta dentro de AggregateException
y se lanza a la API de comunicación remota (proxy). Si el marco no encuentra el convertidor, entonces ServiceException
, que contiene todos los detalles de la excepción como tal, se ajusta dentro de AggregateException
y se lanza.
Actualice un servicio existente para habilitar la serialización de contrato de datos para excepciones de comunicación remota
Los servicios existentes deben seguir el orden siguiente (Primero el servicio) para actualizarse. Si no se sigue este orden, podría producirse un error de comportamiento en la lógica de reintentos y en el control de excepciones.
Del lado del Servicio, implemente las clases
ExceptionConvertor
para las excepciones deseadas, si las hay. Actualice la lógica de registro del agente de escucha de comunicación remota conExceptionSerializationTechnique
y la lista de clasesIExceptionConvertor
. Actualice el servicio existente para aplicar los cambios de serialización de excepciones.Del lado del Cliente, implemente las clases
ExceptionConvertor
para las excepciones deseadas, si las hay. Actualice la lógica de creación de ProxyFactory conExceptionSerializationTechnique
y la lista de clasesIExceptionConvertor
. Actualice el cliente existente para aplicar los cambios de serialización de excepciones.