【问题标题】:My gRPC client in a docker container doesn't work but the client outside the container go well我在 docker 容器中的 gRPC 客户端不起作用,但容器外的客户端运行良好
【发布时间】:2021-02-11 16:51:25
【问题描述】:

环境

$ protoc --version
libprotoc 3.7.1

$ docker-compose --version
docker-compose version 1.22.0, build f46880fe

$ docker --version
Docker version 20.10.0-beta1, build ac365d7

我想做什么

我想做一个由 gin-gonic 实现的微服务。

代码

$ tree
.
├── api
│   ├── Dockerfile
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   ├── pb
│   │   ├── proto
│   │   │   └── user.proto
│   │   ├── user_grpc.pb.go
│   │   └── user.pb.go
│   └── services
│       ├── README.md
│       └── user
│           ├── Dockerfile
│           ├── go.mod
│           ├── go.sum
│           ├── main.go
│           └── pb
│               ├── user_grpc.pb.go
│               └── user.pb.go
├── docker-compose.yml
├── make_pb.sh
└── README.md

如您所见,我现在有 2 个 Dockerfile。
api dir 中的 Dockefile 运行 gRPC 客户端程序。
用户目录中的另一个 Dockerfile 运行 gRPC 服务器程序。

api/main.go

package main

import (
    "context"
    "log"
    "os"
    "time"

    pb "github.com/Asuha-a/URLShortener/api/pb"
    "google.golang.org/grpc"
)

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

func main() {
    hello()
    //r := gin.Default()
    //r.GET("", hello)
    //r.Run()
}

func hello() {
    log.Println(grpc.WithBlock())
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    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.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := client.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}

api/services/user/main.go

package main

import (
    "context"
    "log"
    "net"

    pb "github.com/Asuha-a/URLShortener/api/services/user/pb"
    "google.golang.org/grpc"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
    log.Println("now listening")
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

docker-compose.yml

version: '3'

services:
  gateway:
    build:
      context: ./api/
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    tty:
      true
    depends_on:
      - user
  user:
    build:
      context: ./api/services/user
      dockerfile: Dockerfile
    ports:
      - 50051:50051
    tty:
      true

Dockerfile 具有相同的代码。

FROM golang:latest

RUN mkdir /go/src/work
WORKDIR /go/src/work
ADD . /go/src/work

CMD go run main.go

发生了什么

当我运行 docker-compose up 时,grpc.Dial 似乎不起作用。

日志在这里

$ docker-compose up              
Recreating urlshortener_user_1 ... done
Recreating urlshortener_gateway_1 ... done
Attaching to urlshortener_user_1, urlshortener_gateway_1
user_1     | go: downloading google.golang.org/grpc v1.33.1
user_1     | go: downloading google.golang.org/protobuf v1.25.0
user_1     | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/grpc v1.33.1
gateway_1  | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/protobuf v1.25.0
user_1     | go: downloading google.golang.org/genproto v0.0.0-20201028140639-c77dae4b0522
user_1     | go: downloading golang.org/x/net v0.0.0-20201029055024-942e2f445f3c
gateway_1  | go: downloading google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877
gateway_1  | go: downloading golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1
gateway_1  | go: downloading golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c
user_1     | go: downloading golang.org/x/sys v0.0.0-20201029020603-3518587229cd
user_1     | go: downloading golang.org/x/text v0.3.4
gateway_1  | go: downloading golang.org/x/text v0.3.4
user_1     | 2020/10/29 08:29:42 now listening
gateway_1  | 2020/10/29 08:29:43 true

这应该是打印的“问候:Hello world”。

我尝试了什么

当我在没有容器的情况下运行服务器和客户端时,它是成功的。

运行客户端

$ go run main.go 
2020/10/29 17:37:17 true
2020/10/29 17:38:02 Greeting: Hello world

运行服务器

$ go run main.go 
2020/10/29 17:38:00 now listening
2020/10/29 17:38:02 Received: world

当我在没有容器的情况下运行服务器并使用容器运行客户端时,它失败了。

运行客户端

$ docker-compose up              
Recreating urlshortener_gateway_1 ... done
Attaching to urlshortener_gateway_1
gateway_1  | go: downloading google.golang.org/protobuf v1.25.0
gateway_1  | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/grpc v1.33.1
gateway_1  | go: downloading google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877
gateway_1  | go: downloading golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1
gateway_1  | go: downloading golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c
gateway_1  | go: downloading golang.org/x/text v0.3.4
gateway_1  | 2020/10/29 08:40:47 true

运行服务器

$ go run main.go
2020/10/29 17:40:19 now listening

当我用客户端运行服务端,不带容器运行客户端,就成功了。

运行客户端

$ go run main.go 
2020/10/29 17:43:40 true
2020/10/29 17:43:41 Greeting: Hello world

运行服务器

$ docker-compose up
Removing urlshortener_user_1
Recreating 42fb18da11cf_urlshortener_user_1 ... done
Attaching to urlshortener_user_1
user_1  | go: downloading google.golang.org/grpc v1.33.1
user_1  | go: downloading google.golang.org/protobuf v1.25.0
user_1  | go: downloading github.com/golang/protobuf v1.4.3
user_1  | go: downloading golang.org/x/net v0.0.0-20201029055024-942e2f445f3c
user_1  | go: downloading google.golang.org/genproto v0.0.0-20201028140639-c77dae4b0522
user_1  | go: downloading golang.org/x/sys v0.0.0-20201029020603-3518587229cd
user_1  | go: downloading golang.org/x/text v0.3.4
user_1  | 2020/10/29 08:43:41 now listening
user_1  | 2020/10/29 08:43:41 Received: world

我想知道的

为什么在容器中运行客户端会失败?
如何解决?

【问题讨论】:

  • 容器中的Localhost和服务器运行的地方不一样
  • 天啊,我忘了。我将主机名 'localhost:50051' 更改为 'user:50051' 现在它可以工作了!谢谢!

标签: docker go docker-compose grpc


【解决方案1】:

此评论解决了问题。

容器中的本地主机与服务器运行的位置不同。 – 马特 14 分钟前

我修复了 api/main.go。

address = "localhost:50051" -> address = "user:50051"

现在可以了。
主机名必须是 docker-compose.yml 中指定的容器名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 2023-01-14
    • 2019-09-15
    • 2015-01-18
    • 1970-01-01
    相关资源
    最近更新 更多