在上一节我们使用gRPC实现了客户端和服务端的一对一通讯,也就是客户端向服务端发出一个请求,服务端返回一个结果。但是在很多场景下可能需要客户端向服务端连续发送多个请求后,服务端才能进行处理然后返回一个结果,例如客户端向服务端发送多个订单号,让服务端对订单号进行记录,然后服务端把所有订单号记录后返回结果;或者是客户端发送一个订单号查询所有大于给定订单号的交易记录,然后服务端返回满足条件的十几条记录等。
我们首先看看服务端给客户端返回多条记录的情形。在gRPC中,可以连续发送多条数据的对象叫stream,该对象支持异步发送,假设客户端要查询所有订单号大于10的交易记录,假设在服务端存储了满足条件的记录有20条,那么服务端可以先返回5条,等5分钟后再返回10条,然后等20分钟后再返回5条,因此客户端在接收记录时需要做相应的异步处理。
我们首先修改proto文件如下:
ervice OrderManagement {
rpc getOrder(google.protobuf.StringValue) returns(Order);
rpc searchOrders(google.protobuf.StringValue) returns (stream Order);
}
上面代码中的stream表明,当客户端通过searchOrders接口向服务器发出请求时,它需要通过stream对象来获取一系列从服务器返回的Order数据。按照上一节的方法再次编译proto文件后,我们看看它内容的改变,使用searchOrders作为关键字在生成的pb.go文件中查询我们可以看到如下内容:
type OrderManagementClient interface {
GetOrder(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*Order, error)
SearchOrders(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (OrderManagement_SearchOrdersClient, error)
}
。。。
type OrderManagement_SearchOrdersClient interface {
Recv() (*Order, error)
grpc.ClientStream
}
type orderManagementSearchOrdersClient struct {
grpc.ClientStream
}
func (x *orderManagementSearchOrdersClient) Recv() (*Order, error) {
m := new(Order)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
这段代码表明客户端在调用searchOrders接口时它会获得一个名为OrderManagement_SearchOrdersClient的对象,这个对象实现了一个接口叫Recv,我们不难猜测到时候客户端需要调用Recv()来接收服务端返回的一系列Order数据。继续往下查可以看到如下代码:
// OrderManagementServer is the server API for OrderManagement service.
type OrderManagementServer interface {
GetOrder(context.Context, *wrappers.StringValue) (*Order, error)
SearchOrders(*wrappers.StringValue, OrderManagement_SearchOrdersServer) error
}
。。。。
type OrderManagement_SearchOrdersServer interface {
Send(*Order) error
grpc.ServerStream
}
type orderManagementSearchOrdersServer struct {
g

最低0.47元/天 解锁文章
191

被折叠的 条评论
为什么被折叠?



