O Azure Service Fabric usava o BinaryFormatter para serializar exceções. A partir do ServiceFabric v9.0, a serialização baseada em contrato de dados para exceções na comunicação remota está disponibilizada como um recurso de aceitação. Recomendamos que você opte pela serialização de exceção de comunicação remota do DataContract seguindo as etapas deste artigo.
O suporte para serialização de exceção na comunicação remota baseada no BinaryFormatter será preterido no futuro.
Habilitar a serialização de contrato de dados para exceções na comunicação remota
Observação
A serialização de contrato de dados para exceções na comunicação remota só está disponível para serviços de comunicação remota V2/V2_1.
Para habilitar a serialização de contrato de dados para exceções na comunicação remota:
Habilite a serialização de exceção na comunicação remota do DataContract no lado do Serviço usando FabricTransportRemotingListenerSettings.ExceptionSerializationTechnique ao criar o ouvinte de comunicação remota.
StatelessService
C#
protectedoverride IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
returnnew[]
{
new ServiceInstanceListener(serviceContext =>
new FabricTransportServiceRemotingListener(
serviceContext,
this,
new FabricTransportRemotingListenerSettings
{
ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
}),
"ServiceEndpointV2")
};
}
StatefulService
C#
protectedoverride IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
returnnew[]
{
new ServiceReplicaListener(serviceContext =>
new FabricTransportServiceRemotingListener(
serviceContext,
this,
new FabricTransportRemotingListenerSettings
{
ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
}),
"ServiceEndpointV2")
};
}
ActorService
Para habilitar a serialização de exceção na comunicação remota do DataContract no serviço de ator, substitua CreateServiceReplicaListeners() estendendo ActorService.
Se a exceção original tiver vários níveis de exceções internas, você poderá controlar o número de níveis de exceções internas a serem serializados configurando FabricTransportRemotingListenerSettings.RemotingExceptionDepth.
Habilitar a serialização de exceção na comunicação remota do DataContract no Cliente usando FabricTransportRemotingSettings.ExceptionDeserializationTechnique ao criar o alocador de cliente.
Criação de ServiceProxyFactory
C#
var serviceProxyFactory = new ServiceProxyFactory(
(callbackClient) =>
{
returnnew FabricTransportServiceRemotingClientFactory(
new FabricTransportRemotingSettings
{
ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
},
callbackClient);
});
ActorProxyFactory
C#
var actorProxyFactory = new ActorProxyFactory(
(callbackClient) =>
{
returnnew FabricTransportActorRemotingClientFactory(
new FabricTransportRemotingSettings
{
ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
},
callbackClient);
});
A serialização de exceção de comunicação remota do DataContract converte uma exceção no DTO (objeto de transferência de dados) no lado do serviço. O DTO é convertido novamente em uma exceção no lado do cliente. Os usuários precisam registrar ExceptionConvertor para converter as exceções desejadas em objetos DTO e vice-versa.
A estrutura implementa conversores para a lista de exceções a seguir. Se o código de serviço do usuário depender de exceções fora da lista a seguir para implementação de repetição e tratamento de exceção, o usuário precisará implementar e registrar conversores para essas exceções.
Todas as exceções do Service Fabric derivadas de System.Fabric.FabricException
SystemExceptions derivadas de System.SystemException
Implementação de exemplo de um conversor do lado do serviço para uma exceção personalizada
O exemplo a seguir é uma implementação de referência IExceptionConvertor no lado do Serviço e do Cliente para um tipo de exceção CustomException bem conhecido.
Implementação de IExceptionConvertor no lado do Serviço:
C#
classCustomConvertorService : Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.IExceptionConvertor
{
public Exception[] GetInnerExceptions(Exception originalException)
{
return originalException.InnerException == null ? null : new Exception[] { originalException.InnerException };
}
publicboolTryConvertToServiceException(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 },
};
returntrue;
}
returnfalse;
}
}
A exceção real observada durante a execução da chamada de comunicação remota é passada como entrada para TryConvertToServiceException. Se o tipo da exceção for bem conhecido, TryConvertToServiceException deve converter a exceção original em ServiceException e retorná-la como um parâmetro de saída. Um valor true deverá ser retornado se o tipo de exceção original for bem conhecido e a exceção original for convertida com êxito em ServiceException. Caso contrário, o valor será false.
Uma lista de exceções internas no nível atual deve ser retornada por GetInnerExceptions().
Implementação de IExceptionConvertor no lado do Cliente:
C#
classCustomConvertorClient : Microsoft.ServiceFabric.Services.Remoting.V2.Client.IExceptionConvertor
{
publicboolTryConvertFromServiceException(ServiceException serviceException, out Exception actualException)
{
returnthis.TryConvertFromServiceException(serviceException, (Exception)null, out actualException);
}
publicboolTryConvertFromServiceException(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"]);
returntrue;
}
returnfalse;
}
publicboolTryConvertFromServiceException(ServiceException serviceException, Exception[] innerExceptions, out Exception actualException)
{
thrownew NotImplementedException();
}
}
ServiceException é passado como um parâmetro para TryConvertFromServiceException junto com o innerException[s] convertido. Se o tipo de exceção real, ServiceException.ActualExceptionType, for conhecido, o conversor deverá criar um objeto de exceção real do ServiceException e innerException[s].
Registro de IExceptionConvertor no lado do Serviço:
Para registrar conversores, CreateServiceInstanceListeners deve ser substituído e a lista de classes IExceptionConvertor deve ser passada enquanto você cria a instância RemotingListener.
StatelessService
C#
protectedoverride IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
returnnew[]
{
new ServiceInstanceListener(serviceContext =>
new FabricTransportServiceRemotingListener(
serviceContext,
this,
new FabricTransportRemotingListenerSettings
{
ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
},
exceptionConvertors: new[]
{
new CustomConvertorService(),
}),
"ServiceEndpointV2")
};
}
StatefulService
C#
protectedoverride IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
returnnew[]
{
new ServiceReplicaListener(serviceContext =>
new FabricTransportServiceRemotingListener(
serviceContext,
this,
new FabricTransportRemotingListenerSettings
{
ExceptionSerializationTechnique = FabricTransportRemotingListenerSettings.ExceptionSerialization.Default,
},
exceptionConvertors: new []
{
new CustomConvertorService(),
}),
"ServiceEndpointV2")
};
}
Registro de IExceptionConvertor no lado do Cliente:
Para registrar conversores, a lista de classes IExceptionConvertor deve ser passada enquanto você cria a instância ClientFactory.
Criação de ServiceProxyFactory
C#
var serviceProxyFactory = new ServiceProxyFactory(
(callbackClient) =>
{
returnnew FabricTransportServiceRemotingClientFactory(
new FabricTransportRemotingSettings
{
ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
},
callbackClient,
exceptionConvertors: new[]
{
new CustomConvertorClient(),
});
});
Criação de ActorProxyFactory
C#
var actorProxyFactory = new ActorProxyFactory(
(callbackClient) =>
{
returnnew FabricTransportActorRemotingClientFactory(
new FabricTransportRemotingSettings
{
ExceptionDeserializationTechnique = FabricTransportRemotingSettings.ExceptionDeserialization.Default,
},
callbackClient,
exceptionConvertors: new[]
{
new CustomConvertorClient(),
});
});
Observação
Se a estrutura encontrar o conversor para a exceção, a exceção convertida (real) será encapsulada em AggregateException e lançada na API (proxy) de comunicação remota. Se a estrutura não encontrar o conversor, então ServiceException, que contém todos os detalhes da exceção real, será encapsulado em AggregateException e será gerado.
Atualizar um serviço existente para habilitar a serialização do contrato de dados para exceções de comunicação remota
Os serviços existentes devem seguir a ordem a seguir (Serviço primeiro) para atualizar. A falha em seguir a ordem a seguir pode resultar em mau comportamento na lógica de repetição e tratamento de exceção.
Implemente as classes ExceptionConvertor do lado do Serviço para as exceções desejadas, se houver. Atualize a lógica de registro do ouvinte de comunicação remota com ExceptionSerializationTechnique e a lista de classes IExceptionConvertor. Atualize o serviço existente para aplicar as alterações de serialização de exceção.
Implemente as classes ExceptionConvertor do lado do Cliente para as exceções desejadas, se houver. Atualize a lógica de criação do ProxyFactory com ExceptionSerializationTechnique e a lista de classes IExceptionConvertor. Atualize o cliente existente para aplicar as alterações de serialização de exceção.
Este módulo explora o uso de exceções e o processo de tratamento de exceções em aplicativos de console C#. As atividades práticas fornecem experiência com a implementação de padrões de tratamento de exceções para vários cenários de codificação.