Go gRPC 系列一:相关介绍

你们好,我是煎鱼,做为开篇章,今天将会介绍 gRPC 相关的一些知识。简单来说 gRPC 是一个 基于 HTTP/2 协议设计的 RPC 框架,它采用了 Protobuf 做为 IDLgit

你是否有过疑惑,它们都是些什么?本文将会介绍一些经常使用的知识和概念,更详细的会给出手册地址去深刻github

1、RPC

什么是 RPC

RPC 代指远程过程调用(Remote Procedure Call),它的调用包含了传输协议和编码(对象序列号)协议等等。容许运行于一台计算机的程序调用另外一台计算机的子程序,而开发人员无需额外地为这个交互做用编程apache

实际场景:

有两台服务器,分别是A、B。在 A 上的应用 C 想要调用 B 服务器上的应用 D,它们能够直接本地调用吗?
答案是不能的,但走 RPC 的话,十分方便。所以常有人称使用 RPC,就跟本地调用一个函数同样简单编程

RPC 框架

我认为,一个完整的 RPC 框架,应包含负载均衡、服务注册和发现、服务治理等功能,并具备可拓展性便于流量监控系统等接入
那么它才算完整的,固然了。有些较单一的 RPC 框架,经过组合多组件也能达到这个标准json

你认为呢?安全

常见 RPC 框架

比较一下

\ 跨语言 多 IDL 服务治理 注册中心 服务管理
gRPC × × × ×
Thrift × × × ×
Rpcx ×
Dubbo ×

为何要 RPC

简单、通用、安全、效率bash

RPC 能够基于 HTTP 吗

RPC 是代指远程过程调用,是能够基于 HTTP 协议的服务器

确定会有人说效率优点,我能够告诉你,那是基于 HTTP/1.1 来说的,HTTP/2 优化了许多问题(固然也存在新的问题),因此你看到了本文的主题 gRPC网络

2、Protobuf

介绍

Protocol Buffers 是一种与语言、平台无关,可扩展的序列化结构化数据的方法,经常使用于通讯协议,数据存储等等。相较于 JSON、XML,它更小、更快、更简单,所以也更受开发人员的青眯app

语法

syntax = "proto3";

service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse);
}

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
    ...
}
复制代码

一、第一行(非空的非注释行)声明使用 proto3 语法。若是不声明,将默认使用 proto2 语法。同时我建议用 v2 仍是 v3,都应当声明其使用的版本

二、定义 SearchService RPC 服务,其包含 RPC 方法 Search,入参为 SearchRequest 消息,出参为 SearchResponse 消息

三、定义 SearchRequestSearchResponse 消息,前者定义了三个字段,每个字段包含三个属性:类型、字段名称、字段编号

四、Protobuf 编译器会根据选择的语言不一样,生成相应语言的 Service Interface Code 和 Stubs

最后,这里只是简单的语法介绍,详细的请右拐 Language Guide (proto3)

数据类型

.proto Type C++ Type Java Type Go Type PHP Type
double double double float64 float
float float float float32 float
int32 int32 int int32 integer
int64 int64 long int64 integer/string
uint32 uint32 int uint32 integer
uint64 uint64 long uint64 integer/string
sint32 int32 int int32 integer
sint64 int64 long int64 integer/string
fixed32 uint32 int uint32 integer
fixed64 uint64 long uint64 integer/string
sfixed32 int32 int int32 integer
sfixed64 int64 long int64 integer/string
bool bool boolean bool boolean
string string String string string
bytes string ByteString []byte string

v2 和 v3 主要区别

  • 删除原始值字段的字段存在逻辑
  • 删除 required 字段
  • 删除 optional 字段,默认就是
  • 删除 default 字段
  • 删除扩展特性,新增 Any 类型来替代它
  • 删除 unknown 字段的支持
  • 新增 JSON Mapping
  • 新增 Map 类型的支持
  • 修复 enum 的 unknown 类型
  • repeated 默认使用 packed 编码
  • 引入了新的语言实现(C#,JavaScript,Ruby,Objective-C)

以上是平常涉及的常见功能,若是还想详细了解可阅读 Protobuf Version 3.0.0

相较 Protobuf,为何不使用XML?

  • 更简单
  • 数据描述文件只需原来的1/10至1/3
  • 解析速度是原来的20倍至100倍
  • 减小了二义性
  • 生成了更易使用的数据访问类

3、gRPC

介绍

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计

多语言

  • C++
  • C#
  • Dart
  • Go
  • Java
  • Node.js
  • Objective-C
  • PHP
  • Python
  • Ruby

特色

一、HTTP/2

二、Protobuf

三、客户端、服务端基于同一份 IDL

四、移动网络的良好支持

五、支持多语言

概览

image

讲解

一、客户端(gRPC Sub)调用 A 方法,发起 RPC 调用

二、对请求信息使用 Protobuf 进行对象序列化压缩(IDL)

三、服务端(gRPC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回

四、对响应结果使用 Protobuf 进行对象序列化压缩(IDL)

五、客户端接受到服务端响应,解码请求体。回调被调用的 A 方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果

示例

在这一小节,将简单的给你们展现 gRPC 的客户端和服务端的示例代码,但愿你们先有一个基础的印象,将会在下一章节详细介绍 🤔

构建和启动服务端

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
        log.Fatalf("failed to listen: %v", err)
}

grpcServer := grpc.NewServer()
...
pb.RegisterSearchServer(grpcServer, &SearchServer{})
grpcServer.Serve(lis)
复制代码

一、监听指定 TCP 端口,用于接受客户端请求

二、建立 gRPC Server 的实例对象

三、gRPC Server 内部服务和路由的注册

四、Serve() 调用服务器以执行阻塞等待,直到进程被终止或被 Stop() 调用

建立客户端

var opts []grpc.DialOption
...
conn, err := grpc.Dial(*serverAddr, opts...)
if err != nil {
    log.Fatalf("fail to dial: %v", err)
}

defer conn.Close()
client := pb.NewSearchClient(conn)
...
复制代码

一、建立 gRPC Channel 与 gRPC Server 进行通讯(需服务器地址和端口做为参数)

二、设置 DialOptions 凭证(例如,TLS,GCE凭据,JWT凭证)

三、建立 Search Client Stub

四、调用对应的服务方法

思考题

一、什么场景下不适合使用 Protobuf,而适合使用 JSON、XML?

二、Protobuf 一节中提到的 packed 编码,是什么?

总结

在开篇内容中,我利用了尽可能简短的描述给你介绍了接下来所必须、必要的知识点 但愿你可以有所收获,建议能到我给的参考资料处进行深刻学习,是最好的了

若是有任何疑问或错误,欢迎在 issues 进行提问或给予修正意见,若是喜欢或对你有所帮助,欢迎 Star,对做者是一种鼓励和推动。

个人公众号

image

参考资料

相关文章
相关标签/搜索