GRPC学习笔记
grpc概念详解
- 什么是grpc?
gRPC是由 google开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于HTTP/2 协议标准而设计,同时支持大多数流行的编程语言。
gRPC基于 HTTP/2 协议传输,而HTTP/2相比HTTP1.x,有以下一些优势:
1.用于数据传输的二进制分帧
2.多路复用
3.服务端推送
4.减少网络流量的头部压缩
- grpc远程调用过程
protobuf概念详解
- 什么是protobuf
Protobuf是google 的一种数据交换的格式,它独立于语言,独立于平台。
google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。
由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
- protobuf的优点、缺点
- 什么是protoc
protoc是protobuf文件(.proto)的编译器(参考链接),可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,
包含数据类型定义、调用接口等。
- 什么是protoc-gen-go
protoc-gen-go是protobuf编译插件系列中的Go版本。
一、grpc环境搭建(linux)
- 先装protoc编译插件(protoc.exe是.proto文件的编译器)
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protobuf-all-3.20.0.zip
$ unzip protoc-all-3.20.0.zip
$ cd protobuf-all-3.20.0
$ ./configure
$ make
$ make install
$ protoc --version
- 再装protoc-gen-go(protoc-gen-go是protoc编译器的Go版本)
$ go get github.com/golang/protobuf
$ cd github.com/golang/protobuf/protoc-gen-go
$ go build .
-
将protoc-gen-go文件放入gopath/bin/目录下
-
编写hello.proto测试
syntax = "proto3";
option go_package="./;protofile";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
- 测试安装是否成功
protoc --go_out=./ hello.proto 针对rpc生成go文件
protoc --go_out=plugins=grpc:. hello.proto 针对grpc生成go文件
一、grpc环境搭建(Windows)
- 安装protoc
https://github.com/protocolbuffers/protobuf/releases
- 解压出来把protoc的bin目录放在直接放在系统变量当中
- 安装protobuf
$ go get github.com/golang/protobuf
$ cd github.com/golang/protobuf/protoc-gen-go
$ go build .
- 编写hello.proto测试
syntax = "proto3";
option go_package="./;protofile";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
- 测试安装是否成功
protoc --go_out=./ hello.proto 针对rpc生成go文件
protoc --go_out=plugins=grpc:. hello.proto 针对grpc生成go文件
二、grpc开发实例
protofile文件
syntax = "proto3";
option go_package="./;protofile";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
int32 age = 2;
string addr = 3;
}
message HelloReply {
string message = 1;
}
$ protoc --go_out=plugins=grpc:. hello.proto
server模块
package main
import (
"context"
"google.golang.org/grpc"
"net"
"protofile"
)
type Server struct {
}
func (s *Server) SayHello(ctx context.Context, request *protofile.HelloRequest) (*protofile.HelloReply, error) {
return &protofile.HelloReply{
Message: "fuck you " + request.Name,
}, nil
}
func main() {
listener, err := net.Listen("tcp", ":8080") //监听地址
if err != nil {
panic("failed to listen" + err.Error())
}
g := grpc.NewServer() // 初始化grpc服务
protofile.RegisterGreeterServer(g, &Server{}) // 注册服务
err = g.Serve(listener) // 监听服务,如启动失败则抛出异常
if err != nil {
panic("failed to start grpc" + err.Error())
}
}
client模块
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"protofile"
)
func main() {
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure()) // 建立链接
if err != nil {
panic("failed to Dial" + err.Error())
}
defer conn.Close()
client := protofile.NewGreeterClient(conn) // 初始化客户端
reply, err := client.SayHello(context.Background(), &protofile.HelloRequest{Name: "LZK", Age: 18, Addr: "Nanjing"})
if err != nil {
panic("failed to SayHello" + err.Error())
}
fmt.Println(reply.Message)
}
三、grpc开发实例(流模式)
protofile文件
syntax = "proto3";
option go_package="./;protofile";
service Greeter {
rpc GetStream(StreamReqData) returns (stream StreamRepData); //服务端流模式
rpc PutStream(stream StreamReqData) returns (StreamRepData); //客户端流模式
rpc AllStream(stream StreamReqData) returns (stream StreamRepData); //双向流模式
}
message StreamReqData {
string data = 1;
}
message StreamRepData {
string data = 1;
}
$ protoc --go_out=plugins=grpc:. stream.proto
server模块
package main
import (
"fmt"
"google.golang.org/grpc"
"net"
"protofile"
"time"
)
type Server struct {
}
// GetStream 服务端流模式
func (s *Server) GetStream(req *protofile.StreamReqData, rep protofile.Greeter_GetStreamServer) error {
i := 0
for {
i++
_ = rep.Send(&protofile.StreamRepData{Data: fmt.Sprintf("%v", time.Now().Unix())})
time.Sleep(time.Second)
if i >= 10 {
break
}
}
return nil
}
// PutStream 客户端流模式
func (s *Server) PutStream(cliStr protofile.Greeter_PutStreamServer) error {
for {
if a, err := cliStr.Recv(); err != nil {
fmt.Println(err)
break
} else {
fmt.Println(a.Data)
}
}
return nil
}
// AllStream 双向流模式
func (s *Server) AllStream(allStr protofile.Greeter_AllStreamServer) error {
return nil
}
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
panic("failed to listen " + err.Error())
}
g := grpc.NewServer()
protofile.RegisterGreeterServer(g, &Server{})
err = g.Serve(listener)
if err != nil {
panic(err)
}
}
client模块
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"protofile"
"time"
)
func main() {
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
if err != nil {
panic(err)
}
defer conn.Close()
//服务端流模式
client := protofile.NewGreeterClient(conn)
rep, _ := client.GetStream(context.Background(), &protofile.StreamReqData{Data: "fuck you"})
for {
a, err := rep.Recv()
if err != nil {
fmt.Println(err)
break
}
fmt.Println(a)
}
//客户端流模式
putS, _ := client.PutStream(context.Background())
i := 0
for {
i++
putS.Send(&protofile.StreamReqData{Data: fmt.Sprintf("fuck you 慕课网%d", i)})
time.Sleep(time.Second)
if i >= 10 {
break
}
}
//双向流模式
}