zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Ubuntu apt-get update 失败
    Ubuntu无法访问windows分区
    Python实现使用tkinter弹出输入框输入数字, 具有确定输入和清除功能
    如何更改监控器的默认计数器
    健壮的 Java 基准测试
    从虚拟机视角谈 Java 应用性能优化
    LoadRunner如何调用外部函数
    git安装与上传
    Loadrunner安装与破解【转】
    性能测试方法【转】
  • 原文地址:https://www.cnblogs.com/ExMan/p/12119025.html
Copyright © 2011-2022 走看看