我想知道是否有办法拥有Grpc。Net Core将服务器端的原始异常抛出给客户端。
问题如下。调用grpc服务时,例如:
客户:
using (var channel = GrpcChannel.ForAddress("http://localhost:10042"))
{
var greeterService = channel.CreateGrpcService<IGreetService>();
var result = await greeterService.Greet();
Console.WriteLine(result.Greet);
}
服务器:
public async Task<Greeting> Greet()
{
throw new ArgumentException();
}
运行此操作时,会引发以下RpcException:
Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler.")'
现在,我非常希望在客户端实际引发ArgumentException,以便更好地处理此问题。
我想,可能的是在我的Startup.cs中做以下事情:
services.AddCodeFirstGrpc(options => options.EnableDetailedErrors = true);
结果:
Grpc.Core.RpcException: 'Status(StatusCode=Unknown, Detail="Exception was thrown by handler. ArgumentException: Value does not fall within the expected range.")'
这更好,但仍然不完美。
我的问题是-我能以某种方式在客户端引发服务器异常吗?我读到的是grpc允许";拦截器";以拦截grpc调用。这有可能在这里做点什么吗?
您可以设置一个Interceptor来捕获服务器端异常,序列化异常元数据,并将其打包到自定义RpcException
中。客户端可以从RpcException
反序列化元数据并重新创建异常。
下面是我发现的一篇博客文章,它贯穿了整个过程:ASP gRPC自定义错误处理
正如你所能想象的那样,不利的一面是,每一个例外都需要这样做。我也一直在研究同一个问题,但没有找到任何简单的方法将其应用于所有例外。
配置拦截器:
services.AddGrpc(options =>
{
options.Interceptors.Add<GRPCInterceptor>();
});
裸骨拦截器:
public class GRPCInterceptor : Interceptor
{
private readonly ILogger logger;
public GRPCInterceptor(ILogger logger)
{
this.logger = logger;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
{
logger.Debug($"starting call");
var response = await base.UnaryServerHandler(request, context, continuation);
logger.Debug($"finished call");
return response;
}
}