共计 3863 个字符,预计需要花费 10 分钟才能阅读完成。
[TOC]
gRPC
gRPC 介绍
gRPC 是什么?
RPC 和 RESTful 的区别是什么?
RPC 的音讯传输能够是 TCP,能够是 UDP,也能够是 HTTP,当 RPC 音讯传输是 HTTP 时,它的构造与 RESTful 的架构相似
RPC 和 RESTful 有什么不同呢:
- 操作的对象不一样的,RESTful 会更加灵便
RPC 操作的是办法对象,RESTful 操作的是资源
RPC 的客户端和服务器端是紧耦合的,客户端须要晓得服务端的函数名字,参数类型、程序等,能力近程过程调用。
RESTful 基于 http 的语义操作资源,参数的程序个别没有关系
-
RCP 更适宜定制化
RESTful 执行的是对资源的操作,次要都是 CURD(增删改查)的操作,若须要实现一个特定的性能,如计算一个班级的平均分,这个时候应用 RPC 定义服务器的办法(如:Stu.CalAvg)供客户端调用则显得更有意义
gRPC 的个性是什么?
- gRPC 是能够跨语言开发的
在 gRPC 客户端能够间接调用不同服务器上的近程程序,应用姿态看起来就像调用本地过程调用一样,很容易去构建分布式应用和服务。客户端和服务端能够别离应用 gRPC 反对的不同语言实现。
-
基于 HTTP2 规范设计,比其余框架更优的中央有
- 反对
长连贯,双向流、头部压缩、多复用申请
等 节俭带宽
、升高 TCP 链接次数
、节俭 CPU 应用
和缩短电池寿命
- 进步了云端服务和 Web 利用的性能
- 客户端和服务端交互通明
- gRPC 默认应用 protobuf 来对数据序列化
- 反对
gRPC 的数据交互模式是怎么样的?
申请应答式
客户端收回一次申请,能够从服务端读取一系列的音讯
客户端写一系列音讯给到服务端,期待服务端应答
客户端和服务端都能够通过读写数据流来发送一系列音讯
数据的序列化形式 – protobuf
protobuf 是一个对数据序列化的形式,相似的有 JSON,XML 等
简略介绍 protobuf 的构造定义蕴含的 3 个关键字
- 以.proto 做为后缀,除构造定义外的语句以分号结尾
- 构造定义能够蕴含:message、service、enum,三个关键字
- rpc 办法定义结尾的分号可有可无
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)
}
一个 DEMO
目录构造为:
-------------------------------
| 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 的认证
技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。
我是小魔童哪吒,欢送点赞关注珍藏,下次见~