为了账号安全,请及时绑定邮箱和手机立即绑定

gRPC 可能出现零服务器消息吗?

gRPC 可能出现零服务器消息吗?

Go
白猪掌柜的 2023-06-19 14:12:02
在下面的gRPC客户端代码中,第二个是if必要的吗?status, err := cli.GetStatus(ctx, &empty.Empty{})if err != nil {    return err}if status == nil {    // this should NEVER happen - right?    return fmt.Errorf("nil Status result returned") }go 直觉上,为了以防万一,应该总是检查 nil 。但是,有一个运行时检查来捕获任何客户端到服务器的nil使用,例如status, err := cli.GetStatus(ctx, nil) // <- runtime errorif err != nil {    // "rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil"    return err}那么是否有类似的服务器到客户端运行时保证,从而消除检查的需要status == nil?
查看完整描述

2 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

使用人为的服务器示例进一步调查:


func (s *mygRPC) GetStatus(context.Context, *empty.Empty) (*pb.Status, error) {

    log.Println("cli: GetStatus()")


    //return &pb.Status{}, nil

    return nil, nil // <- can server return a nil status message (with nil error)

}

并测试客户端/服务器的反应:


客户:


ERROR: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

服务器:


2019/05/14 16:09:50 cli: GetStatus()

ERROR: 2019/05/14 16:09:50 grpc: server failed to encode response:  rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

因此,即使想要合法地返回一个 nil 值,gRPC传输也不会允许。


注意:服务器端代码仍在执行 - 正如预期的那样 - 但就客户端而言,调用gRPC失败了。


结论:有效的 ( err==nil) 服务器响应将始终返回有效的 ( 非nil) 消息。


编辑:


检查源代码可以揭示捕获消息的gRPC位置:nil


服务器.go

func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {

    data, err := encode(s.getCodec(stream.ContentSubtype()), msg)

    if err != nil {

        grpclog.Errorln("grpc: server failed to encode response: ", err)

        return err

    }

    // ...

}

rpc_util.go

func encode(c baseCodec, msg interface{}) ([]byte, error) {

    if msg == nil { // NOTE: typed nils will not be caught by this check

        return nil, nil

    }

    b, err := c.Marshal(msg)

    if err != nil {

        return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())

    }

    // ...

}

这一行的评论是关键:


if msg == nil { // NOTE: typed nils will not be caught by this check }

因此,如果要对我们的 typed-nil 使用 reflect,reflect.ValueOf(msg).IsNil()将返回true. 以下c.Marshal(msg)错误 - 调用无法向客户端发送消息响应。


查看完整回答
反对 回复 2023-06-19
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

是的,这永远不应该发生。GRPC 对此负责。



查看完整回答
反对 回复 2023-06-19
  • 2 回答
  • 0 关注
  • 126 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信