GRPC中設置client的超時時間(golang)


在使用grpc的時候遇到了一個問題: 如何設置client端的超時時間? 網上搜了一大圈, 沒有太明顯的例子.

這里我們先看下看看grpc的helloworld例子:

client

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
func main() {  // Set up a connection to the server.  conn, err := grpc.Dial(address, grpc.WithInsecure())  if err != nil {  log.Fatalf("did not connect: %v", err)  }  defer conn.Close()  c := pb.NewGreeterClient(conn)   // Contact the server and print out its response.  name := defaultName  if len(os.Args) > 1 {  name = os.Args[1]  }  r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})  if err != nil {  log.Fatalf("could not greet: %v", err)  }  log.Printf("Greeting: %s", r.Message) } 

稍微跟一下SayHello的調用, 最后是調用到invoke函數:

google.golang.org/grpc/call.go

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
func invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (e error) {  c := defaultCallInfo  mc := cc.GetMethodConfig(method)  if mc.WaitForReady != nil {  c.failFast = !*mc.WaitForReady  }   // 值得注意  if mc.Timeout != nil && *mc.Timeout >= 0 {  var cancel context.CancelFunc  ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)  defer cancel()  }   opts = append(cc.dopts.callOptions, opts...)  for _, o := range opts {  if err := o.before(&c); err != nil {  return toRPCErr(err)  }  }  defer func() {  for _, o := range opts {  o.after(&c)  }  }() 

這里值得注意的是context的超時設置. 仔細讀下context的文檔, 會發現context里面有對應的超時設置:

WithTimeout

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
package main  import (  "context"  "fmt"  "time" )  func main() {  // Pass a context with a timeout to tell a blocking function that it  // should abandon its work after the timeout elapses.  ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)  defer cancel()   select {  case <-time.After(1 * time.Second):  fmt.Println("overslept")  case <-ctx.Done():  fmt.Println(ctx.Err()) // prints "context deadline exceeded"  } } 

我們嘗試在client調用之前設置context的超時:

client

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
func main() {  // Set up a connection to the server.  conn, err := grpc.Dial(address, grpc.WithInsecure())  if err != nil {  log.Fatalf("did not connect: %v", err)  }  defer conn.Close()  c := pb.NewGreeterClient(conn)   // Contact the server and print out its response.  name := defaultName  if len(os.Args) > 1 {  name = os.Args[1]  }   // 改一下  ctx, cancel := context.WithTimeout(context.Background(), 100 * time.Millisecond)  defer cancel()  r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})  if err != nil {  log.Fatalf("could not greet: %v", err)  }  log.Printf("Greeting: %s", r.Message) } 

為保證超時, 在sever代碼中休息一會兒:

server

1
2 3 4 5 
// SayHello implements helloworld.GreeterServer func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {  time.Sleep(1 * time.Second)  return &pb.HelloReply{Message: "Hello " + in.Name}, nil } 

分別運行client和server兩個程序, 會看見client端打印:

1
could not greet: rpc error: code = DeadlineExceeded desc = context deadline exceeded


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM