【实战分享】漫谈 gRPC的选型

什么是 gRPC?

gRPC 的几种常见模式

在学习 gRPC 的时候,相信大家对于它的四种模式都有了解,我们来简单回顾一下:

  • 简单模式(Simple RPC):这种模式最为传统,即客户端发起一次请求,服务端响应一个数据,这和大家平时熟悉的 RPC 没有什么大的区别,所以不再详细介绍。

  • 服务端数据流模式(Server-side streaming RPC):这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。如果是使用我们容器云功能的同学应该会发现,我们的容器实时日志流就是使用了这个典型模式。

  • 客户端数据流模式(Client-side streaming RPC):与服务端数据流模式相反,这次是客户端源源不断地向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子是物联网终端向服务器报送数据。

  • 双向数据流模式(Bidirectional streaming RPC):顾名思义,这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。典型的例子是聊天机器人。

接下来我们通过一个小例子来看看 gRPC 具体的使用流程。

假设我们有一个聊天机器人,现需要增加一个对外提供服务的接口。具体需求为,接口传入参数是一个人名,返回一段内容是“Hello 人名”的音频。如果这个是让你在不使用 gRPC 的情况下,你会怎么做?大家可能会选择使用 restful api 来实现这个功能,传入人名,返回音频二进制数据。

那么如果使用 gRPC,我们需要怎么来设计呢?

第一步,需要定义一个接口文档,也就是 proto 文件。在定义内会定义一个 Service,接下来再在 Service 里定义一个 SayHello 的方法。下面定义传入参数,输入 name 返回 message,需要注意 message 是 bytes 类型,即返回的格式是二进制数据。对于 Golang 底层对应的是一个 bytes 数据,对于其他语言可能是字节流或二进制。

syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
bytes message = 1;

定义完成后 ,下一步就是使用 protoc 命令行工具生成代码。下图左侧是初始化的项目,你会发现,有一个单独的目录 protoc,存放了 hello.proto 这个文件,这个文件就是前面定义好的。

下图右侧是自动生成代码后的项目结构,生成了一个 pkg/helloworld 的包,里面有一个 hello.pb.go,打开这个文件,你会发现刚才定义的 proto 已经被翻译成了 Go 语言。具体 protoc 命令行工具如何使用,可以自行搜索下,这里不再过多展开。

定义好了 proto 文件,以及生成了相应的 package 代码,下一步我们就可以编写业务逻辑了。

Hello gRPC - 服务端业务代码

import (
"google.golang.org/grpc"
pb "grpc-hw/pkg/helloworld"
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
tempFile := "srv.wav"
err := exec.Command("flite", "-t", "Hello "+in.GetName(), "-o", tempFile).Run()
if err != nil {
return nil, fmt.Errorf("make audio failed: %v", err)
}
data, _ := ioutil.ReadFile(tempFile)
return &pb.HelloReply{Message: data}, nil
}
func main() {
lis, _ := net.Listen("tcp", port)
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
s.Serve(lis)
}

在服务端侧,需要实现 SayHello 的方法来满足 GreeterServer 接口的要求。SayHello 方法的传入参数,是在 proto 文件中定义的 HelloRequest,传出参数,是在 proto 文件中定义的 HelloReply,以及一个 error。

业务逻辑也比较简单,获取 HelloRequest 中 Name 字段,然后通过命令行行工具转换成对应的音频,将 bytes 数组存在在 HelloReply 中返回。

Hello gRPC - 客户端业务代码

func main() {
flag.StringVar(&address, "addr", address, "server address")
flag.StringVar(&name, "name", "world", "name")
flag.Parse()
// Set up a connection to the server.
conn, _ := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
tempFile := "cli.wav"
ioutil.WriteFile(tempFile, r.Message, 0666)
exec.Command("afplay", tempFile).Run()
}

我们再来看一下如何实现 Client。首先,建立一个 gRPC 的连接,并初始化 GreeterClient,然后直接调用下 GreeterClient 的 SayHello 的方法,将把返回结果另存为一个文件,通过播放器播放就可以了。

总体而言,整个使用过程很简单,并且非常容易上手,让开发可以更加关注在客户端、服务端业务的实现,不用操心传输层的事情。

gRPC 的使用总结

通过刚刚的小例子,我们来总结一下 gRPC 的使用:

  • 定义好接口文档

  • 工具生成服务端/客户端代码

  • 服务端补充业务代码

  • 客户端建立 gRPC 连接后,使用自动生成的代码调用函数

  • 编译、运行

以上 5 步就是 gRPC 的简单使用方法了。

gRPC 与 Protobuf

接下来我们来聊聊 gRPC 跟 Protobuf 之间的联系,当然在这之前我们需要先知道 Protobuf 是什么。

Protobuf

Protobuf 是一个语言无关、平台无关的可扩展的结构化数据序列化方案。大家可能会觉得它跟 JSON 好像没什么区别,功能上看起来是一样的,但像上文那样去定义 SayHello 的操作,JSON 是做不到的,JSON 只能定义一个请求体或者一个返回体,没法定义一个方法,但是 Protobuf 是可以的。

Protobuf 多用于协议通讯、数据存储和其他更多用途。它是一个比较灵活的、高效的、自动化的结构化数据序列机制,但是更小,更快并且更简单。一旦定义好数据如何构造, 就可以使用特殊生成的代码来轻易地读写结构化数据,无需关心用什么语言来实现。你甚至可以更新数据结构而不打破已部署的使用"旧有"格式编译的程序。

上图是 Protobuf 与 JSON 以及 JSON stream 三者之间的性能比较,可以明显的看到在解码的时候 Protobuf 比其他两项快了不只一星半点。

Protobuf  与 XML、JSON 的吞吐量比较

上图中,我们可以看到 Protobuf 还是有一些缺点的,比如浏览器的支持没有其他几个支持的好。但是,在数据安全方面,由于传输过程中采用的是加密压缩后的字节流,一般无法直接查看,安全性非常好。以及在处理速度方面,因为编解码效率很高使得整体吞吐量有了显著提升。还有一点,定义方法,这个是其他两种序列化协议所做不到的。

gRPC 跟 Protobuf 的联系

虽然每次 gRPC 与 Protobuf 都是同时出现的,但是其实两者之间并没有很深的联系。只是因为两者都是由 Google 开发的,和 gRPC 本身负载无关,在使用时也可以选择 JSON 等等,但是考虑到 Protobuf 有定义方法的优势,在微服务里还是很推荐使用的。

gRPC vs Restful API

上图是 gRPC 与 Restful API 的对比,平常我们可能更多使用 Restful API。但从图上可以看到,因为 gRPC 用的是 Protobuf,本身就比较小所以很快,不像 JSON 体积比较大、比较慢。另外,gRPC 是加载 HTTP/2 上面的,延迟比较低,也因为 HTTP/2 支持链接复用,这就可以让多个 stream 共用一个连接,从而进一步提升速度。对比 Restful 则使用的是 HTTP 1.1,延迟比较高,而且在一般情况下,每次请求都需要建一下新的连接。

gRPC 是双向的。什么是双向呢?比如我们平常做 Restful,都是从客户端到服务端,但是服务端没办法直接主动向客户端发送信息,gRPC 则可以。gRPC 也支持流,Restful只支持Request/Response 这样的机制。gRPC是面向 API 的,没有限制,也面向增删改查。gRPC 可以通过 Protobuf 直接生成代码,而 Restful 需要依赖第三方。

另外 gRPC 支持 RPC 可以调用服务器上的一些方法,而 Restful 是基于HTTP的语法,很多东西需要自己去定义。这方面相信大家都有感触,比如 REST 定义post/put/delete/get时,因为每个人都有自己的习惯,所以协作时需要沟通讨论进行指定。但是 gRPC 就不需要了,它支持定义函数式办法,不需要大家去考虑如何设计语法。

以上就是 gRPC 跟 Restful API 的对比。

引入 gRPC 需要考虑哪些问题?

那么当我们引入 gRPC 的时候需要考虑什么呢?以下几点肯定是不可避免的考虑项:

  • 是否可以满足当前需求

  • 性能如何

  • 连接异常断开后,是否需要客户端重试

  • TCP 连接是否可以复用

  • 业务层改动是否足够便利

  • 业务后期迭代是否会出现问题,如何避免

这个也是我们引入一项新的东西时,往往需要考虑到的问题。

回顾与总结

从选择 gRPC 到整个项目落地,以及现在上线后正常使用。整个过程中,我对于项目的思考可以包括了过去、现在和未来三个阶段。

对我而言,过去就是要去看我选择的这个东西,用的人多不多,完善程度怎么样了?而现在则是要结合项目,看看合不合适,能不能使用。当然不能思考到能使用就结束,我们还需要考虑这个项目在未来的 3-5 年的发展,你引入它后在这个时间内需不需要大的变动。这个是非常重要的,虽然我们现在常说敏捷开发,也经常会进行很多的调整,但是在类似 gRPC 这种底层基础来说,是固定的。

以上就是我今天的全部分享内容,讲的比较简单,希望能带给大家一些收获。

相关推荐

3 分钟了解 NVIDIA 新出的 H200

英伟达在 2023 年全球超算大会上发布了备受瞩目的新一代 AI 芯片——H200 Tensor Core GPU。相较于上一代产品 H100,H200 在性能上实现了近一倍的提升,内存容量翻倍,带宽也显著增加……

github_36774378的博客 2380

深入了解浮点运算——CPU 和 GPU 算力是如何计算的

算力最基本的计量单位是 FLOPS,英文 Floating-point Operations Per Second,即每秒执行的浮点运算次数。浮点运算其实就是带小数的加减乘除运算。

github_36774378的博客 5104

加速计算,为何会成为 AI 时代的计算力“新宠”

加速计算是指使用专用硬件来执行某些类型的计算,其效率要比仅使用通用中央处理器(CPU)高。利用图形处理单元(GPU)、专用集成电路(ASIC)(包括张量处理单元(TPU))和现场可编程逻辑门阵列(FPGA)等设备的强大功能,以更高的速度执行计算,从而加速计算过程,一般我们也将这些设备称之为加速器。这些加速器尤其适用于可被分解为较小并行任务的项目,如高性能计算 (HPC)、深度学习、机器学习、人工智能和大数据分析。通过将指定类型的工作分派到这些专用加速计算硬件上,大大提高了系统的性能和效率。

github_36774378的博客 1072

NVIDIA RTX4090,你能用它做什么?

如果女生选择给男生送礼,我相信一块 RTX4090 就足以让他高兴得死去活来。RTX4090 到底是何方神圣?它凭什么赢得所有男生的“芳心”?

github_36774378的博客 2353

3 分钟看完 NVIDIA GPU 架构及演进

近期随着 AI 市场的爆发式增长,作为 AI 背后技术的核心之一 GPU(图形处理器)的价格也水涨船高。GPU 在人工智能中发挥着巨大的重要,特别是在计算和数据处理方面。目前生产 GPU 主流厂商其实并不多,主要就是 NVIDIA、AMD、Intel、高通等厂家。本文将主要聊聊 NVIDIA GPU 的核心架构及架构演进。

github_36774378的博客 1983

聊聊 GPU 产品选型那些事

随着人工智能的飞速崛起,随之而来的是算力需求的指数级增加,CPU 已经不足以满足深度学习、大模型计算等场景的海量数据处理需求。GPU 作为一种强大的计算工具,无论是高性能计算、图形渲染还是机器学习领域,在各个领域展现出了巨大的潜力和应用前景。说起 GPU,绕不过的当然是 NVIDIA 这个公司了,现在市面上火热的 A100/A800、H100 等 GPU 全是他家的产品。但当你有业务需求或者个人需求,想要采购 GPU 的时候,你会发现各个型号的 GPU 令你眼花缭乱。

github_36774378的博客 985

巅峰对决:英伟达 V100、A100/800、H100/800 GPU 对比

近期,不论是国外的 ChatGPT,还是国内诸多的大模型,让 AIGC 的市场一片爆火。而在 AIGC 的种种智能表现背后,均来自于堪称天文数字的算力支持。以 ChatGPT 为例,据微软高管透露,为 ChatGPT 提供算力支持的 AI 超级计算机,是微软在 2019 年投资 10 亿美元建造一台大型顶尖超级计算机,配备了数万个 NVIDIA A100 GPU,还配备了 60 多个数据中心总共部署了几十万个 NVIDIA GPU 辅助。

github_36774378的博客 1万+

InfiniBand 的前世今生

今年,以 ChatGPT 为代表的 AI 大模型强势崛起,而 ChatGPT 所使用的网络,正是 InfiniBand,这也让 InfiniBand 大火了起来。那么,到底什么是 InfiniBand 呢?下面,我们就来带你深入了解 InfiniBand。

github_36774378的博客 865

揭秘神秘的字符串匹配工具——正则表达式

每个正则表达式都有一个有限自动机(也称为状态机),它接受表达式指定的语言,并使用 Thompson 构造算法将正则表达式转化为一个与之等价的非确定有限状态自动机(NFA)。同时,对于每个有限自动机来说,还有一个描述该自动机所接受语言的正则表达式。该表达式可以通过克莱恩算法或高斯消元法生成。正则表达式的一个著名应用是文本编辑器中的搜索和替换功能,计算机先驱 Ken Thompson( UNIX 操作系统的开发者之一)首先在 20 世纪 60 年代的面向行编辑器 QED 中实现了该功能。

github_36774378的博客 382

深入了解 GPU 互联技术——NVLINK

随着人工智能和图形处理需求的不断增长,多 GPU 并行计算已成为一种趋势。对于多 GPU 系统而言,一个关键的挑战是如何实现 GPU 之间的高速数据传输和协同工作。然而,传统的 PCIe 总线由于带宽限制和延迟问题,已无法满足 GPU 之间通信的需求。为了解决这个问题,NVIDIA 于 2018 年推出了 NVLINK,以提高 GPU 之间的通信效率。

github_36774378的博客 3874

各快 100 倍?4G、5G、6G 相差这么多吗

二狗子今天晚上有点 emo,为什么呢?原来是二狗子心心念很久的一个手游上线了,二狗子兴冲冲地下载了 40 多分钟,终于下载完了游戏。结果打开游戏一看,发现游戏内部的更新写着预计 30 分钟完成更新。这就把二狗子搞得 emo 了。二狗子突然发现自己的室友已经在这款游戏的新手村大杀四方了。“你怎么这么快?”二狗子问。“我用手机流量下载的,5G,当然快。”室友都没看二狗子一眼,沉浸在自己的游戏世界里。5G 真的有这么快吗?好学的二狗子就让游戏保持着后台更新,在网上冲浪学习下知识充实自己。

github_36774378的博客 468

为什么大家都在用 WebP?

WebP 是谷歌在 2010 年提出的一种新型的图片格式,放到现在来讲,已经不算是“新”技术了,毕竟已经有了更新的 JPEG XL 和 AVIF。但是在日常工作中,大家时常会碰到保存下来的图片的后缀是 .webp。那么 WebP 到底有什么魔力,让越来越多的网站“抛弃”常用的 PNG、JPG 而青睐它呢?

github_36774378的博客 958

从驾考科目二到自动驾驶,聊聊 GPU 为什么对自动驾驶很重要

这些数据包含前车和本车的距离,左右两边的道路指示标志,周围汽车的距离,前方道路指示标志,红绿灯信号,马路边行人,非机动车等信息等,大量的图像和视频信息被转换成电脑能处理的二进制信息,这就需要 CPU 和 GPU 的共同加持才能完成安全稳定的自动驾驶工作。

github_36774378的博客 361

聊透 GPU 通信技术——GPU Direct、NVLink、RDMA

AI 技术对算力的需求是非常庞大的,虽然 GPU 的计算能力在持续提升,但是对于 AI 来说,单卡的计算能力就算再强,也是有极限的,这就需要多 GPU 组合。而 GPU 多卡的组合,主要分为单个服务器多张 GPU 卡和多个服务器,每个服务器多张卡这两种情况,无论是单机多卡还是多机多卡,GPU 之间需要有超强的通信支持。

github_36774378的博客 2570

这个 AI 机器人会怼人,它是怎么做到的?

人工智能可以定义为计算机科学的一个分支,其目标是创造与人类智力相当的技术。但智力到底是什么?如何利用技术来复制智力?这个疑问并不存在单一的理解,目前已经有了许多理论和方法来回答这些问题。人工智能的实现方式主要有两种:一种是基于规则的人工智能,通过预先编写的规则和逻辑来实现特定的任务;另一种是基于机器学习的人工智能,通过让计算机从数据中学习和优化算法,来实现特定的任务。

github_36774378的博客 717

如何评估计算机的算力:从 CPU 到 GPU 的演变

这就是 CPU 和 GPU 在计算能力上的区别,这是由它们的架构决定的,CPU 可以执行任何程序,而 GPU转为多任务而生,并发能力强。当然,上面的两张图并不是说 GPU 比 CPU 厉害,事实上,CPU 和 GPU 各自具有不同的特点和优势,选择哪种设备取决于具体的应用场景和需求。其中,CPU(中央处理器)和 GPU(图形处理器)是计算机中最为核心的两个组件,它们的算力和性能对于计算机的整体性能具有决定性的影响。CPU 是计算机的核心组件之一,它的主要功能是执行指令、控制计算机的运行和处理数据等任务。

github_36774378的博客 2390

浅谈 Linux 下 vim 的使用

底线模式的进入方法为:在命令模式下按":“键,Vim 窗口的左下方会出现一个”:"符号,这时就可以输入相关的指令进行操作了。在此模式下可以使用上、下、左、右键或者k、j、h、l键进行光标的移动,还可以对文件内容进行复制、粘贴、替换、删除等操作。当编辑完成,就可以按 Esc 退出插入模式,进入到命令模式。p : 黏贴,此命令是在命令模式下,按照上面的命令复制后,然后光标移动到想要复制的位置,然后按 p 黏贴。直接到某行:在底线模式下直接输入数字就可以到想到的行,如果输入的数字比文档的行数多就会到最后一行。

github_36774378的博客 1311

如何高效实现 MySQL 与 elasticsearch 的数据同步

MySQL 自身简单、高效、可靠,是又拍云内部使用最广泛的数据库。但是当数据量达到一定程度的时候,对整个 MySQL 的操作会变得非常迟缓。而公司内部 robin/logs 表的数据量已经达到 800w,后续又有全文检索的需求。这个需求直接在 MySQL 上实施是难以做到的。

github_36774378的博客 724

国密证书 VS 传统 SSL 证书,到底区别在哪?

国密算法,即国家商用密码算法。是我国自主研发创新的一套数据加密处理系列算法。从 SM1-SM4 分别实现了对称、非对称、摘要等算法功能。尤其适用于嵌入式物联网等相关领域,完成身份认证和数据加解密等功能。

github_36774378的博客 1310

又拍云邵海杨 - 25年Linux老兵,聊聊运维的“术”与“道”

邵海杨,从1998年开始使用Linux至今快25年了,资深Linux系统运维/架构师,DevOps八荣八耻倡导者,喜欢交流分享,活跃于社区,一直积极投身于开源活动的组织和传播。

github_36774378的博客 745

从 AI 绘画到 ChatGPT,聊聊生成式 AI

无论是 AI 绘画,还是现在风靡全球的 ChatGPT,它们都属于 AI 的一个分支——生成式AI(Generative AI)。相较于传统的 AI 模型,生成式 AI 是一种特定类型的 AI,它专注于创建新内容。

github_36774378的博客 5755

从 B 站出发,用 Chrome devTools performance 分析页面如何渲染

页面是如何渲染的?从 Chrome 的性能工具开始,具体看看一个页面是如何进行渲染的,以及进行页面优化时需要关注哪些指标。

github_36774378的博客 1136

【白话科普】聊聊网络架构变革的关键——SDN

SDN 即软件定义网络,它描述了一种网络架构,可以使用软件对单个硬件组件进行集中、智能的管理和控制,使用 OpenFlow 等开放协议允许访问网络设备,如交换机、路由器或防火墙等。

github_36774378的博客 1838

二狗子翻车了,只因上了这个网站……

通过 fetch API 或 XMLHttpRequest 等方式发起的 HTTP 请求,必须要遵守同源策略 ,那什么是同源策略呢?为什么这个策略会导致我们的信息在浏览器上被盗用。

github_36774378的博客 659

一文读懂 Kubernetes 存储设计

在 Docker 的设计中,容器内的文件是临时存放的,通过在 docker run 启动容器时,使用 --volume/-v 参数来指定挂载卷,将容器内部的路径挂载到主机,来保证即便容器被删除,保存到主机路径中的数据也仍然存在。

github_36774378的博客 545

从实战出发,聊聊缓存数据库一致性

在云服务中,缓存是极其重要的一点。所谓缓存,其实是一个高速数据存储层。本文主要介绍更新数据库成功后,更新缓存和删除缓存这两个操作的区别和改进方案。

github_36774378的博客 584

当谈论 React hook,我们究竟说的是什么?

React hook是什么,所谓 React hook,就是增强函数组件能力特性的钩子,把不同的特性「钩」进纯函数。React hook 的由来,其实也可以看作是前端技术不断演进的结果。

github_36774378的博客 589

视频网站节约 30% 成本的秘密在这里

今年,爱奇艺宣布2022年第一季度首次实现季度盈利,长视频行业发展十几年来,一直深陷亏损旋涡。爱奇艺的首次实现季度盈利,也意味着降本增效将成为视频平台的发展方向。

github_36774378的博客 965

【白话科普】从“熊猫烧香”聊聊计算机病毒

到底什么是计算机病毒呢?它是什么途径传播的,又会带来哪些危害,我们又该如何在日常使用电脑中防止感染病毒呢?

github_36774378的博客 1642

【实操日记】使用 PyQt5 设计下载远程服务器日志文件程序

PyQt5 是一套 Python 绑定 Digia Qt5 应用的框架,是最强大的 GUI 库之一,使用 PyQt5 我们能够很容易的开发桌面应用,我们如何用 PyQt5 设计一个下载服务器指定日期日志文件的程序。

github_36774378的博客 1117
上一篇: 白话科普系列——最好用的浏览器 Chrome,你用了么?
下一篇: 这些表情包你有吗?来 Battle 啊
又拍云 UPYUN
又拍云 UPYUN 又拍云官方账号 又拍云官方账号
博客等级 码龄10年 153粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值