本文是gRPC的简介与实践,介绍内容主要有gRPC本身,以及gRPC默认使用的数据交换格式protobuf,最后提供一个简单版本的gRPC demo。
一、gRPC是什么
gRPC是Google开源的RPC实现,基于最新的HTTP2.0协议,并支持常见的众多编程语言。gRPC客户端和服务端可以在多种环境中运行和交互,并且可以使用任何gRPC支持的语言来编写,支持跨平台、跨语言调用。
二、protoBuf
protoBuf是Google开源的一套成熟的结构数据序列化机制,gRPC默认使用的数据交换格式就是protoBuf。
1. 优点:
(1)序列化后体积比Json和XML都小,适合网络传输。
(2)支持跨平台多语言。
(3)消息格式升级和兼容性还不错。
(4)序列化反序列化速度很快,快于Json的处理速度。
2. 缺点:
(1)功能简单,无法用来表示复杂的概念。
(2)二进制数据格式,需要编码和解码,数据本身不具有可读性,因此只能方序列化之后得到真正可读的数据。
三、Go gRPC简单实践
1. 安装gRPC包
go get -u google.golang.org/grpc
2. 安装protoBuf
(1)centOs安装
#安装依赖
yum install autoconf automake libtool curl make g++ unzip libffi-dev glibc-headers gcc-c++ -y
#下载
git clone https://github.com/protocolbuffers/protobuf.git
#安装
unzip protobuf.zip
cd protobuf
./autogen.sh
./configure
make && make install
ldconfig #刷新共享库
#查看版本号,是否安装成功
protoc --version
(2)windows安装
下载:https://github.com/google/protobuf/releases
下载windows版本后,配置文件中的bin目录到path环境变量下即可。
查看版本号,是否安装成功:
protoc --version
3. 写代码
gRPC有普通模式与流式模式两种模式,这里只示例普通模式。demo逻辑很简单,就是求两个整型数值的乘机和商余。
(1)契约文件:
syntax = "proto3";
package proto;
service Arith {
rpc Multiply(ArithArgs) returns(ArithReply){}
rpc Divide(ArithArgs) returns(ArithQuotient){}
}
message ArithArgs {
int64 A = 1;
int64 B = 2;
}
message ArithReply {
int64 Value = 1;
}
message ArithQuotient {
int64 Quo = 1;
int64 Rem = 2;
}
生成Go代码:(在契约文件目录下执行)
protoc --go_out=plugins=grpc:. *.proto
执行完成以后当前目录会生成一个.pb.go文件。
(2)服务端:
/**
* grpc demo nostream server - 求两数的乘积与商余
* author: JetWu
* date: 2020.04.21
*/
package main
import (
"context"
"errors"
proto "go-git/grpc-demo/nostream/proto"
"log"
"net"
"google.golang.org/grpc"
)
//gRPC服务方法
type Arith struct{}
func (t *Arith) Multiply(ctx context.Context, args *proto.ArithArgs) (*proto.ArithReply, error) {
return &proto.ArithReply{
Value: args.A * args.B,
}, nil
}
func (t *Arith) Divide(ctx context.Context, args *proto.ArithArgs) (*proto.ArithQuotient, error) {
if args.B == 0 {
return nil, errors.New("divide by zero")
}
return &proto.ArithQuotient{
Quo: args.A / args.B,
Rem: args.A % args.B,
}, nil
}
func main() {
//监听网络
listener, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("net.Listen err: ", err)
}
defer listener.Close()
//创建grpc句柄
srv := grpc.NewServer()
//将Arith结构体注册到grpc服务中
proto.RegisterArithServer(srv, &Arith{})
log.Println("grpc demo nostream server started ...")
//监听服务
err = srv.Serve(listener) //阻塞
if err != nil {
log.Fatal("srv.Serve err: ", err)
}
}
(3)客户端:
/**
* grpc demo nostream client - 求两数的乘积与商余
* author: JetWu
* date: 2020.04.21
*/
package main
import (
"context"
"fmt"
proto "go-git/grpc-demo/nostream/proto"
"log"
"google.golang.org/grpc"
)
func main() {
//连接服务器
conn, err := grpc.Dial(":1234", grpc.WithInsecure())
if err != nil {
log.Fatal("grpc.Dial err: ", err)
}
defer conn.Close()
log.Println("successfully connected to the grpc demo nostream server ...")
//获得grpc句柄
client := proto.NewArithClient(conn)
args := &proto.ArithArgs{A: 17, B: 8}
reply, err := client.Multiply(context.Background(), args)
if err != nil {
log.Fatal("Arith.Multiply error: ", err)
}
fmt.Printf("Arith.Multiply: %d * %d = %d
", args.A, args.B, reply.Value)
quo, err := client.Divide(context.Background(), args)
if err != nil {
log.Fatal("Arith.Divide error: ", err)
}
fmt.Printf("Arith.Divide: %d / %d = %d remainder %d
", args.A, args.B, quo.Quo, quo.Rem)
}