gRCP拦截C#中的调用

时间:2019-04-11 10:15:50

标签: c# grpc

我在C#(NETCore)中使用gRPC。我想记录每个方法调用,并且我希望可以有某种方式一次插入每个调用,而不是在每个服务方法上都记录一个日志。没找到方法,但是不存在某种拦截策略?

2 个答案:

答案 0 :(得分:2)

要使用 Grpc.Core 创建客户端拦截器,您可以执行以下操作:

var clientInterceptor = new YourClientInterceptor();
var channel = new Channel($"localhost", ChannelCredentials.Insecure);
var interceptingInvoker = channel.Intercept(clientInterceptor);
var client = = new YourServiceClient(interceptingInvoker);

请注意 channel.Intercept(clientInterceptor) 如何返回一个新的调用程序供您传递给客户端。那里的命名有点不直观,但这就是我们现在所拥有的。

要拦截客户端调用,请让拦截器覆盖/实现您需要的所有 ...Call 方法,例如 BlockingUnaryCall(...)AsyncUnaryCall(...)

答案 1 :(得分:1)

可以为客户端和服务器端定义自定义拦截器。在这两种情况下,您都需要创建一个继承自Interceptor类的新类,并覆盖要拦截的方法。对于客户端,拦截器与整个客户端类连接。在服务器端拦截器仅针对服务定义创建-这意味着,如果要使用日志记录拦截器,则需要为每个服务定义指定拦截器。另外,对于客户端,您可以使用带有Func的已有扩展方法作为参数,该参数可以用于直接截获场景(我不会向您显示代码,因为我现在无法访问它) )。

下面有一个简单的拦截器:

public class GlobalServerLoggerInterceptor : Interceptor
{
    private readonly ILogger logger;

    public GlobalServerLoggerInterceptor(ILogger logger)
    {
        this.logger = logger;
    }

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
    {
        logger.Debug($"{Environment.NewLine}GRPC Request{Environment.NewLine}Method: {context.Method}{Environment.NewLine}Data: {JsonConvert.SerializeObject(request, Formatting.Indented)}");

        var response = await base.UnaryServerHandler(request, context, continuation);

        logger.Debug($"{Environment.NewLine}GRPC Response{Environment.NewLine}Method: {context.Method}{Environment.NewLine}Data: {JsonConvert.SerializeObject(response, Formatting.Indented)}");

        return response;
    }
}

服务器端拦截器的初始化(伪代码):

   var server = new Grpc.Core.Server
            {
                Services =
                {

TestService.BindService(new TestImplementationService()).Intercept(IoC.Resolve<GlobalServerLoggerInterceptor>())
                },
                Ports = { new ServerPort("localhost", 1234, ServerCredentials.Insecure) }
            };

在上面的示例中,您可能会注意到这样的声明:

.Intercept(IoC.Resolve<GlobalServerLoggerInterceptor>())

如果拦截器需要引用某些其他类,则需要在运行服务器之前对其进行初始化。