如何使用gRPC UnaryClientInterceptor中的`reply`参数?

问题描述 投票:0回答:1

来自 UnaryClientInterceptor

google.golang.org/grpc
 界面具有类似 

的签名
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply any, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error

我对此接口的理解是,在发出请求之前调用实现,从而允许在请求到达网络之前对其进行丰富和修改。

但是,我不理解

reply
参数,因为尚未发出请求。我是否误解了此接口的使用,或者即使我们实际上无法访问响应,也可以使用
reply
参数完成一些有趣的事情?

go interceptor grpc-go
1个回答
0
投票

进行 gRPC 调用后,您可以检查

reply
参数中的响应。

一元拦截器的参数之一是

invoker
函数,其类型为
UnaryInvoker
。在一元拦截器中,您应该调用此函数,如文档中所述:

invoker 是完成 RPC 的处理程序,拦截器负责调用它

并且

invoker
本身将
req
reply
作为参数。您可以调用调用者然后检查
reply

但是,如何检查它?

reply
接口的动态类型应该是指向 protobuffer 架构中定义的 gRPC 处理程序的返回类型的指针。您可以检查
method
的值来了解期望的返回类型。

为了进一步帮助您理解,您可以看一下

protoc
生成的代码。 gRPC 方法的实现显示了用于调用的实际参数是什么
Invoke

假设你有一个像这样的原型缓冲区:

package foo;

service MyService {
    rpc GetFoo(FooRequest) returns (FooResponse);
}

GetFoo
方法生成的代码将类似于:

func (c *myServiceClient) GetFoo(ctx context.Context, in *FooRequest, opts ...grpc.CallOption) (*FooResponse, error) {
    out := new(FooResponse)
    err := c.cc.Invoke(ctx, "/foo.MyService/GetFoo", in, out, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

因此您可以根据

reply
的值知道
method
的类型。从那时起,您可以获得以下示例一元拦截器:

grpc.WithUnaryInterceptor(func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
    // some interceptor logic
    err := invoker(ctx, method, req, reply, cc, opts...)
    if err != nil {
        // handle error
    }
    // here you can inspect reply before returning
    switch method {
    case "/foo.MyService/GetFoo":
        fooResp := reply.(*FooResponse)
        // access fields to do whatever you want
    }
    return nil
}),
© www.soinside.com 2019 - 2024. All rights reserved.