grpc 服务与docker - Go语言中文社区

grpc 服务与docker


本文的目的是grpc简单例子,在centos7上的docker上运行单一的grpc服务。

样例项目结构:

一个grpc项目,proto里存放了不同的proto服务文件,比如hello服务的hello目录,里面是hello.proto

grpc下的hello文件夹是服务实现的server端文件夹,以及测试使用的client文件夹

 

hello.proto文件代码

syntax = "proto3";
package hello;
option go_package ="hello";
service Hello{
        rpc SayHello(HelloRequest)returns(HelloResponse){}
}
message HelloRequest{
        string name=1;
}
message HelloResponse{
        string message =1;
}

server的main.go

package main

import (
        "fmt"
        "golang.org/x/net/context"
        "google.golang.org/grpc"
        "google.golang.org/grpc/grpclog"
        "net"
        pb "proto/hello"
)

const (
        Address = ":50052" //这里不能使用127.0.0.1:50052,因为要放到docker里会导致只能在docker里面才能访问服务
)

//定义helloService并实现约定的接口
type helloService struct{}

var HelloService = helloService{}

//SayHello 实现Hello服务接口
func (h helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
        resp := new(pb.HelloResponse)
        resp.Message = fmt.Sprintf("Hello %s", in.Name)
        return resp, nil
}
func main() {
        listen, err := net.Listen("tcp", Address)
        if err != nil {
                grpclog.Fatalf("Failed to listen:%v", err)
        }
        s := grpc.NewServer()
        pb.RegisterHelloServer(s, HelloService)
        grpclog.Println("Listen on " + Address)
        s.Serve(listen)
}

server的go.mod文件,其中require项是运行main.go程序时自动生成的

module server

go 1.15

replace proto/hello => /root/grpc/proto/hello

require (
        golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
        google.golang.org/grpc v1.34.0 // indirect
        proto/hello v0.0.0-00010101000000-000000000000 // indirect
)

server 的Dockerfile

FROM alpine
ADD main /main
EXPOSE 50052
ENTRYPOINT [ "/main" ]

server的Makefile

GOPATH:=$(shell go env GOPATH)
.PHONY: init
init:
        go get -u github.com/golang/protobuf/proto
        go get -u github.com/golang/protobuf/protoc-gen-go
        go get github.com/micro/micro/v3/cmd/protoc-gen-micro
.PHONY: proto
proto:
        protoc --proto_path=. --micro_out=. --go_out=:. proto/userlogin.proto

.PHONY: build
build:
        CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main *.go

.PHONY: test
test:
        go test -v ./... -cover

.PHONY: docker
docker:
        docker build . -t main:latest

client的main.go

package main

import (
        pb "proto/hello"
        "context"
        "fmt"
        "google.golang.org/grpc"
        "google.golang.org/grpc/grpclog"
        "sync"
)

const (
        Address = "127.0.0.1:50052"
)

//定义helloService并实现约定的接口
type helloService struct{}

var HelloService = helloService{}

func main() {
        conn, err := grpc.Dial(Address, grpc.WithInsecure())
        if err != nil {
                grpclog.Fatalln(err)
        }
        defer conn.Close()
        var wg sync.WaitGroup
        wg.Add(100)
        for i := 0; i < 100; i++ {
                go func(i int) {

                        c := pb.NewHelloClient(conn)
                        str := fmt.Sprintf("gRpc,%v", i)
                        req := &pb.HelloRequest{Name: str}
                        res, err := c.SayHello(context.Background(), req)
                        if err != nil {
                                grpclog.Fatalln(err)
                        }
                        fmt.Println(res.Message)
                        wg.Done()
                }(i)

        }
        wg.Wait()
        fmt.Println("main exit")
}

client的go.mod

module client

replace proto/hello => /root/grpc/proto/hello

go 1.15

require (
        golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
        google.golang.org/grpc v1.34.0
        proto/hello v0.0.0-00010101000000-000000000000
)

 

测试:

在server里执行

make build

./main

在client里直接运行go run main.go

 

 

 

 

正常运行服务

生成hello服务的docker 镜像,在server里执行make docker

查看镜像docker image ls

运行镜像

docker run --name hello -p 50052:50052 -d main:latest

查看正在运行中的容器

docker ps

[root@localhost server]# docker ps
CONTAINER ID   IMAGE         COMMAND   CREATED              STATUS              PORTS                      NAMES
27b50bbe33d6   main:latest   "/main"   About a minute ago   Up About a minute   0.0.0.0:50052->50052/tcp   hello
[root@localhost server]#
进入容器查看信息

docker exec -it hello /bin/sh

容器正常监听所有地址的50052端口

本地查看50052端口是哪个程序?是docker

再次运行client的main.go验证服务是否正常

正常运行服务.

如果监听写成127.0.0.1:50052会出现什么错误?

[root@localhost client]# go run main.go
FATAL: 2021/01/10 15:42:28 rpc error: code = Unavailable desc = connection closed
exit status 1
进入docker的容器查看信息

[root@localhost client]# docker exec -it hello /bin/sh
/ # netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:50052         0.0.0.0:*               LISTEN      1/main
/ #
可以看到docker里监听的只是本地ip,所以出现上面连接失败信息。

下一集,使用k8s管理运行hello服务的docker.

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/freelove_2005/article/details/112427748
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-04-10 22:57:43
  • 阅读 ( 1603 )
  • 分类:docker

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢