grpc 是一个高性能、通用的开源 RPC 框架,基于 HTTP/2 协议标准和 Protobuf 序列化协议开发,支持众多的开发语言。在对接口具有严格约束或者传递大量数据的场景中得到了广泛的应用。本文作者从什么是 grpc 开始介绍,讲诉了 protobuf 的语法以及如何使用 grpc 框架,对于想学习 grpc 的初学者来说,是一篇极好的入门教程,下来就跟随作者一起学习吧。
PS:丰富的一线技术、多元化的表现形式,尽在“360 云计算”,点关注哦!
简介
什么是 grpc
grpc 是一个由 google 推出的、高性能、开源、通用的 rpc 框架。它是基于 HTTP2 协议标准设计开发,默认采用 Protocol Buffers 数据序列化协议,支持多种开发语言。
什么是 protobuf buffers
ProtoBuf buffer 是一种数据表达方式,以.proto 结尾的数据文件,可以类比 json、xml 等。
针对 ProtoBuf buffer 数据源,可以利用 protoc 工具来生成各种语言的访问类。
其操作步骤:
1.定义数据元;
2.生成数据元的访问类。
优点:
protobuf buffers 定义数据元的语法
一个.proto 文件,主要包括以下部分:
syntax = "proto3";
package studentpb;
service Student {
rpc add (StudentReqs) returns (StudentReply) {} //新增学生接口
}
message StudentReqs {
repeated StudentReq s = 1;
}
message StudentReq{
string name= 1;
int32 age = 2;
}
message StudentReply {
int32 errno = 1;
string errmsg = 2;
}
复制代码
关键字 syntax:指定使用的 proto3 语法;
关键字 package:定义一个包,需要注意避免命名冲突;
关键字 message 来定义请求或相应需要使用的消息格式,里面可以包含了不同类型的字段 。一个.proto 文件中,可以包含多个 message 的定义。
关键字 server 来定一个服务。GRPC 的服务是通过参数和返回类型来指定可以远程调用的方法。
字段的约束规则
repeated:前置 repeated 关键词,声明该字段为数组类型。
proto3 不支持 proto2 中的 required 和 optional 关键字。
字段支持的类型
支持基础类型、枚举类型、map 类型、数组类型、message 类型等。
syntax = "proto3";
message Student{
string name = 1;
// 定义enum类型
enum Sex {
BOY = 0;
GIRL = 1;
}
Sex sex = 1; // 使用Corpus作为字段类型
}
message类型
syntax = "proto3";
message Students {
repeated Student s = 1;
}
message Student{
string name = 1;
// 定义enum类型
enum Sex {
BOY = 0;
GIRL = 1;
}
Sex sex = 4; // 使用Corpus作为字段类型
}
复制代码
如何利用 protoc 工具生成访问类
prooc 常用参数
案例
文件目录如下:
其中“t.proto”内容如下:
syntax = "proto3";
package studentpb;
service Student {
rpc add (StudentReqs) returns (StudentReply) {} //新增学生接口
}
message StudentReqs {
repeated StudentReq s = 1;
}
message StudentReq{
string name= 1;
int32 age = 2;
}
message StudentReply {
int32 errno = 1;
string errmsg = 2;
}
复制代码
生成 go 访问类的语句如下:
protoc --go_out=plugins=grpc:. protobuf/*.proto
复制代码
GO 如何利用 GRPC 通信
pb 文件
syntax = "proto3";
package studentpb;
service Student {
rpc add (StudentReqs) returns (StudentReply) {} //新增学生接口
}
message StudentReqs {
repeated StudentReq s = 1;
}
message StudentReq{
string name= 1;
int32 age = 2;
}
message StudentReply {
int32 errno = 1;
string errmsg = 2;
}
复制代码
执行如下命令,生成 grpc 访问类
protoc --go_out=plugins=grpc:. *.proto
服务端
目录结构如下:
main.go 内容如下:
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"log"
"net"
"test/studentpb"
)
type Student struct {
}
// 新增students
func (r *Student) Add(ctx context.Context, in *studentpb.StudentReqs) (*studentpb.StudentReply, error) {
return &studentpb.StudentReply{
Errno: 0,
Errmsg: "ok",
}, nil
}
func main() {
// 建立server监听
rpcAddr := "127.0.0.1:8601"
server, err := net.Listen("tcp", rpcAddr)
if err != nil {
fmt.Println("failed to listen", rpcAddr)
panic(err)
}
// 建立rpc server
var RpcServer = grpc.NewServer()
err = RpcServer.Serve(server)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 对外提供服务
r := new(Student)
studentpb.RegisterStudentServer(RpcServer, r)
select {
}
}
复制代码
用户端
用户端的目录结构和服务端一样。main.go 的内容如下:
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"test/studentpb"
"time"
)
func main() {
addr := "127.0.0.1:8601"
timeout := 10
//建立rpc通道
client, err := grpc.Dial(addr, grpc.WithInsecure())
if err != nil {
panic("连接失败")
}
defer client.Close()
// 创建studentrpc对象
rpcClient := studentpb.NewStudentClient(client)
// 创建上线文
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
defer cancel()
//封装请求参数
req := &studentpb.StudentReqs{}
req.S = append(req.S, &studentpb.StudentReq{Name:"张三", Age:12})
// 打印结果
res , err := rpcClient.Add(ctx, req)
if err != nil {
fmt.Println("请求错误", err)
} else {
fmt.Println(res.GetErrno(), res.GetErrmsg())
}
}
复制代码
本文转载自 360 云计算公众号。
原文链接:https://mp.weixin.qq.com/s/0TnMIuHE0BZ7sFXTm0kvDw
评论