Author Archives: admin

gRPC golang 初步接触

概述

gRPC使用protocol buffers作为 IDL(Interface Definition Language), 提供一种跨平台,跨语言的RPC(远程过程调用)机制,本文通过示例程序介绍gRPC基本使用。

前置条件

  • Go 版本1.6及以上 (传送)
    $ go version
    
  • 安装gRPC
    $ go get -u google.golang.org/grpc
    
  • 安装 Protocol Buffers v3

    Protocol编译器是用来生成gRPC服务代码的。下载对应的zip文件包来安装即可 传送

    • 解压zip文件
    • 将二进制文件(bin/protoc)添加进path环境变量

    接着安装 protoc的Go插件:

    $ go get -u github.com/golang/protobuf/protoc-gen-go
    

    protoc-gen-go 编译器插件安装在$GOBIN,变量定义为 \$GOPATH/bin,在\$PATH环境变量中必须存在 protocol ,protoc相关命令。

    $ export PATH=$PATH:$GOPATH/bin
    

下载代码

下载gRPC示例代码库GIthub,示例代码位于 $GOPATH/src/google.golang.org/grpc/examples 目录下。

$ go get google.golang.org/grpc 

#或者从github下载
$ go get github.com/grpc/grpc

构建程序

#切换到示例代码目录中
$ cd $GOPATH/src/google.golang.org/grpc/examples

.proto 文件 定义 gRPC服务,同时也用来生成对应的 .pb.go 文件。 .pb.go 文件是使用 protoc 编译器根据.proto来生成的。

对示例程序来说,helloworld.pb.go 文件已经提前生成(依据 helloworld.proto 定义),文件位于$GOPATH/src/google.golang.org/grpc/examples/helloworld/helloworld

文件 helloworld.pb.go 包含以下内容:

  • 生成的客户端和服务端代码
  • 生成定义好的 HelloRequestHelloReply 类型操作代码

运行程序

使用 go run 指令运行。

运行服务端:

$ go run greeter_server/main.go

运行客户端(新开terminal):

$ go run greeter_client/main.go

若打印 Greeting: Hello world,表示基于 client-server 的 gRPC 运用运行成功。

修改程序

目的:服务端(server)增加一个新的方法(SayHelloAgain)供客户端(client)调用。gRPC服务使 protocol定义;在这个 地址 和这个 地址 能找到定义 .proto 文件的更多信息。现在,你只需要知道服务端和客户端”stub”同时存在一个 SayHello 方法,该方法接受从客户端 HelloRequest 类型参数并且由服务端返回 HelloReply 类型结果,代码如下:

//  greeting 服务定义.
service Greeter {
  // 发送 greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// request 消息体包含 user's name.
message HelloRequest {
  string name = 1;
}

// response 消息提包含 greetings
message HelloReply {
  string message = 1;
}

Greeter 增加一个 SayHelloAgain 方法,确保当前工作目录为$GOPATH/src/google.golang.org/grpc/examples/helloworld。

修改 helloworld/helloworld.proto 文件,增加一个 SayHelloAgain 方法,带有 HelloRequestHelloReply 类型。代码如下:

//  greeting 服务定义.
service Greeter {
  // 发送 greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // 新增 SayHelloAgain
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// request 消息体包含 user's name.
message HelloRequest {
  string name = 1;
}

// response 消息提包含 greetings
message HelloReply {
  string message = 1;
}

生成gRPC代码

现在使用定义好的服务重新生成gRPC代码。工作目录为($GOPATH/src/google.golang.org/grpc/examples/helloworld)。指令如下:

$ protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld

文件 helloworld.pb.go 被重新生成。

修改&重新运行

虽然已经重新生成 服务端 (server) 和 客户端 (client) 代码, 但让然需要手动修改部分调用代码。

修改 server

编辑文件 greeter_server/main.go,增加如下代码:

func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        return &pb.HelloReply{Message: "Hello again " + in.Name}, nil
}

修改 client

编辑文件 greeter_client/main.go,在 main 函数中增加如下代码:

r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
        log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)

运行

运行服务端:

$ go run greeter_server/main.go

运行客户端:

$ go run greeter_server/main.go

期望结果:

$ go run greeter_client/main.go
Greeting: Hello world
Greeting: Hello again world