grpc介绍
源于Google的内部RPC框架, 使用protobuf进行编码解码。
grpc的一些特点:
数据空间更小(protobuffer其数据格式紧密,没有多余的空格,括号,尖括号,key 等)
支持多种语言,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub
支持相对复杂的数据格式
支持HTTP/2
性能相对更好,protobuffer + 二进制传输 + HTTP/2 。
grpc总共支持4种通信方式:
Simple RPC
简单rpc 这就是一般的rpc调用,一个请求对象对应一个返回对象 proto语法:
rpc simpleHello(Person) returns (Result) {}
Server-side streaming RPC
服务端流式rpc 一个请求对象,服务端可以传回多个结果对象
rpc serverStreamHello(Person) returns (stream Result) {}
Client-side streaming RPC
客户端流式rpc 客户端传入多个请求对象,服务端返回一个响应结果
rpc clientStreamHello(stream Person) returns (Result) {}
Bidirectional streaming RPC
双向流式rpc 结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象
rpc biStreamHello(stream Person) returns (stream Result) {}
grpc实现
Protobuf安装
Mac用户可以使用brew进行安装:
brew install protobuf
定义.proto 文件, hello.proto 如下:
syntax="proto3";
packageproto;
// The request message containing the user's name.
messageHelloRequest{
stringname=1;
}
// The response message containing the greetings
messageHelloReply{
stringmessage=1;
}
// The greeting service definition.
serviceGreeter{
// Sends a greeting
rpcSayHello(HelloRequest)returns(HelloReply) {}
// Sends another greeting
rpcSayHelloAgain(HelloRequest)returns(HelloReply) {}
}
proto定义完之后,用protocol生成器生成一份go的代码,用来给server端和client端调用,
protoc--go_out=plugins=grpc:.hello.proto
生成的文件为hello.pb.go,包含几个部分:
方法出入参结构体以及序列化和反序列方法
注册出入参结构体的 init 方法
客户端存根结构体和接口以及实现
服务端结构体和接口以及一个空实现
stream 的 send 和 recv 结构体和接口以及实现
服务的一些描述
编写服务端代码:
服务端主要是定义一个结构体,实现pb.go接口
packageserver
import(
"context"
pb"github.com/goCode/rpc/grpc/proto"
)
typeHelloServerstruct{
}
func(s*HelloServer)SayHello(ctxcontext.Context,in*pb.HelloRequest) (*pb.HelloReply,error) {
return&pb.HelloReply{Message:"Hello "+in.GetName()},nil
}
func(s*HelloServer)SayHelloAgain(ctxcontext.Context,in*pb.HelloRequest) (*pb.HelloReply,error) {
return&pb.HelloReply{Message:"Hello again "+in.GetName()},nil
}
启动服务端
funcStartServer() {
lis,err:=net.Listen("tcp","127.0.0.1:8091")
iferr!=nil{
log.Fatalf("failed to listen: %v",err)
}
//创建一个grpc服务器对象
gRpcServer:=grpc.NewServer()
//注册grpc服务
pb.RegisterGreeterServer(gRpcServer,&HelloServer{})
gRpcServer.Serve(lis)
}
实现客户端
funcStartClient() {
conn,err:=grpc.Dial("127.0.0.1:8091",grpc.WithInsecure())
iferr!=nil{
return
}
deferconn.Close()
c:=pb.NewGreeterClient(conn)
res,err:=c.SayHello(context.Background(),new(pb.HelloRequest),grpc.EmptyCallOption{})
fmt.Println(res,err)
}
网友评论