[TOC]git
RPC的消息传输能够是TCP,能够是UDP,也能够是HTTP,当RPC消息传输是HTTP时,它的结构与RESTful的架构相似github
RPC和RESTful有什么不一样呢:golang
RPC操做的是方法对象, RESTful操做的是资源json
RPC的客户端和服务器端是紧耦合的,客户端须要知道服务端的函数名字,参数类型、顺序等,才能远程过程调用。bash
RESTful基于 http的语义操做资源,参数的顺序通常没有关系服务器
RCP更适合定制化架构
RESTful执行的是对资源的操做,主要都是CURD(增删改查)的操做,若须要实现一个特定的功能,如计算一个班级的平均分,这个时候使用RPC定义服务器的方法(如:Stu.CalAvg)供客户端调用则显得更有意义框架
在gRPC客户端能够直接调用不一样服务器上的远程程序,使用姿式看起来就像调用本地过程调用同样,很容易去构建分布式应用和服务。客户端和服务端能够分别使用gRPC支持的不一样语言实现。tcp
基于HTTP2标准设计,比其余框架更优的地方有分布式
长链接,双向流、头部压缩、多复用请求
等节省带宽
、下降TCP连接次数
、节省CPU使用
和延长电池寿命
请求应答式
客户端发出一次请求,能够从服务端读取一系列的消息
客户端写一系列消息给到服务端,等待服务端应答
客户端和服务端均可以经过读写数据流来发送一系列消息
protobuf 是一个对数据序列化的方式,相似的有JSON,XML等
Message命名采用驼峰命名方式,字段是小写加下划线
message ServerRequest { required string my_name = 1; }
Enums类型名采用驼峰命名方式,字段命名采用大写字母加下划线
enum MyNum { VALUE1 = 1; VALUE2 = 2; }
Service与rpc方法名统一采用驼峰式命名
service Love { // 定义Confession方法 rpc MyConfession(Request) returns (Response) {} }
关于prtobuf的安装能够看看以前写的一个安装步骤《5个步骤搞定PROTOBUF的安装》
在proto文件中使用package
关键字声明包名,默认转换成go中的包名与此一致,能够自定义包名,修改go_package
便可:
test.proto
syntax = "proto3"; // proto版本 package pb; // 指定包名,默认go中包名也是这个 // 定义Love服务 service Love { // 定义Confession方法 rpc Confession(Request) returns (Response) {} } // 请求 message Request { string name = 1; } // 响应 message Response { string result = 1; }
安装好protoc环境以后,进入到proto文件的目录下,(例如打开window git
)执行以下命令,将proto
文件编译成pb.go
文件
protoc --go_out=plugins=grpc:. test.proto
转换结果:
// Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 // protoc v3.13.0 // source: test.proto package test import ( context "context" proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // This is a compile-time assertion that a sufficiently up-to-date version // of the legacy proto package is being used. const _ = proto.ProtoPackageIsVersion4 type Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } type Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` } // LoveServer is the server API for Love service. type LoveServer interface { Confession(context.Context, *Request) (*Response, error) }
目录结构为:
------------------------------- | mygrpc | ---------pb | -------------test.proto | ---------client.go | ---------srv.go -------------------------------
client.go
package main import ( "context" "log" "mygrpc.com/pb" "google.golang.org/grpc" ) func main() { // 链接grpc服务 conn, err := grpc.Dial(":8888", grpc.WithInsecure()) if err != nil { log.Fatal(err) } // 很关键 defer conn.Close() // 初始化客户端 c := pb.NewLoveClient(conn) // 发起请求 response, err := c.Confession(context.Background(), &pb.Request{Name: "小魔童哪吒"}) if err != nil { log.Fatal(err) } log.Println(response.Result) }
server.go
package main import ( "context" "log" "net" "google.golang.org/grpc" "mygrpc.com/pb" ) // 定义Love服务 type Love struct { } // 实现Love服务接口 func (l *Love) Confession(ctx context.Context, request *pb.Request) (*pb.Response, error) { resp := &pb.Response{} resp.Result = "your name is " + request.Name return resp, nil } func main() { // 监听8888端口 listen, err := net.Listen("tcp", ":8888") if err != nil { log.Fatal(err) } // 实例化grpc server s := grpc.NewServer() // 注册Love服务 pb.RegisterLoveServer(s, new(Love)) log.Println("Listen on 127.0.0.1:8888...") s.Serve(listen) }
下一次介绍关于gRPC的认证
技术是开放的,咱们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是小魔童哪吒,欢迎点赞关注收藏,下次见~