GRPC(2):基本概念

基本概念
什么是 gRPC?

gRPC 最初是 google 开发的高性能,且功能强大的开源 RPC 框架,后来被纳入云原生基金会的托管项目中,由于背靠 google 老大哥,不论是技术储备还是生态建设都十分的成熟和完善。是一个应用非常广泛的 RPC 框架。

图片

RPC 详解我们知道,RPC 框架中有两个核心组件,客户端存根(client-stub)和服务端存根(server-stub)。业务代码通过调用存根提供的接口,使得远程调用看起来像本地接口调用一样。要创建这两个存根,我们需要明确客户端存根和和服务端存根传递消息的格式,传递消息使用的协议,以及类似参数传递等问题(这些在RPC 详解中已经介绍,这里不再赘述)。而定义这些服务使用的语言我们称作(IDL),服务定义语言(interface definition language)。

gRPC 使用 proto buffers 作为服务定义语言,编写 proto 文件,即可完成服务的定义。

gRPC 为什么使用 Proto Buffers?
  • 可读性好

  • 支持多种语言代码的生成

  • 二进制数据表示,传输更快,序列化和反序列化更高效;

  • 采用强类型协议,更稳定

  • 兼容性更好,新增接口服务不影响原服务的使用

  • 图片

如何定义一个 protocol message
syntax = "proto3";

message <NameOfTheMessage> {
  <data-type> name_of_field_1 = tag_1;
  <data-type> name_of_field_2 = tag_2;
  ...
  <data-type> name_of_field_n = tag_n;
}
  • 消息类型采用驼峰格式

  • 消息域采用小写字母蛇形格式

  • 基本数据类型有:

    string, bool, bytes,

    float, double

    int32, int64, uint32, uint4, sint32, sint64, etc.

  • 数据类型也可以是自定义的消息类型和枚举类型

  • tag_n :字段编号,用于二进制消息中识别各个字段,该编号在每个消息中唯一,且不可修改。注意在将message编码成二进制消息体时字段编号1-15将会占用1个字节,16-2047将占用两个字节。所以在一些频繁使用用的message中,你应该总是先使用前面1-15字段编号。

  • 注意在将message编码成二进制消息体时字段编号1-15将会占用1个字节,16-2047将占用两个字节。所以在一些频繁使用用的message中,你应该总是先使用前面1-15字段编号。

如何使用 proto buffers 定义一个 gRPC 服务?

mysql.proto 定义了一个 SelectRecord gRPC 接口

syntax = "proto3";                     // 1

package sample;                        // 2

option go_package = "./;pb";           // 3

import "google/api/annotations.proto"; // 4

message CreateMysqlRequest {           // 5
  string sql = 1;                      // 6
}

message CreateMysqlResponse {          // 7
  string body = 1;                     // 8
}

service MysqlService {                 // 9
  rpc SelectRecord(CreateMysqlRequest) returns (CreateMysqlResponse) { // 10
    option (google.api.http) = {       // 11
      post : "/v1/mysql/select"
      body : "*"
    };
  };
}
  1. syntax = "proto3";,文件开头指定版本号;

  2. package sample;,定义本服务的包名,避免不同服务相同消息类型产生冲突;

  3. option go_package = "./;pb";,生成 go 代码对应的路径和目录;

  4. import "google/api/annotations.proto";,需要引用外部 proto 文件时使用;

  5. CreateMysqlRequest,请求消息类型定义;

  6. sql,定义消息中域的名称和类型,支持的类型可参考下面的链接,后面的数字同一个类型下面必须唯一;

  7. CreateMysqlResponse,响应消息类型;

  8. body,定义消息中域的名称和类型,支持的类型可参考下面的链接,后面的数字同一个类型下面必须唯一;

  9. MysqlService,定义服务的接口名称;

  10. SelectRecord ,远程调用方法名;

  11. option (google.api.http)gRPC网关,用于支持 http 协议。

关于 proto buffers 详细内容可以参考谷歌的教程:https://developers.google.com/protocol-buffers/docs/gotutorial

使用编译器 protoc,可以将 proto 文件编译生成客户端和服务端存根代码,要让这些代码能能够正常工作,我们还需要做以下事情。

  • 服务端

在服务端代码中添加业务逻辑代码;

type MysqlServer struct{}

// NewMysqlServer returns a new MysqlServer
func NewMysqlServer() *MysqlServer {
  return &MysqlServer{}
}

// SelectRecord selects record with the specific table
func (server *MysqlServer) SelectRecord(
  ctx context.Context, req *pb.CreateMysqlRequest,
) (*pb.CreateMysqlResponse, error) {
  sql := req.GetSql()
  // business logic
  // ...
}

创建并启动 gRPC 监听端口,并返回响应客户端请求。

func main() {
  // step 1: news a server message struct
  mySqlServer := service.NewMysqlServer()
  
  // step 2: difines a listen address
  listener, _ := net.Listen("tcp", address)
  
  // setp 3: news a grpc server
  grpcServer := grpc.NewServer()

  // setp 4: regists grpc server 
  pb.RegisterMysqlServiceServer(grpcServer, mysqlServer)
  reflection.Register(grpcServer)

  // step 5: starts grpc server
  return grpcServer.Serve(listener)
}
  • 客户端

设置连接地址和端口号,调用 gRPC 接口(客户端和服务端可能使用不同的开发语言,需要使用 protoc 编译生成对应的开发语言代码)

func main() {
  serverAddress := flag.String("address", "", "the server address")
  flag.Parse()

  cc1, err := grpc.Dial(*serverAddress)

  mysqlClient := client.NewMysqlClient(cc1)

  // business logic
  log.Printf(mysqlClient.SelectRecord("SELECT * FROM users WHERE id=1;"))
}

到这里一个完整的 gRPC 服务就完成了,那么 gRPC 有哪些优势呢?

gRPC 的优势
  • 高效的进程间通信

    不同于文本传输的 JSONXMLgRPC 使用基于二进制 proto buffers 协议进行客户端和服务端之间的通信,它是基于 HTTP2 协议标准实现的,不同进程间通信更加的快捷。

图片

  • 服务接口定义更加简单,可读性好

图片

  • 支持多种语言,各个系统接入成本低

图片

  • 支持双向流模式

图片

  • 支持一些常用特性功能

    如权限校验,加密通信,服务超时服务截止时间,元数据交换,压缩,负载均衡以及服务发现等等。

  • 集成到了云原生生态中

    gRPC 作为云原生基金会的一个托管项目,大多数现代框架和技术都提供了对 gRPC 的支持。

gRPC 的劣势(相信我总能给你圆回来,哈哈)
  • 对于外部服务可能不是适用

    有可能对方(本公司)系统不支持 gRPC服务,也有可能不能向对方(非本公司)暴露gRPC服务。早期 gRPC 不支持 HTTP 请求,不过现在这个问题已经解决了,可以通过 gRPC网关将 http请求转为 gRPC请求。这样服务可以支持 gRPCHTTP 两种请求。

  • 对于频繁更迭的服务接口,不是很适用

    每次修改服务接口,我们通常需要重新生成客户端和服务端代码,需要将这些代码并入现存的持续集成服务中,这可能使得整体开发周期变得复杂。但是,gRPC 对于不破坏服务约定的修改具有很好的兼容性,允许客户端和服务端使用不同版本的 proto 文件,因此代码重新生成也不是什么问题。

  • 生态相对较小

    和传统的 REST/HTTP 协议相比,gRPC 在浏览器和移动端应用的支持还处于很初级的阶段。

gRPC 支持的四种传输类型
typerequestresponsescenario
unaryunaryunarynormal
client streamingstreamingunarycontinuous request
server streamingunarystreamingcontinuous response
bidirectional streamingstreamingstreamingcontinuous request and response
HTTP/2 versus HTTP/1/1

图片

体验一把:http://www.http2demo.io

gRPC versus REST

图片

参考资料

gRPC Up and Running

https://blog.csdn.net/weixin_39678525/article/details/110570486

https://developers.google.com/protocol-buffers/docs/gotutorial

https://www.bilibili.com/video/BV1Xv411t7h5?spm_id_from=333.999.0.0

获取更多知识请关注公众号——无涯的计算机笔记

图片

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值