如何将 bufconn 包与 grpc.NewClient 一起使用?

问题描述 投票:0回答:1

我有一个类似于以下内容的单元测试(改编自https://github.com/castaneai/grpc-testing-with-bufconn/blob/master/server/server.go):

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    "google.golang.org/grpc/examples/helloworld/helloworld"
    "google.golang.org/grpc/test/bufconn"
)

func main() {
    lis := bufconn.Listen(1024 * 1024)
    s := grpc.NewServer()
    helloworld.RegisterGreeterServer(s, &server{})
    go func() {
        if err := s.Serve(lis); err != nil {
            log.Fatal(err)
        }
    }()

    conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(func(ctx context.Context, s string) (net.Conn, error) {
        return lis.Dial()
    }), grpc.WithInsecure())
    if err != nil {
        log.Fatalf("dial: %v", err)
    }

    client := helloworld.NewGreeterClient(conn)
    resp, err := client.SayHello(context.Background(), &helloworld.HelloRequest{
        Name: "Mary Contrary",
    })
    if err != nil {
        log.Fatalf("say hello: %v", err)
    }
    log.Println("response message:", resp.GetMessage())
}

type server struct {
    helloworld.UnimplementedGreeterServer
}

func (s *server) SayHello(_ context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
    log.Printf("Received: %v", in.Name)
    return &helloworld.HelloReply{
        Message: "Hello, " + in.Name,
    }, nil
}

当我运行它时,它会打印预期的输出:

> go run main.go
2024/05/15 10:20:19 Received: Mary Contrary
2024/05/15 10:20:19 response message: Hello, Mary Contrary

但是,

DialContext
已弃用并由
NewClient
取代。如果我尝试像这样替换它,

    conn, err := grpc.NewClient("bufnet", grpc.WithContextDialer(func(ctx context.Context, s string) (net.Conn, error) {
        return lis.Dial()
    }), grpc.WithInsecure())

程序现在出现错误:

> go run main.go
2024/05/15 10:17:37 say hello: rpc error: code = Unavailable desc = name resolver error: produced zero addresses
exit status 1

我怀疑这与此文档注释有关:

NewClient 与 Dial 和 DialContext 之间的一个细微差别是,前者使用“dns”作为默认名称解析器,而后者使用“passthrough”以实现向后兼容性。这种区别对于大多数用户来说并不重要,但对于指定自定义拨号器并希望它直接接收目标字符串的旧用户来说可能很重要。

确实,如果我看一下

DialContext
的定义,

func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
    // At the end of this method, we kick the channel out of idle, rather than
    // waiting for the first rpc.
    opts = append([]DialOption{withDefaultScheme("passthrough")}, opts...)
    cc, err := NewClient(target, opts...)
    if err != nil {
        return nil, err
    }
    ...

它似乎只是在后台调用

NewClient
并使用非导出选项覆盖默认方案。我怎样才能使用
NewClient
来运行这个示例?

go grpc grpc-go
1个回答
0
投票

事实证明,可以通过调用

resolver.SetDefaultScheme
来全局覆盖默认方案。完整更新的程序是:

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    "google.golang.org/grpc/examples/helloworld/helloworld"
    "google.golang.org/grpc/resolver"
    "google.golang.org/grpc/test/bufconn"
)

func main() {
    lis := bufconn.Listen(1024 * 1024)
    s := grpc.NewServer()
    helloworld.RegisterGreeterServer(s, &server{})
    go func() {
        if err := s.Serve(lis); err != nil {
            log.Fatal(err)
        }
    }()

    resolver.SetDefaultScheme("passthrough")
    conn, err := grpc.NewClient("bufnet", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
        return lis.Dial()
    }), grpc.WithInsecure())
    if err != nil {
        log.Fatalf("dial: %v", err)
    }

    client := helloworld.NewGreeterClient(conn)
    resp, err := client.SayHello(context.Background(), &helloworld.HelloRequest{
        Name: "Mary Contrary",
    })
    if err != nil {
        log.Fatalf("say hello: %v", err)
    }
    log.Println("response message:", resp.GetMessage())
}

type server struct {
    helloworld.UnimplementedGreeterServer
}

func (s *server) SayHello(_ context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
    log.Printf("Received: %v", in.Name)
    return &helloworld.HelloReply{
        Message: "Hello, " + in.Name,
    }, nil
}

再次打印预期输出:

> go run main.go
2024/05/15 11:34:34 Received: Mary Contrary
2024/05/15 11:34:34 response message: Hello, Mary Contrary
© www.soinside.com 2019 - 2024. All rights reserved.