使用gRPC在容器之间进行通信

huangapple go评论128阅读模式
英文:

Use gRPC to communicate between containers

问题

我正在实现两个服务(服务器和客户端),它们运行在两个不同的容器中,并尝试使用gRPC进行通信。

如果我将服务器部署为容器,并在非容器环境下运行客户端,一切都正常。但是,如果我将客户端部署在另一个容器中,我会遇到Error #01: could not retrieve restaurant's list: rpc error: code = Unavailable desc = grpc: the connection is unavailable错误。

我错过了哪些步骤来使用gRPC通信两个不同的容器?

PS:目前我想先尝试不使用Kubernetes。

服务器

  1. func Serve() {
  2. log.Println("serving...")
  3. port := ":50051"
  4. lis, err := net.Listen("tcp", port)
  5. if err != nil {
  6. log.Fatalf("failed to listen on port %s: %v", port, err)
  7. }
  8. s := grpc.NewServer()
  9. server := server{}
  10. RegisterNeo4BaconServer(s, server)
  11. if err := s.Serve(lis); err != nil {
  12. log.Fatal("could not serve: ", err)
  13. }
  14. }

Makefile

  1. image: ## build docker image and push image to registry
  2. @docker build -t neo4bacon -f resources/prod/Dockerfile .
  3. run: ## deploy application container
  4. @docker run --rm -d --name neo4bacon neo4bacon

客户端

  1. func Get() (*api.RestaurantList, error) {
  2. // Neo4bacon 后端
  3. backendPort := ":50051"
  4. conn, err := grpc.Dial(backendPort, grpc.WithInsecure())
  5. if err != nil {
  6. return &api.RestaurantList{}, fmt.Errorf("could not connect to backend %s: %s", backendPort, err)
  7. }
  8. defer conn.Close()
  9. client := api.NewNeo4BaconClient(conn)
  10. restaurantList, err := client.List(context.Background(), &api.Empty{})
  11. if err != nil {
  12. return &api.RestaurantList{}, fmt.Errorf("could not retrieve restaurant's list: %s", err)
  13. }
  14. return restaurantList, nil
  15. }

Makefile

  1. image: ## build docker image and push image to registry
  2. @docker build -t alesr/bacon-api -f resources/prod/Dockerfile .
  3. run: ## deploy docker container
  4. @docker run --rm -d -p 8080:8080 --name bacon-api bacon-api
英文:

I'm implementing two services (server and client) running on two different containers and trying to use gRPC to communicate between them.

If I deploy the server as a container and run the client not on a container, everything works just fine. But if I deploy the client on a different container I get Error #01: could not retrieve restaurant's list: rpc error: code = Unavailable desc = grpc: the connection is unavailable error.

What steps am I missing to communicate two different containers using gRPC?

PS: I would like to try without Kubernetes for now.

SERVER

  1. func Serve() {
  2. log.Println("serving...")
  3. port := ":50051"
  4. lis, err := net.Listen("tcp", port)
  5. if err != nil {
  6. log.Fatalf("failed to listen on port %s: %v", port, err)
  7. }
  8. s := grpc.NewServer()
  9. server := server{}
  10. RegisterNeo4BaconServer(s, server)
  11. if err := s.Serve(lis); err != nil {
  12. log.Fatal("could not serve: ", err)
  13. }
  14. }

Makefile

  1. image: ## build docker image and push image to registry
  2. @docker build -t neo4bacon -f resources/prod/Dockerfile .
  3. run: ## deploy application container
  4. @docker run --rm -d --name neo4bacon neo4bacon

CLIENT

  1. func Get() (*api.RestaurantList, error) {
  2. // Neo4bacon backend
  3. backendPort := ":50051"
  4. conn, err := grpc.Dial(backendPort, grpc.WithInsecure())
  5. if err != nil {
  6. &api.RestaurantList{}, fmt.Errorf("could not connect to backend %s: %s", backendPort, err)
  7. }
  8. defer conn.Close()
  9. client := api.NewNeo4BaconClient(conn)
  10. restaurantList, err := client.List(context.Background(), &api.Empty{})
  11. if err != nil {
  12. return &api.RestaurantList{}, fmt.Errorf("could not retrieve restaurant's list: %s", err)
  13. }
  14. return restaurantList, nil
  15. }

Makefile

  1. image: ## build docker image and push image to registry
  2. @docker build -t alesr/bacon-api -f resources/prod/Dockerfile .
  3. run: ## deploy docker container
  4. @docker run --rm -d -p 8080:8080 --name bacon-api bacon-api

答案1

得分: 10

你需要在拨号函数中包含主机名,否则它会默认使用本地主机(localhost),而每个容器的本地主机是唯一的(Docker默认为每个容器创建一个单独的网络命名空间)。请修改以下内容:

  1. backendPort := "neo4bacon:50051"

另外,你还需要设置一个网络,并将容器连接到该网络,因为默认的桥接网络不包含DNS发现功能:

  1. docker network create baconnet
  2. docker run --rm -d --net baconnet --name neo4bacon neo4bacon
  3. docker run --rm -d --net baconnet -p 8080:8080 --name bacon-api bacon-api
英文:

You need to include the hostname in the dial function, otherwise it's looking at localhost which is unique to each container (docker creates a separate networking namespace for containers by default). Change the following:

  1. backendPort := "neo4bacon:50051"

Edit: you also need to setup a network and connect the containers to that network because the default bridge does not include DNS discovery:

  1. docker network create baconnet
  2. docker run --rm -d --net baconnet --name neo4bacon neo4bacon
  3. docker run --rm -d --net baconnet -p 8080:8080 --name bacon-api bacon-api

答案2

得分: 0

如果您的gRPC客户端和服务器托管在Docker上,要在两个容器之间建立连接,您应该按照以下步骤操作:

  1. 首先,您需要创建一个Docker网络。

    docker network create web_server --driver bridge

  2. 然后,将您的容器注册到创建的网络中。您应该在docker run命令中提及服务名称和网络。

    docker run -dit -p 3000:3000 --name question-service --network web_server ${{ env.REGISTRY }}/question-service:latest

  3. 现在,您的URL应该按照以下格式设置:

    {{service-name}}:port

    例如:

    question-service:3000

    有关更多详细信息,您可以参考这篇博客文章

英文:

If your gRPC client and server are hosted on docker, to establish the connection between to container you should follow the below steps.

  1. First, you should create a docker network.

    docker network create web_server --driver bridge

  2. Then register your containers with the created network. You should mention the service name and the network in the docker run command.

    docker run -dit -p 3000:3000 --name question-service --network web_server ${{ env.REGISTRY }}/question-service:latest

  3. Now your URL should format as below,

> {{service-name}}:port

as an example

  1. question-service:3000

for more details, you can refer to this blog

huangapple
  • 本文由 发表于 2017年6月20日 09:11:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/44642241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定