版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://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
    1. 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


微信公众号