gRPC 在 Golang 实践 - 入门

kenticny

gRPC 作为一个开源 RPC 框架,而且有 Google 背书也可谓是有深厚的背景,gRPC 采用 protocol buffers 作为 IDL,并且支持多语言跨平台运行,官方支持 C++C#GolangPython 等10种语言,并且都提供了对于语言较为详细的接入文档,所以在使用上也是十分便捷的。本文将以 Golang 为例来介绍 gRPC 的快速入门使用。

准备

所谓准备,就是要安装所有相关的环境和库,首先是 Golang (这是一句废话),但是要注意的一点是现在最新的 gRPC 要运行在 Golang v1.6 以上。

然后就是安装 gRPC,可以通过下面命令进行安装:

go get -u google.golang.org/grpc

接下要安装 Protocol Buffers,这里包含两部分,第一部分就是安装 protobuf 的编译器,方式很简单,下载地址如下:

https://github.com/google/protobuf/releases
  • 选择合适自己的压缩包进行下载,比如我这里下载了适合 macos 平台的压缩包:protoc-3.5.1-osx-x86_64.zip

  • 解压这个压缩包:unzip protoc-3.5.1-osx-x86_64.zip

  • 将解压后 bin/protoc 移动到 PATH 环境变量下面,比如 /usr/local/bin,将 include 文件夹下的内容移动到 /usr/local/includes 下即可

  • 可以运行 protoc --help 查看编译器运行帮助

另一部分是要安装编译器的适用 Golang 的插件,安装方式如下:

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

至此运行环境准备完毕。

定义服务

前面提到过,gRPC 采用 Protocol Buffers 来定义服务,这里可以先假设一个场景:“服务端提供一个 Version 的接口来获取服务的版本”,下面就是通过 Protocol Buffers 定义这个服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义服务接口
service DemoService {
rpc Version (VersionRequest) returns (VersionResponse) {}
}

// 定义 VersionRequest 的消息体
message VersionRequest {
string name = 1;
}

// 定义 VersionResponse 的消息体
message VersionResponse {
int64 version = 1;
}

上面的 Protobuf 定义了一个RPC服务 DemoService,包含一个接口 Version,这个接口接受 name 字段,返回 version 字段。

接下来,我们就要使用 Protobuf 的编译器生成 gRPC 的代码,这里就用到了我们之前安装的 protoc 工具,执行以下命令:

protoc --go_out=plugins=grpc:pb ./pb/demo_service.proto

上述命令中 --go_out=plugins=grpc:pb 定义了编译完成后输出的代码位置为 pb 目录,./pb/demo_service.proto 为需要编译的 proto 文件。生成的代码文件就不在这里展示了,里面就是定义了一些接口和结构体。

服务端程序

服务端程序就是启动一个gRPC服务器,直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"log"
"net"

"golang.org/x/net/context"
"google.golang.org/grpc"
pb "xxxx/xxx/demo_service"
"google.golang.org/grpc/reflection"
)
type server struct {}

func (s *server) Version(ctx context.Context,
in *pb.VersionRequest) (*pb.VersionResponse, error) {
return &pb.VersionResponse {Version: 1}, nil
}

func main() {
lis, err := net.Listen("tcp", ":8888")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterDemoServiceServer(s, &server{})
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

以上代码启动了一个服务器并监听8888端口,这里面主要的就是要定义一个结构体,上一步通过 Protobuf 生成的代码中会有一个 interface,里面包含 Version 方法,这里定义的结构体需要实现这个接口,这个服务才可以被注册。

客户端程序

有了服务的程序,下面我们编写一个客户端程序来连接到服务端进行通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"log"
"time"

"golang.org/x/net/context"
"google.golang.org/grpc"
pb "xxxx/xxxx/demo_service"
)

func main() {

// 连接到服务器
conn, err := grpc.Dial(":8888", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewDemoServiceClient(conn)

// 定义请求context
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.Version(ctx, &pb.VersionRequest{Name: "demo-service"})
if err != nil {
log.Fatalf("Request error: %v", err)
}
log.Printf("Version: %s", r.Message)
}

上面的代码创建了一个客户端程序,并且连接到服务器,然后调用了 Version 接口获取信息。

小结

以上为 gRPC 的使用的快速入门,包括使用 Protobuf 来定义RPC服务,然后通过编译器生成 gRPC代码,再然后编写服务端和客户端来实现通信。之后会再真的gRPC使用的一些细节和场景进行介绍。

  • 本文标题:gRPC 在 Golang 实践 - 入门
  • 本文作者:kenticny
  • 创建时间:2017-11-14 22:17:45
  • 本文链接:https://luyun.io/2017/11/14/grpc-golang-practice-01/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论
此页目录
gRPC 在 Golang 实践 - 入门