遠端例外狀況序列化概觀
BinaryFormatter 型序列化並不安全,因此請勿使用 BinaryFormatter 進行資料處理。 如需安全性含意的詳細資訊,請參閱 使用 BinaryFormatter 和相關類型的還原序列化風險。
Azure Service Fabric 已使用 BinaryFormatter 將例外狀況序列化。 從 ServiceFabric v9.0 開始,遠端例外狀況的資料合約型序列化會以選擇加入功能的形式提供。 建議您依照本文中的步驟,選擇使用 DataContract 遠端處理例外狀況序列化。
未來將會淘汰 BinaryFormatter 型遠端例外狀況序列化的支援。
啟用遠端例外狀況的資料合約序列化
注意
遠端例外狀況的資料合約序列化僅適用於遠端 V2/V2_1 服務。
啟用遠端例外狀況的資料合約序列化:
在您建立遠端接聽程式時,使用
FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique
在 [服務] 端啟用 DataContract 遠端例外狀況序列化。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 遠端例外狀況序列化,請擴充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
來控制要序列化的內部例外狀況層級數目。在您建立 Client Factory 時,使用
FabricTransportRemotingSettings.ExceptionDeserializationTechnique
在 [用戶端] 上啟用 DataContract 遠端例外狀況序列化。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 遠端例外狀況序列化會將例外狀況轉換為服務端的資料傳輸物件 (DTO)。 DTO 會轉換成用戶端上的例外狀況。 使用者必須註冊
ExceptionConvertor
,才能將所需的例外狀況轉換為 DTO 物件,反之亦然。架構會針對下列例外狀況清單實作轉換器。 如果使用者服務程式碼在進行重試實作和例外狀況處理時,取決於下列清單以外的例外狀況,則使用者必須實作及註冊這類例外狀況的轉換器。
- 所有 Service Fabric 例外狀況衍生自
System.Fabric.FabricException
- SystemExceptions 衍生自
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
- 所有 Service Fabric 例外狀況衍生自
自訂例外狀況的服務端轉換器範例實作
以下範例是已知例外狀況類型 CustomException
的 [服務] 端和 [用戶] 端上的參考 IExceptionConvertor
實作,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
實作: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
會以參數形式傳遞至 TryConvertFromServiceException
,以及轉換的 innerException[s]
。 如果實際的例外狀況類型 ServiceException.ActualExceptionType
是已知的類型,則轉換器應該從 ServiceException
和 innerException[s]
建立實際的例外狀況物件。
在 [服務] 端的
IExceptionConvertor
註冊:若要註冊轉換程式,則必須覆寫
CreateServiceInstanceListeners
,而且您必須在建立RemotingListener
執行個體時傳遞類別清單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 (Proxy) 擲回。 如果架構找不到轉換器,則 ServiceException
(包含實際例外狀況的所有詳細資料) 會包裝在 AggregateException
內並加以擲回。
升級現有服務,以啟用資料合約序列化來進行遠端例外狀況
現有的服務必須遵循下列順序 (服務優先) 以進行升級。 若無法遵循此順序,可能會導致重試邏輯和例外狀況處理之錯誤行為。
請針對所需的例外狀況 (若有) 實作 [服務] 端
ExceptionConvertor
類別。 使用ExceptionSerializationTechnique
和IExceptionConvertor
類別清單更新遠端接聽程式註冊邏輯。 升級現有的服務以套用例外狀況序列化變更。請針對所需的例外狀況 (若有) 實作 [用戶] 端的
ExceptionConvertor
類別。 使用ExceptionSerializationTechnique
和IExceptionConvertor
類別清單來更新 ProxyFactory 建立邏輯。 升級現有的用戶端來套用例外狀況序列化變更。