gRPC 拦截器

前言

gRPC 的拦截器类似 .NET Core 中的中间件和过滤器,是AOP的的一种实现方式,非常适合做一些与业务无关的处理,譬如错误处理、日志记录、身份验证等。

拦截器类型

要自定义拦截器就必须继承 Interceptor 抽象类。它是所有拦截器的基类,它定义了几个可以重写的虚方法。

拦截器可以分为 一元拦截器流式拦截器,或者 客户端拦截器服务端拦截器

函数名 拦截类型 描述
BlockingUnaryCall 客户端 拦截非异步一元调用
AsyncUnaryCall 客户端 拦截一元异步调用
AsyncServerStreamingCall 客户端 拦截异步服务端流调用
AsyncClientStreamingCall 客户端 拦截客户端流式处理的异步调用
AsyncDuplexStreamingCall 客户端 拦截异步双向流调用
UnaryServerHandler 服务器 拦截普通一元调用
ClientStreamingServerHandler 服务器 拦截客户端流式调用
ServerStreamingServerHandler 服务器 拦截服务端流式处理
DuplexStreamingServerHandler 服务器 拦截双向流调用

服务端拦截器

拦截服务端一元调用只需要重写 UnaryServerHandler 就可以了。其他形式的服务器拦截器大致都是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public class TestInterceptor : Interceptor
{
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
UnaryServerMethod<TRequest, TResponse> continuation)
{
Console.WriteLine($"开始调用,请求参数: {request.SerializeObjects()}");
var reply = await continuation(request, context);
Console.WriteLine($"结束调用,返回结果{reply.SerializeObjects()}");
return reply;
}
}

UnaryServerHandler 中可以获取到详细的调用和处理信息,continuation 是一个委托,它负责调用下一个拦截器,或者调用处理程序,continuation 可以不需要等待,但是如果你需要添加处理结果后的结果可以等待完成。

还需要在 ConfigureServices 中注册拦截器:

1
services.AddGrpc(options => { options.Interceptors.Add<TestInterceptor>(); });

输出:

客户端拦截器

拦截客户端一元异步调用,重写 AsyncUnaryCall 方法:

1
2
3
4
5
6
7
8
9
10
public class TestInterceptor : Interceptor
{
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
Console.WriteLine($"开始调用RPC");
var call= base.AsyncUnaryCall(request, context, continuation);
Console.WriteLine($"调用RPC结束");
return call;
}
}

客户端:

1
2
3
4
5
6
7
8
9
10
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var channel = GrpcChannel.ForAddress("http://localhost:5000")
.Intercept(new TestInterceptor());

var client = new Greeter.GreeterClient(channel);
var response = client.SayHello(new HelloRequest
{
Name = "1"
});
Console.WriteLine($"{response.Message}");

IOC 方式:

1
2
services.AddGrpcClient<Greeter.GreeterClient>(options => { options.Address = new Uri("http://localhost:5000"); })
.AddInterceptor<TestInterceptor>()

输出:

AsyncUnaryCall 只能拦截异步的调用,如果是同步的是拦截不到的。

小结

拦截器可以方便我们组装自己请求处理管道,大大的提升灵活性。可以将与业务无关的内容抽离到拦截器中。拦截器的使用和中间件也是大同小异。


gRPC 拦截器
http://example.com/posts/23546.html
作者
她微笑的脸y
发布于
2022年8月25日
许可协议