哈Ha! 我向您介绍Mat Evans
撰写的文章
“ Go,gRPC和Docker”的翻译。
关于共享Go和Docker的文章很多。 创建可以与客户以及彼此之间进行交互的容器非常容易。 以下是在基本级别上如何完成此操作的一个小示例。
我们创造什么?
我们将创建非常简单的客户端和服务器,并使用
gRPC进行
交互 。 该服务器将位于
Docker容器内,因此可以轻松进行部署。
假设我们需要一个从客户端接收字符串并返回字符顺序相反的字符串的服务。 例如,发送“ cat”并获得“ current”作为响应。
.proto文件
.proto- file描述我们的服务将执行的操作以及将交换的数据。 在项目中创建
proto文件夹,并在其中创建
reverse.proto文件
syntax = "proto3"; package reverse; service Reverse { rpc Do(Request) returns (Response) {} } message Request { string message = 1; } message Response { string message = 1; }
在服务器上远程调用并向客户端返回数据的功能被标记为
rpc 。 用于在交互节点之间交换信息的数据结构被标记为
message 。 必须为每个消息字段分配一个序列号。 在这种情况下,我们的函数从客户端接收
请求消息并返回
响应消息。
创建
.proto文件后,有必要获取我们服务的
.go文件。 为此,请在
proto文件夹中运行以下控制台命令:
$ protoc -I . reverse.proto --go_out=plugins=grpc:.
当然,首先需要
构建gRPC 。
执行上述命令将创建一个新的
.go文件,其中包含用于创建客户端,服务器和它们交换的消息的方法。 如果调用
godoc ,将看到以下内容:
$ godoc . PACKAGE DOCUMENTATION package reverse import "." Package reverse is a generated protocol buffer package. It is generated from these files: reverse.proto It has these top-level messages: Request Response ....
顾客
如果我们的客户像这样工作,那就太好了:
reverse "this is a test" tset a si siht
以下是使用从
.proto文件生成的数据结构创建
gRPC客户端的代码:
package main import ( "context" "fmt" "os" pb "github.com/matzhouse/go-grpc/proto" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" ) func main() { opts := []grpc.DialOption{ grpc.WithInsecure(), } args := os.Args conn, err := grpc.Dial("127.0.0.1:5300", opts...) if err != nil { grpclog.Fatalf("fail to dial: %v", err) } defer conn.Close() client := pb.NewReverseClient(conn) request := &pb.Request{ Message: args[1], } response, err := client.Do(context.Background(), request) if err != nil { grpclog.Fatalf("fail to dial: %v", err) } fmt.Println(response.Message) }
伺服器
服务器将使用相同的生成的
.go文件。 但是,它仅定义服务器接口,但是我们必须自己实现逻辑:
package main import ( "net" pb "github.com/matzhouse/go-grpc/proto" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" ) func main() { listener, err := net.Listen("tcp", ":5300") if err != nil { grpclog.Fatalf("failed to listen: %v", err) } opts := []grpc.ServerOption{} grpcServer := grpc.NewServer(opts...) pb.RegisterReverseServer(grpcServer, &server{}) grpcServer.Serve(listener) } type server struct{} func (s *server) Do(c context.Context, request *pb.Request) (response *pb.Response, err error) { n := 0
码头工人
我假设您知道
Docker是什么以及它的用途。 这是我们的
Dockerfile :
FROM golang:1.12 ADD . /go/src/github.com/matzhouse/go-grpc/server RUN go install github.com/matzhouse/go-grpc/server ENTRYPOINT ["/go/bin/server"] EXPOSE 5300
Docker镜像的汇编代码在此处编写。 我们将逐行分析它。
FROM golang:1.12
此命令意味着我们要基于先前创建的图像
golang创建应用程序的图像。 这是
Docker映像,具有已配置的环境,用于构建和运行用
Go编写的程序。
ADD . /go/src/github.com/matzhouse/go-grpc/server
此命令将我们的应用程序的源代码复制到
GOPATH / src容器中。
RUN go install github.com/matzhouse/go-grpc/server
此命令从复制到容器的源中收集我们的应用程序,并将其安装在
GOPATH / bin容器
文件夹中 。
ENTRYPOINT ["/go/bin/server"]
此命令将容器配置为充当可执行程序。 在其中,我们指示了应用程序可执行文件的路径,并在必要时指示了命令行参数。
EXPOSE 5300
使用此命令,我们告诉容器应该从外部访问哪些端口。
服务器启动
我们需要使用我们的服务器应用程序运行容器。
首先,您需要根据
Dockerfile中的指令构建映像:
$ sudo docker build -t matzhouse/grpc-server . Sending build context to Docker daemon 31.76 MB Step 1/5 : FROM golang ---> a0c61f0b0796 Step 2/5 : ADD . /go/src/github.com/matzhouse/go-grpc ---> 9508be6501c1 Removing intermediate container 94dc6e3a9a20 Step 3/5 : RUN go install github.com/matzhouse/go-grpc/server ---> Running in f3e0b993a420 ---> f7a0370b7f7d Removing intermediate container f3e0b993a420 Step 4/5 : ENTRYPOINT /go/bin/server ---> Running in 9c9619e45df4 ---> fb34dfe1c0ea Removing intermediate container 9c9619e45df4 Step 5/5 : EXPOSE 5300 ---> Running in 0403390af135 ---> 008e09b9aebd Removing intermediate container 0403390af135 Successfully built 008e09b9aebd
现在我们可以在列表中看到该图像:
$ docker images REPOSITORY TAG IMAGE ID ... matzhouse/grpc-server latest 008e09b9aebd ...
太好了! 我们有服务器应用程序的映像,您可以使用以下命令启动其容器:
$ docker run -it -p 5300:5300 matzhouse/grpc-server
在这种情况下,所谓的
端口转发 。 请注意,为此,我们需要
EXPOSE语句和
-p参数。
客户启动
客户端的容器化不会带来很大的优势,所以让我们以通常的方式开始:
$ go build -o reverse $ ./reverse "this is a test" tset a si siht
感谢您的阅读!