リモート処理例外のシリアル化の概要
BinaryFormatter ベースのシリアル化は安全ではないので、データ処理には BinaryFormatter を使わないでください。 セキュリティへの影響について詳しくは、「BinaryFormatter および関連する型を使用するときの逆シリアル化のリスク」をご覧ください。
Azure Service Fabric では、例外のシリアル化に BinaryFormatter が使われていました。 ServiceFabric v9.0 以降では、リモート処理例外に対するデータ コントラクト ベースのシリアル化をオプトイン機能として利用できます。 この記事の手順に従って、DataContract リモート処理例外のシリアル化を選ぶことをお勧めします。
BinaryFormatter ベースのリモート処理例外のシリアル化は、今後サポートされなくなります。
リモート処理例外でデータ コントラクトのシリアル化を有効にする
Note
リモート処理例外でのデータ コントラクトのシリアル化は、リモート処理 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
を設定することで、シリアル化する内部例外のレベル数を制御できます。クライアント ファクトリの作成時に
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 は、クライアント側で例外に変換されます。 ユーザーは、目的の例外を DTO オブジェクトに変換するために (逆の場合も同様)
ExceptionConvertor
を登録する必要があります。フレームワークにより、次の一覧の例外に対するコンバーターが実装されます。 ユーザー サービス コードが再試行の実装と例外処理のために次の一覧以外の例外に依存する場合、ユーザーはそのような例外用のコンバーターを実装して登録する必要があります。
System.Fabric.FabricException
から派生するすべての Service Fabric 例外System.SystemException
から派生する 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
カスタム例外のサービス側コンバーターの実装例
既知の例外の種類 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
の登録:コンバーターを登録するには、
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 (プロキシ) でスローされます。 フレームワークによってコンバーターが検出されない場合は、実際の例外のすべての詳細を含む ServiceException
が AggregateException
内でラップされ、スローされます。
既存のサービスをアップグレードして、リモート処理例外で DataContract シリアル化を有効にする
アップグレードするには、既存のサービスが以下の順序 ("サービス優先") になっている必要があります。 この順序に従っていない場合、再試行ロジックや例外処理で誤った動作が発生する可能性があります。
サービス側で、目的の例外 (存在する場合) の
ExceptionConvertor
クラスを実装します。ExceptionSerializationTechnique
でのリモート処理リスナー登録ロジックと、IExceptionConvertor
クラスのリストを更新します。 既存のサービスをアップグレードして、例外のシリアル化の変更を適用します。クライアント側で、目的の例外 (存在する場合) の
ExceptionConvertor
クラスを実装します。ExceptionSerializationTechnique
での ProxyFactory 作成ロジックと、IExceptionConvertor
クラスのリストを更新します。 既存のクライアントをアップグレードして、例外のシリアル化の変更を適用します。