gRPC(三)基础:gRPC快速入门

简介: Protobuf 是 Google 的序列化/反序列化协议,可以轻松定义服务和自动生成客户端库。gRPC 使用此协议作为其接口定义语言 (IDL) 和序列化工具集。

前言


个人网站:https://linzyblog.netlify.app/

示例代码已经上传到github:点击跳转

gRPC官方文档:点击跳转


一、gRPC概述


1、什么是gRPC?


gRPC 是一个强大的开源 RPC(远程过程调用)框架,用于构建可扩展且快速的 API。它允许客户端和服务器应用程序透明地通信并开发连接的系统。gRPC框架依赖 HTTP/2、协议缓冲区和其他现代技术堆栈来确保最大的 API 安全性、性能和可扩展性。


在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像是本地对象一样,更容易创建分布式应用程序和服务。


与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。在服务端,服务端实现这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端,客户端有一个存根(自动生成的文件),它提供与服务器相同的方法。


65739071138f4cbeb98dec3befa78154.png


2、gRPC 的历史


2015 年,Google 开发了 gRPC 作为 RPC 框架的扩展,以链接使用不同技术创建的许多微服务。最初,它与 Google 的内部基础设施密切相关,但后来,它被开源并标准化以供社区使用。在其发布的第一年,顶级组织利用它来支持从微服务到 Web、移动和物联网的用例。并在 2017 年因越来越受欢迎而成为云原生计算基金会(CNCF)孵化项目。


3、使用Protobuf


Protobuf 是 Google 的序列化/反序列化协议,可以轻松定义服务和自动生成客户端库。gRPC 使用此协议作为其接口定义语言 (IDL) 和序列化工具集。


  • 客户端和服务器之间的 gRPC 服务和消息在 proto 文件中定义。


  • Protobuf 编译器 protoc 生成客户端和服务器代码,在运行时将 .proto 文件加载到内存中,并使用内存中的模式来序列化/反序列化二进制消息。


  • 代码生成后,每条消息都会在客户端和远程服务之间进行交换。


为什么使用Protobuf?

使用 Protobuf 进行解析需要更少的 CPU 资源,因为数据被转换为二进制格式,并且编码的消息的大小更轻。因此,消息交换速度更快,即使在 CPU 速度较慢的机器(例如移动设备)中也是如此。


4、gRPC架构


在下面的 gRPC 架构图中,我们有 gRPC 客户端和服务器端。在 gRPC 中,每个客户端服务都包含一个存根(自动生成的文件),类似于包含当前远程过程的接口。


gRPC工作流程:


  • gRPC 客户端将要发送到服务器的参数对存根进行本地过程调用。


  • 客户端存根使用 Protobuf 使用编组过程序列化参数,并将请求转发到本地机器中的本地客户端时间库。


  • 操作系统通过 HTTP/2 协议调用远程服务器机器。


  • 服务器的操作系统接收数据包并调用服务器存根程序,该程序对接收到的参数进行解码并使用 Protobuf 执行相应的程序调用。


  • 服务器存根将编码响应发送回客户端传输层。客户端存根取回结果消息并解包返回的参数,然后执行返回给调用者。


84fd0a66d828452ca6afbae8dd031de5.png


二、准备工作


使用 Go 来编写 gRPC Server 和 Client,让其互相通讯。在此之上会使用到如下库:


下面示例是在 windows环境中安装。


google.golang.org/grpc
google.golang.org/protobuf/cmd/protoc-gen-go
google.golang.org/grpc/cmd/protoc-gen-go-grpc


1.初始化项目go mod init 项目名称模块管理依赖项


go mod init go-grpc-examle


2.安装protoc:


➜ go get -u google.golang.org/grpc


通过--version命令查看是否安装成功:


➜ protoc --version
libprotoc 3.20.1


2.使用以下命令为 Go 安装协议编译器插件:


➜ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
➜ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2


验证插件是否安装成功:


➜ protoc-gen-go --version
protoc-gen-go.exe v1.28.1
➜ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.2.0


3.更新你的PATH,以便protoc编译器可以找到插件(你不在gopath下创建的项目,这里自行百度改一下PATH)


三、编写gRPC Client and Server


1、目录结构


go-grpc-example
├── client
│   └──hello_client
│     └── client.go
├── proto
│   └──hello
│     └── hello.proto
├── server
│   └──hello_server
│     └── server.go


2、编写 .proto 文件


syntax = "proto3";
// 定义go生成后的包名
option go_package = "./;hello";
package proto;
// 定义入参
message Request {
  string name =1;
}
// 定义返回
message Response {
  string result = 1;
}
// 定义接口
service UserService {
  rpc Say(Request) returns (Response);
}


3、生成Go代码


# 同时生成hello.pb.go 和 hello_grpc.pb.go
➜ protoc --go-grpc_out=. --go_out=. hello.proto


当前目录下可以看到生成两个文件:


f2da544cb2754ce7b4e2c4e923de1d9c.png


4、编写 Server 服务端代码


编写 gRPC Server 的基础模板,完成一个方法的调用。对 server.go 写入如下内容:


type HelloService struct {
  // 必须嵌入UnimplementedUserServiceServer
  hello.UnimplementedUserServiceServer
}
// 实现SayHi方法
func (h *HelloService) SayHi(ctx context.Context, req *hello.Request) (res *hello.Response, err error) {
  format := time.Now().Format("2006-01-02 15:04:05")
  return &hello.Response{Result: "hi " + req.GetName() + "---" + format}, nil
}
const PORT = "8888"
func main() {
  // 创建grpc服务
  server := grpc.NewServer()
  // 注册服务
  hello.RegisterUserServiceServer(server, &HelloService{})
  // 监听端口
  lis, err := net.Listen("tcp", ":"+PORT)
  if err != nil {
    log.Fatalf("net.Listen err: %v", err)
  }
  server.Serve(lis)
}


5、编写 Client 客户端代码


接下来编写 gRPC Go Client 的基础模板,打开 hello_client/client.go 文件,写入以下内容:


const PORT = "8888"
func main() {
  // 建立链接
  conn, err := grpc.Dial(":"+PORT, grpc.WithInsecure())
  if err != nil {
    log.Fatalf("grpc.Dial err: %v", err)
  }
  // 一定要记得关闭链接
  defer conn.Close()
  // 实例化客户端
  client := hello.NewUserServiceClient(conn)
  // 发起请求
  response, err := client.SayHi(context.Background(), &hello.Request{Name: "lin钟一"})
  if err != nil {
    log.Fatalf("client.SayHi err: %v", err)
  }
  fmt.Printf("resp: %s", response.GetResult())
}


6、启动 & 请求


# 启动服务端
$ go run server.go
API server listening at: 127.0.0.1:50970
# 启动客户端
$ go run client.go 
API server listening at: 127.0.0.1:51040
resp: hi lin钟一---2022-11-01 14:54:01


四、小结


在本文,我们对 gRPC Client/Server 进行了介绍和了解。希望你结合第一章写的rpc请求的方法对文中讲述内容再写一个 Demo 进行深入了解。


下一篇关于gRPC Streaming的内容,gRPC 三种类型的流式。


  • Server-side streaming RPC:服务器端流式 RPC
  • Client-side streaming RPC:客户端流式 RPC
  • Bidirectional streaming RPC:双向流式 RPC
目录
相关文章
|
安全 JavaScript 前端开发
QML信号与信号槽实践指南:轻松掌握现代软件开发的关键技术(三)
QML信号与信号槽实践指南:轻松掌握现代软件开发的关键技术
429 0
|
存储 C语言 内存技术
专为MCU项目开发提速的代码框架BabyOS
专为MCU项目开发提速的代码框架BabyOS
367 0
|
3月前
|
传感器 人工智能 JavaScript
Playwright实战:写UI自动化脚本,速度直接起飞
简介: 测试工程师老王因UI自动化问题深夜奋战,反映出传统测试工具的局限性。微软开源的Playwright凭借智能等待、跨域操作、移动端模拟与网络拦截等强大功能,正迅速取代Selenium,成为新一代自动化测试标准。其稳定高效的设计显著降低维护成本,助力企业构建高质量测试流程。
|
机器学习/深度学习 数据挖掘
机器学习之聚类——模糊聚类FCM
机器学习之聚类——模糊聚类FCM
554 4
|
存储 算法 数据可视化
|
缓存 JSON 负载均衡
http请求grpc服务的最终解决方案
所有的rpc协议遵守着一个万变不离其宗的定律:调用方与服务提供方有一套约定的报文解析格式。nodejs做代理,http报文组装成grpc报文,必须依赖.proto文件中定义的消息体
2250 0
http请求grpc服务的最终解决方案
|
存储 缓存 NoSQL
使用 Spring Cache 实现缓存,这种方式才叫优雅!
使用 Spring Cache 实现缓存,这种方式才叫优雅!
|
负载均衡 应用服务中间件 Linux
Nginx系列教程(12) - HTTP动态负载均衡(二)
Nginx系列教程(12) - HTTP动态负载均衡(二)
374 1
|
XML 存储 JSON
gRPC(二)入门:Protobuf入门
Any以字节的形式包含任意序列化的消息,以及作为该消息类型的全局唯一标识符并解析为该消息类型的URL。要使用Any类型,您需要 import google/protobuf/any.proto
699 0
gRPC(二)入门:Protobuf入门
|
安全 C++ 数据格式
C++ 字符串格式化转为 数据变量 - sscanf,sscanf_s及其相关用法
C++ 字符串格式化转为 数据变量 - sscanf,sscanf_s及其相关用法
494 1