热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分布式服务框架gRPC

什么是gRPCgRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP2协议标准而设计,基于Pro

什么是gRPC

gRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于Protobuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。在gRPC中一个客户端可以像使用本地对象那样直接调用位于不同机器上的服务端应用的方法(methods)。这让你能够更容易的构建分布式的应用和服务。和其他RPC系统类似,gRPC也是基于定义一个服务,指定服务可以被远程调用的方法以及他们的参数和返回类型。在服务端,实现服务的接口然后运行一个gRPC服务来处理可出端的请求。在客户端,客户端拥有一个存根(stub在某些语言中仅称为客户端),提供与服务器相同的方法。

![grpc](/Users/qsc/Desktop/Writing/grpc.png)

·gRPC客户端和服务器可以在各种环境中运行并相互通信,并且可以使用gRPC支持的任何语言编写。因此,例如,您可以使用Go,Python或Ruby的客户端轻松地用Java创建gRPC服务器。此外,最新的Google API的接口将拥有gRPC版本,可让您轻松地在应用程序中内置Google功能。


使用protocol buffer

默认情况下,gRPC使用protocol buffer,用于序列化结构化数据(尽管它可以与其他数据格式(例如JSON)一起使用)。使用协议缓冲区的第一步是在proto文件中为要序列化的数据定义结构:proto文件扩展名为.proto的普通文本文件。protocol buffer数据被构造为消息,其中每个消息都是信息的逻辑记录,其中包含一系列称为字段的名称/值对。这是一个简单的示例:

message Person {string name = 1;int32 id = 2;bool has_ponycopter = 3;
}

定义了数据结构后,就可以使用protocol buffer编译器protoc生成你所选语言的数据访问类。访问类为每个字段提供了简单的访问器(例如name())和set_name()),以及将整个结构序列化为原始字节或从原始字节中解析出整个结构的方法-例如,如果您选择的语言是C ++,则在上面的示例将生成一个名为Person的类。然后,您可以在应用程序中使用此类来填充,序列化和检索Person的protocol buffer消息。

除此之外你还要在.proto件中定义gRPC服务,并将RPC方法参数和返回类型指定为protocol buffer消息:

// The greeter service definition.
service Greeter {// Sends a greetingrpc 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 {string message = 1;
}

gRPC使用也是使用编译器protoc从proto文件生成代码,不过编译器要首先安装一个gRPC插件。使用gRPC插件,你可以获得生成的gRPC客户端和服务器代码,以及用于填充,序列化和检索消息类型的常规protocol buffer访问类代码。

下面会更详细地介绍gRPC里的一些关键的概念。


服务定义

与许多RPC系统一样,gRPC围绕定义服务的思想,指定可通过其参数和返回类型远程调用的方法。默认情况下,gRPC使用protocol buffer作为接口定义语言(IDL)来描述服务接口和有效负载消息的结构。如果需要,可以使用其他替代方法。

service HelloService {rpc SayHello (HelloRequest) returns (HelloResponse);
}message HelloRequest {string greeting = 1;
}message HelloResponse {string reply = 1;
}

gRPC允许定义四种服务方法:


  • 一元RPC,客户端向服务器发送单个请求并获得单个响应,就像普通函数调用一样。

rpc SayHello(HelloRequest) returns (HelloResponse){
}

  • 服务器流式RPC,客户端向服务器发送请求,并获取流以读取回一系列消息。客户端从返回的流中读取,直到没有更多消息为止。 gRPC保证单个RPC调用中的消息顺序。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}

  • 客户端流式RPC,客户端使用提供的流写入消息序列然后将它们发送到服务器。客户端写完消息后,它将等待服务器读取消息并返回响应。 gRPC保证了在单个RPC调用中的消息顺序。

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}

  • 双向流式RPC,双方都使用读写流发送一系列消息。这两个流是独立运行的,因此客户端和服务器可以按照自己喜欢的顺序进行读写:例如,服务器可以在写响应之前等待接收完所有客户端消息,或者可以先读取一条消息再写入一条消息,或其他一些读写组合。每个流中的消息顺序都会保留。

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}

在下面的RPC生命周期章节我们会更详细的比较这几种不同的RPC。


使用API界面

.proto文件中的服务定义开始,gRPC提供了protocol buffer编译器插件,插件可生成客户端和服务器端代码。 gRPC用户通常在客户端调用这些API,并在服务器端实现相应的API。


  • 在服务侧,服务器实现服务中声明的方法并运行一个gRPC服务器来处理客户端的调用。gRPC的基础设施解码传入的请求,执行服务的方法,编码服务的响应。
  • 在客户端,客户端拥有一个名为stub(存根)的本地对象(在有些语言中更倾向于把stub叫做客户端)该对象同样实现了服务中方法。客户端可以只在本地对象上调用这些方法,将调用参数包装在适当的protocol buffer消息类型中,gRPC会负责将请求发送给服务器并且返回服务端的protocol buffer响应。

同步vs异步

同步RPC调用会阻塞当前线程直到服务器收到响应为止,这是最接近RPC所追求的过程调用抽象的近似方法。另一方面,网络本质上是异步的,并且在许多情况下能够启动RPC而不阻塞当前线程很有用。

大多数语言中的gRPC编程界面都有同步和异步两种形式。可以在每种语言的教程和参考文档中找到更多信息。


RPC生命周期

现在让我们具体看一下当一个gRPC客户端调用了一个gRPC服务器的方法后都发生了什么。我们不会查看具体实现细节,留到后面的编程语言教程中再看实现细节。


一元RPC

首先来看一个最简单的RPC类型,客户端发送一个请求然后接受一个响应。


  • 一旦客户端调用了存根/客户端对象上的方法,服务器会被通知RPC已经被调用了,同样会接收到调用时客户端的元数据、调用的方法名称以及制定的截止时间(如果适用的话)。
  • 然后,服务器可以立即发送自己的初始元数据(必须在发送任何响应之前发送),也可以等待客户端的请求消息-哪个先发生应用程序指定的。
  • 服务器收到客户的请求消息后,它将完成创建和填充其响应所需的必要工作。然后将响应(如果成功)连同状态详细信息(状态代码和可选状态消息)以及可选尾随元数据一起返回。
  • 如果状态是OK,客户端将获得响应,从而在客户端完成并终结整个调用过程。

服务器流式RPC

一个服务器流式RPC与简单的一元RPC类似,不同的是服务器在接收到客户端的请求消息后会发回一个响应流。在发送回所有的响应后,服务器的状态详情(状态码和可选的状态信息)和可选的尾随元数据会被发回以完成服务端的工作。客户端在接收到所有的服务器响应后即完成操作。


客户端流式RPC

客户端流式RPC也类似于一元PRC,不同之处在于客户端向服务器发送请求流而不是单个请求。服务器通常在收到客户端的所有请求后(但不一定)发送单个响应,以及其状态详细信息和可选的尾随元数据。


双向流式RPC

在双向流式RPC中,调用再次由客户端调用方法发起,服务器接收客户端元数据,方法名称和期限。同样,服务器可以选择发回其初始元数据,或等待客户端开始发送请求。

接下来发生的情况取决于应用程序,因为客户端和服务器可以按任何顺序进行读取和写入-流操作完全是独立地运行。因此,例如,服务器可以等到收到所有客户端的消息后再写响应,或者服务器和客户端可以玩“乒乓”:服务器收到请求,然后发回响应,然后客户端发送基于响应的另一个请求,依此类推。


截止时间/超时时间

gRPC允许客户端指定在RPC被DEADLINE_EXCEEDED错误终结前愿意等待多长时间来让RPC完成工作。在服务器端,服务器可以查看一个特定的RPC是否超时或者还有多长时间剩余来完成RPC。

如何指定期限或超时的方式因语言而异-例如,并非所有语言都有默认期限,某些语言API按照期限(固定的时间点)工作,而某些语言API根据超时来工作(持续时间)。


RPC终止

在gRPC中,客户端和服务端对调用是否成功做出独立的基于本地的决定,而且两端的结论有可能不匹配。这意味着,比如说,你可能会有一个在服务端成功完成(“我已经发送完所有响应了”)但是在客户端失败(“响应是在我指定的deadline之后到达的”)的RPC。服务器也有可能在客户端发送所有请求之前决定RPC完成了。


取消RPC

客户端或服务器都可以随时取消RPC。取消操作将立即终止RPC,因此不再进行任何工作。这不是“撤消”:取消之前所做的更改不会回滚。


元数据

元数据是以键值对列表形式提供的关于特定RPC调用的信息(比如说身份验证详情),其中键是字符串,值通常来说是字符串(但是也可以是二进制数据)。元数据对gRPC本身是不透明的-它允许客户端向服务器提供与调用相关的信息,反之亦然。

对元数据的访问取决于语言。


通道

一个gRPC通道提供了一个到指定主机和端口号的gRPC服务器的连接,它在创建客户端存根(或者对某些语言来说就是“客户端”)时被使用。客户端可以指定通道参数来更改gRPC的默认行为,比如说打开/关闭消息压缩。每个通道都有状态,状态包括connectedidle(闲置)

gRPC怎么处理关掉的通道是语言相关的,有些语言还允许查询通道的状态。



WX20191117-152623@2x.png


推荐阅读
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 本文将介绍如何在混合开发(Hybrid)应用中实现Native与HTML5的交互,包括基本概念、学习目标以及具体的实现步骤。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • javax.mail.search.BodyTerm.matchPart()方法的使用及代码示例 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 本教程详细介绍了如何使用 Spring Boot 创建一个简单的 Hello World 应用程序。适合初学者快速上手。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
author-avatar
ThanksGiven
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有