Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

1. 前言

和Http协议一样,gRPC协议也提供了一组基础的状态码。
一般情况下,仅使用这组基础状态码就可以反应gPRC请求处理的所有错误信息。

2. 示例代码

grpc_status_error

server

var counter uint64 = 0

const (
    port = ":50051"
)

type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    fmt.Println("pb.HelloRequest", in.Name)
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        fmt.Printf("get metadata error")
    }
    for key, val := range md {
        fmt.Printf("%v:%v\n", key, val)
    }

    x := atomic.AddUint64(&counter, 1) % 3
    switch x {
    case 0:
        return &pb.HelloReply{Message: "Hello " + in.Name}, nil
    case 1:
        return nil, status.Error(codes.DataLoss, "--DataLoss--")
    default:
        return nil, status.Error(codes.Unauthenticated, "--Unauthenticated--")
    }
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    // Register reflection service on gRPC server.
    reflection.Register(s)

    log.Println("say_hello_grpc starting...")
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

client

func main() {
    conn, err := grpc.Dial("localhost:50051",
        grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    client := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := client.SayHello(ctx, &pb.HelloRequest{Name: "lily"})
    if err != nil {
        s := status.Convert(err)
        log.Printf("code:%v, message:%v\n", s.Code(), s.Message())
    } else {
        log.Printf("reply:%v\n", r.String())
    }
}
  • 也可以使用status.Code(err),直接得到code
  • 当 err == nil 时,code为codes.OK, 值为0

3. wireshark 抓包

wireshark 抓包gRPC参考
Analyzing gRPC messages using Wireshark

3.1 err == nil的情况


上图的情况是多个Frame包含在一个TCP报文中

3.2 err != nil 的情况


对比3.1和3.2的情况,能发现2个特点
* 1) 3.1比3.2的情况,response中多一个DATA Frame,用于返回helloworld.HelloReply
* 2) gRPC的status的code和message是通过HEADER Frame来传递的。

// 15 对应的就是 DataLoss
grpc-status: 15
grpc-message: "--DataLoss--"

参考资料

1.Status codes and their use in gRPC
2.Analyzing gRPC messages using Wireshark


微信公众号

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注