玩转GRPC(2)-状态码
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc
1. 前言
和Http协议一样,gRPC协议也提供了一组基础的状态码。
一般情况下,仅使用这组基础状态码就可以反应gPRC请求处理的所有错误信息。
2. 示例代码
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