首页 文章

使用Go gRPC为对等连接指定截止日期 .

提问于
浏览
4

根据gRPC文档,客户可以指定deadlines来确定客户端在退出 DEADLINE_EXCEEDED 错误之前在服务器上等待的时间 . 该文档提到不同的语言具有不同的实现,并且某些语言没有默认值 .

实际上,Go gRPC documentation上"deadline"的快速CTRL F显示没有结果 . 我发现的是用于TCP连接的拨号器上的WithTimeout .

实现如下(来自helloworld example):

package main

import (
    "log"
    "os"
    "time"

    "golang.org/x/net/context"
    "google.golang.org/grpc"
    pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
    deadline    = 20 
)

func main() {
    // Set up a connection to the server with a timeout 
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithTimeout(time.Duration(deadline)*time.Second)
    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)
}

仅当客户端在20秒后无法连接时,代码才会引发错误 . 输出将如下所示:

2016/05/24 09:02:54 grpc: Conn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp [::1]:3265: getsockopt: connection refused"; Reconnecting to "localhost:3265"
2016/05/24 09:02:54 Failed to dial localhost:3265: grpc: timed out trying to connect; please retry.
2016/05/24 09:02:54 could not greet: rpc error: code = 2 desc = grpc: the client connection is closing

正如问题 Headers 中所述,系统实际上正在寻找截止日期,因为如果远程连接,但服务器需要> 20秒才能响应,则 WithTimeout 上下文中不会引发异常 .

对我来说完全胜利的是超时/截止日期系统,其中:

  • 如果客户端无法连接,则超时后会返回错误

  • 如果客户端连接,但服务器在超时之前没有响应,则返回错误 .

  • 如果客户端连接,但连接在超时之前丢失,则返回错误 .

我的感觉是,我需要一些连接管理和gRPC截止日期管理的组合 . 有谁知道如何在Go中实现最后期限?

2 回答

  • 0

    根据context context的例子

    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"
        }
    }
    

    您可以将 helloworld example 客户端代码更改为100毫秒超时:

    ctx, _ := context.WithTimeout(context.Background(), 100 * time.Millisecond)
    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)
    
  • 1

    您应该更仔细地查看 context 包 . GRPC是以背景为基础构建的 . 您可能需要 Build 相关信息 grpc.Dial 上下文和 client.SayHello 上下文,但这应该是相当直接的 .

相关问题