원격 예외 직렬화 개요
BinaryFormatter 기반 직렬화는 안전하지 않으므로 데이터 처리에 BinaryFormatter를 사용하지 마세요. 보안에 미치는 영향에 대한 자세한 내용은 BinaryFormatter 및 관련 형식을 사용할 때의 역직렬화 위험을 참조하세요.
Azure Service Fabric은 예외를 직렬화하기 위해 BinaryFormatter를 사용했습니다. ServiceFabric v9.0부터 원격 예외를 위한 데이터 계약 기반 serialization이 옵트인 기능으로 제공됩니다. 이 문서의 단계에 따라 DataContract 원격 예외 serialization을 선택하는 것이 좋습니다.
BinaryFormatter 기반 원격 예외 serialization에 대한 지원은 향후 더 이상 사용되지 않습니다.
원격 예외에 대한 데이터 계약 serialization을 사용하도록 설정
참고 항목
원격 예외에 대한 데이터 계약 serialization은 원격 V2/V2_1 서비스에만 사용할 수 있습니다.
원격 예외에 대한 데이터 계약 serialization을 사용하도록 설정하려면 다음을 수행합니다.
원격 수신기를 만드는 동안
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
을 사용하여 서비스 측에서 DataContract 원격 예외 serialization을 사용하도록 설정합니다.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
작업자 서비스에서 DataContract 원격 예외 serialization을 사용하도록 설정하려면ActorService
를 확장하여CreateServiceReplicaListeners()
를 재정의합니다.protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() { return new List<ServiceReplicaListener> { new ServiceReplicaListener(_ => { return new FabricTransportActorServiceRemotingListener( this, new FabricTransportRemotingListenerSettings { ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default, }); }, "MyActorServiceEndpointV2") }; }
원래 예외에 여러 수준의 내부 예외가 있는 경우
FabricTransportRemotingListenerSettings.RemotingExceptionDepth
를 설정하여 직렬화할 내부 예외 수준 수를 제어할 수 있습니다.클라이언트 팩터리를 만드는 동안
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
을 사용하여 클라이언트에서 DataContract 원격 예외 serialization을 사용하도록 설정합니다.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 원격 예외 serialization은 예외를 서비스 쪽의 DTO(데이터 전송 개체)로 변환합니다. DTO는 클라이언트 쪽에서 예외로 다시 변환됩니다. 사용자는 원하는 예외를 DTO 개체로 또는 그 반대로 변환하려면
ExceptionConvertor
를 등록해야 합니다.프레임워크는 다음 예외 목록에 대한 변환기를 구현합니다. 사용자 서비스 코드가 다시 시도 구현, 예외 처리 등을 위해 다음 목록 외부의 예외에 의존하는 경우 사용자는 이러한 예외에 대한 변환기를 구현 및 등록해야 합니다.
System.Fabric.FabricException
에서 파생된 모든 Service Fabric 예외System.SystemException
에서 파생된 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
사용자 지정 예외에 대한 서비스 측 변환기의 샘플 구현
다음 예제는 잘 알려진 예외 형식 CustomException
에 대한 서비스 및 클라이언트 측의 참조 IExceptionConvertor
구현입니다.
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
구현: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; } }
원격 호출을 실행하는 동안 관찰된 실제 예외는 TryConvertToServiceException
에 대한 입력으로 전달됩니다. 예외 형식이 잘 알려진 형식이면 TryConvertToServiceException
은 원래 예외를 ServiceException
으로 변환하고 이를 out 매개 변수로 반환해야 합니다. 원래 예외 형식이 잘 알려진 형식이고 원래 예외가 성공적으로 ServiceException
으로 변환되면 true 값이 반환되어야 합니다. 그렇지 않으면 값은 false입니다.
현재 수준의 내부 예외 목록은 GetInnerExceptions()
에 의해 반환되어야 합니다.
클라이언트 측에서
IExceptionConvertor
구현: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
은 변환된 innerException[s]
와 함께 TryConvertFromServiceException
에 매개 변수로 전달됩니다. 실제 예외 형식(ServiceException.ActualExceptionType
)이 알려진 형식인 경우 변환기는 ServiceException
및 innerException[s]
에서 실제 예외 개체를 만들어야 합니다.
서비스 측에서
IExceptionConvertor
등록:변환기를 등록하려면
RemotingListener
인스턴스를 만드는 동안CreateServiceInstanceListeners
를 재정의하고IExceptionConvertor
클래스 목록을 전달해야 합니다.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
등록:변환기를 등록하려면
ClientFactory
인스턴스를 만드는 동안IExceptionConvertor
클래스 목록을 전달해야 합니다.ServiceProxyFactory 만들기
var serviceProxyFactory = new ServiceProxyFactory( (callbackClient) => { return new FabricTransportServiceRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
ActorProxyFactory 만들기
var actorProxyFactory = new ActorProxyFactory( (callbackClient) => { return new FabricTransportActorRemotingClientFactory( new FabricTransportRemotingSettings { ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default, }, callbackClient, exceptionConvertors: new[] { new CustomConvertorClient(), }); });
참고 항목
프레임워크가 예외에 대한 변환기를 찾으면 변환된 예외(실제 예외)가 AggregateException
내부에 래핑되고 원격 API(프록시)에서 throw됩니다. 프레임워크가 변환기를 찾지 못하면 실제 예외의 모든 세부 정보를 포함하는 ServiceException
이 AggregateException
내부에 래핑되고 throw됩니다.
원격 예외에 대한 데이터 계약 serialization을 사용하도록 설정하도록 기존 서비스 업그레이드
기존 서비스를 업그레이드하려면 다음 순서(서비스 우선)를 따라야 합니다. 이 순서를 따르지 않으면 다시 시도 논리 및 예외 처리에서 오작동이 발생할 수 있습니다.
원하는 예외에 대해 서비스 측
ExceptionConvertor
클래스를 구현합니다(있는 경우).ExceptionSerializationTechnique
및IExceptionConvertor
클래스 목록을 사용하여 원격 수신기 등록 논리를 업데이트합니다. 예외 serialization 변경 내용을 적용하려면 기존 서비스를 업그레이드합니다.원하는 예외에 대해 클라이언트 측
ExceptionConvertor
클래스를 구현합니다(있는 경우).ExceptionSerializationTechnique
및IExceptionConvertor
클래스 목록을 사용하여 ProxyFactory 만들기 논리를 업데이트합니다. 예외 serialization 변경 내용을 적용하려면 기존 클라이언트를 업그레이드합니다.