共用方式為


遠端例外狀況序列化概觀

BinaryFormatter 型序列化並不安全,因此請勿使用 BinaryFormatter 進行資料處理。 如需安全性含意的詳細資訊,請參閱 使用 BinaryFormatter 和相關類型的還原序列化風險

Azure Service Fabric 已使用 BinaryFormatter 將例外狀況序列化。 從 ServiceFabric v9.0 開始,遠端例外狀況的資料合約型序列化會以選擇加入功能的形式提供。 建議您依照本文中的步驟,選擇使用 DataContract 遠端處理例外狀況序列化。

未來將會淘汰 BinaryFormatter 型遠端例外狀況序列化的支援。

啟用遠端例外狀況的資料合約序列化

注意

遠端例外狀況的資料合約序列化僅適用於遠端 V2/V2_1 服務。

啟用遠端例外狀況的資料合約序列化:

  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 來控制要序列化的內部例外狀況層級數目。

  2. 在您建立 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);
      });
      
  3. 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

自訂例外狀況的服務端轉換器範例實作

以下範例是已知例外狀況類型 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 是已知的類型,則轉換器應該從 ServiceExceptioninnerException[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 內並加以擲回。

升級現有服務,以啟用資料合約序列化來進行遠端例外狀況

現有的服務必須遵循下列順序 (服務優先) 以進行升級。 若無法遵循此順序,可能會導致重試邏輯和例外狀況處理之錯誤行為。

  1. 請針對所需的例外狀況 (若有) 實作 [服務]ExceptionConvertor 類別。 使用 ExceptionSerializationTechniqueIExceptionConvertor 類別清單更新遠端接聽程式註冊邏輯。 升級現有的服務以套用例外狀況序列化變更。

  2. 請針對所需的例外狀況 (若有) 實作 [用戶] 端的 ExceptionConvertor 類別。 使用 ExceptionSerializationTechniqueIExceptionConvertor 類別清單來更新 ProxyFactory 建立邏輯。 升級現有的用戶端來套用例外狀況序列化變更。

下一步