20

ASP.NET Core gRPC 拦截器 | Beck's Blog

 4 years ago
source link: http://beckjin.com/2019/12/22/grpc-interceptor/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ASP.NET Core gRPC 拦截器

发表于 2019-12-22

| 分类于 ASP.NET Core

| 阅读次数: 192

gRPC 作为一套独立的 RPC 框架,像拦截器这种功能当然也是不可或缺的,框架自带的拦截器更多是基于框架本身出发,对于 gRPC 来说最突出的就是需要支持各种不同 RPC 调用方式的拦截,如:简单 RPC 调用流式 RPC 调用,流式调用又分 客户端流式调用服务端流式调用双向流式调用,关于流式调用更多介绍可参考:ASP.NET Core gRPC 流式调用

拦截器分类

不论是基于 .NET Core 2.x 或 3.x,都需要依赖 Grpc.Core 这个 NuGet Package,Grpc.Core 中已提供拦截器(Interceptor 类)功能(不过如果使用的版本过低,可能不支持拦截器,我们之前经历过这个阶段)。拦截器中的方法分两类,分别作用于客户端(客户端向服务端发请求时拦截) 和 服务端(服务端接收到客户端请求时拦截)。

服务端相关拦截方法:

1
2
3
4
5
6
7
8
9
10
11
// 简单调用拦截
public virtual Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)

// 客户端流式调用拦截
public virtual Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, ServerCallContext context, ClientStreamingServerMethod<TRequest, TResponse> continuation)

// 服务端流式调用拦截
public virtual Task ServerStreamingServerHandler<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, ServerStreamingServerMethod<TRequest, TResponse> continuation)

// 双向流调用拦截
public virtual Task DuplexStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, DuplexStreamingServerMethod<TRequest, TResponse> continuation)

客户端相关拦截方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 同步简单调用拦截
public virtual TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)

// 异步简单调用拦截
public virtual AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)

// 异步服务端流式调用拦截
public virtual AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncServerStreamingCallContinuation<TRequest, TResponse> continuation)

// 异步客户端流式调用拦截
public virtual AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> context, AsyncClientStreamingCallContinuation<TRequest, TResponse> continuation)

// 异步双向流调用拦截
public virtual AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> context, AsyncDuplexStreamingCallContinuation<TRequest, TResponse> continuation)

服务端拦截器实现

创建 ServerInterceptor 继承于抽象类 Interceptor,这里通过实现简单调用的服务端拦截方法 UnaryServerHandler 进行说明,最终需按实际开发情况实现更多拦截方法。

1
2
3
4
5
6
7
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
{
Console.WriteLine("服务端执行开始");
var response = await continuation(request, context);
Console.WriteLine("服务端执行结束");
return response;
}

客户端拦截器实现

创建 ClientInterceptor 继承于抽象类 Interceptor,这里通过实现 同步/异步 客户端简单调用的拦截方法 BlockingUnaryCallAsyncUnaryCall 进行说明,最终需按实际开发情况实现更多拦截方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public override TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
{
Console.WriteLine("客户端调用执行开始");
var response = continuation(request, context);
Console.WriteLine("客户端调用执行结束");
return response;
}

public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
Console.WriteLine("客户端调用执行开始");
var responseCon = continuation(request, context);
var response = new AsyncUnaryCall<TResponse>(responseCon.ResponseAsync, responseCon.ResponseHeadersAsync, responseCon.GetStatus, responseCon.GetTrailers, responseCon.Dispose);
Console.WriteLine("客户端调用执行结束");
return response;
}

拦截器配置

.NET Core 3.0 后配置方式如下:

服务端配置拦截器可通过在 ConfigureServices 中通过 services.AddGrpc 中的 GrpcServiceOptions 来指定 Interceptors,如下:

1
2
3
4
services.AddGrpc(options =>
{
options.Interceptors.Add<ServerInterceptor>();
});

客户端配置拦截通过 channelIntercept 方法,如下:

1
2
3
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var invoker = channel.Intercept(new ClientInterceptor());
var client = new Greeter.GreeterClient(invoker);

服务端和服务端拦截器的配置都可支持多个,如果同时指定多个拦截器会按照添加顺序依次执行

result
如果对你有帮助就好

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK