概述
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 包含以下内容:
- 生成的客户端和服务端代码
- 生成定义好的 HelloRequest 和 HelloReply 类型操作代码
运行程序
使用 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 方法,带有 HelloRequest 和 HelloReply 类型。代码如下:
// 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
完毕!