读gRPC Microservices in Go第一章

读gRPC Microservices in Go第一章

微服务可用任何语言实现

Go 适用于构建高性能/云原生/分布式应用程序,如大规模Kubernetes中的微服务。使用gRPC通信的微服务使许多公司能基于其业务能力实现小型服务,让这些服务与彼此和公共服务顺畅通信。借助Go语言这些服务的分布变得更加容易,因为它具有快速编译能力,能生成可执行二进制

gRPC是开源远程过程调用框架,它帮助连接服务,内置了负载均衡、追踪、容错和安全支持。优势是为多种语言生成服务器和客户端存根(stubs)(即客户端上实现与服务相同方法的对象),存根在消费者项目中用于调用远程服务方法,在服务器项目中用于定义这些服务方法背后的业务逻辑

  • 服务器存根:服务器端存根是一种骨架代码,用于定义服务接口。开发者可在这个骨架基础上实现具体业务逻辑。如定义了一个服务方法getUser,gRPC会生成相应的存根,你只需填充这个方法的具体实现(如如何检索用户数据)
  • 客户端存根:客户端存根是一种代理对象,提供与服务器端定义的同样方法。客户端开发者可使用这些方法来调用远程服务,就像调用本地方法一样。如客户端上的getUser方法会通过网络与服务器上的同名方法通信

微服务是面向服务的架构形式,将应用程序定义为松散耦合、细粒度的服务,这些服务可独立实现、部署和扩展

借助gRPC微服务中的挑战,如处理网络故障和对服务通信应用TLS(传输层安全)都可以消除

总之就是gRPC提供了很多功能

gRPC比其他协议(如用JSON/XML通信的REST)提供更好性能安全,因为它使用协议缓冲区,且在TLS上的HTTP/2非常直接。

  • 协议缓冲区(Protobuf),是不论语言和平台的用于序列化结构化数据的机制。使gRPC能在服务器和客户端快速序列化成小巧紧凑的消息
  • HTTP/2通过服务器端推送、多路复用和头部压缩提高了性能

服务器端推送 (Server Push) 是HTTP/2的功能,允许服务器主动向客户端发送资源,不需客户端明确请求。这功能对提升页面加载速度尤其有用 当客户端请求页面时,服务器不仅发送请求的HTML文件,还可发送页面中将要用到的其他资源(如CSS文件、JavaScript文件、图像等) 服务器通过PUSH_PROMISE帧通知客户端它将发送哪些附加资源,这样客户端不会再次请求这些资源

多路复用 (Multiplexing) 是HTTP/2中的核心改进,允许在单一TCP连接上同时发送多个请求和响应 HTTP/2将请求和响应分解为更小的帧,并在一个TCP连接上同时交错发送这些帧 每个帧都属于特定的流(stream),流是独立请求或响应的标识 优势:

  • 减少由于TCP连接建立和拥塞控制引起的延迟
  • 允许同时加载页面多个部分,而不是按顺序加载

头部压缩 (Header Compression): HTTP/2通过HPACK算法压缩头部信息,减少传输数据量 HTTP/2使用静态和动态两种字典存储和传输常见的头部字段 静态字典包含常见的头部字段名和值,动态字典记录在通信过程中出现的头部字段 对于每个请求和响应,只传输字典中的索引和未出现过的新头部字段大大减少了传输头部大小

假设有结账服务和支付服务,允许客户结账购物篮后触发支付服务。要访问支付服务需在某处(如共享库)拥有请求和响应模型,以便轻松访问

请求和响应模型是指在客户端和服务器之间进行通信时所使用的数据结构或格式 微服务架构中服务间的交互通过网络进行。为简化这些服务间交互,常在共享库(shared library)中定义请求和响应模型。好处是实现了代码的复用和标准化,使不同的服务可更容易、更一致地通信

微服务中重用共享请求和响应模型看起来方便,但尤其是当您为每个微服务使用不同语言时,这不是好做法

  • 在结账服务中复制模型,通常是通过创建另一个数据类来构建请求对象和反序列化响应对象,是更好的选择。这是为了防止错误的抽象,正如“一点点重复远比错误的抽象便宜”
  • 简单方法:gRPC定义消息并生成客户端存根,这样就可直接在任何语言中注入依赖

共享库是特定语言编写的,可能限制其他服务使用不同语言时的兼容性。相反复制模型(即在每个服务中独立定义请求和响应模型)提供更大灵活性 共享库可能导致错误抽象,即一个服务的改变需修改共享库,进而影响到所有使用该库的服务。复制模型避免了这种紧密耦合,每个服务可独立演化而不影响其他服务 gRPC可定义统一的消息格式(Protocol Buffers),且gRPC自动生成各种语言的客户端和服务器端代码。每个服务可使用生成的代码构建请求对象和反序列化响应对象,无需手动编写通信代码 gRPC使用Protocol Buffers定义强类型接口,比JSON或XML等格式更严格清晰,减少解析错误和数据不一致的风险

gRPC越来越受欢迎。只需决定需要拥有什么样的业务对象。一旦选择结账模型需要的字段,可引入相应请求和响应消息。这些消息只是在IDL(接口定义语言)中的定义,与任何语言规范无关。定义了消息规范后,可生成特定语言实现,以便任何消费者都可依赖该来源。服务器端开发语言可与客户端不同,因为服务器端方法可为客户端特定语言生成存根

除业务对象还可类似定义服务方法并生成实现。初始化gRPC客户端后这些服务功能可在消费者端调用;这个客户端是开箱即用的

幂等性是成功容错环境的关键,因为需要确保一旦在失败或未达到预期状态的情况下重试操作时,使用相同参数不会改变实际资源内容。如希望在响应中出现网络故障时重试删除用户操作。如果操作即使多次调用也返回相同结果,称这个操作是幂等的

如果操作不适合幂等用例,则必须在响应消息中提供适当的验证错误,以知道何时停止重试操作。一旦保证了这种幂等性或适当的验证,那么在gRPC端定义重试策略就只是定义问题。容错还专注于速率限制、断路器和故障注入等主题

网络服务中,尤其是可能存在网络问题或其他故障情况下,客户端可能会重试不幂等操作,导致不期望的副作用(如重复扣费) 为解决问题,服务在响应消息中应提供适当验证错误。意味着当操作不应被重试时(如它已执行了),服务应返回明确的错误消息告诉客户端不要再重试操作 gRPC支持客户端和服务器端的重试策略,可配置这些策略来适应不同操作和故障情况

大多数系统可能需要安全层来保护产品免受未经验证来源的侵害。gRPC鼓励在SSL/TLS上使用HTTP/2来认证和加密客户端和服务器间交换的数据。可使用SSL/TLS、ALTS(应用层传输安全)或基于令牌的认证系统轻松设置该认证系统

有时可能需要将响应数据分成几块,以分页方式减少带宽并快速返回给用户。如果用户只对特定页面感兴趣,则同时返回所有数据没有意义

  • gRPC中除了分页,还可将这些数据流式传输给消费者,而不是强迫用户进行分页以迭代地获取数据。
  • 流式处理不一定要在服务器端进行;也可在客户端或同时在双方进行,称双向流式处理。典型的流式处理用例中,只打开一次连接,数据通过这个打开的连接进行流式传输

分页 (Pagination) 目的:当服务器有大量数据需发给客户端时,一次性发送所有数据可能导致带宽浪费和响应延迟。分页是常见解决方案,服务器将数据分成“页”,每页包含一定数据项。客户端首先请求第一页数据,如需更多数据,可继续请求后续页。这可减少单次请求的数据量,从而减轻服务器负载,加快响应时间 流式传输 (Streaming): 与传统请求/响应模型不同,流式传输允许数据在客户端和服务器间持续流动

  • 应用场景:流式传输适用于需要实时处理大量数据的场景,如视频播放、实时数据分析等
  • 优势在于只打开一次连接,数据可通过已打开连接持续传输,提高效率并减少连接开销

REST(表述性状态转移)是微服务广泛采用的协议。但如果有严格的要求,如低延迟、多语言系统支持等,可能会考虑gRPC

  • REST基于HTTP 1.0,在客户端和服务器间以JSON/XML格式交换消息
  • gRPC基于RPC架构,使用协议缓冲区的二进制格式在HTTP 2.0协议上交换数据
  • 并不意味着REST不兼容HTTP 2.0;可使用自定义实现基于该协议设置REST服务,以便它是gRPC中的内置功能

由于gRPC内置了HTTP 2.0支持,还可在客户端和服务器间使用一元和双向流式传输,从而实现高速通信。使用REST服务的默认设置,多个客户端-服务器通信可能导致整体系统性能的延迟

一些情况下REST比gRPC更有利。如REST协议在所有类型的浏览器中都支持。由于gRPC支持有限可能需使用代理层,如gRPC Web,以便轻松与gRPC服务器通信

gRPC有许多优势,如能定义消息以便于在服务间轻松交换数据

  • 可读性而言,REST的JSON/XML更好
  • 如果没有对更改字段的显式业务验证,则可自由更改请求。相比之下gRPC中进行更改时,需遵循规则

gRPC内置了客户端和服务器存根生成机制,REST中则需用如Swagger Codegen之类的框架来生成客户端模型。同时维护多个服务和多个客户SDK时尤其关键

对浏览器支持有严格要求需用REST,因为最终需要设置另一层来转换HTTP/2和HTTP/1。但仍可用gRPC进行服务间通信,并将gRPC负载均衡器连接到该服务池,以便公开API以兼容REST。其他替代方案包括Twirp,这是基于Protobuf的RPC框架。Twirp允许为gRPC服务启用REST层,使您能访问端点,如以下示例发送带有JSON有效负载的POST请求:

curl -X "POST"
-H "Content-Type: application/json"
-d '{"name": "dev-cluster"}'
 http://localhost:8080/twirp/github.com/huseyinbabal/microservices-proto/cluster/Create

多语言开发环境适合gRPC,因为结账服务中使用Python客户端访问使用Java编写的支付服务,通过客户端存根生成非常容易。可将相同的策略应用于公共消费者的SDK生成。此外,每当您更改服务定义时,客户端的测试都会失败,这是您微服务的合适验证机制。

对于只包含一到两个服务的简单应用程序,例如创业项目,gRPC可能不是合适的选择,因为维护包含服务定义的proto文件并不容易,尤其是对于没有经验的用户。

然而,将gRPC通信用于内部服务是可以接受的,但向客户公开gRPC接口可能不是理想的选择,尤其是如果没有用于gRPC服务通信的客户端SDK。如果您更喜欢公开gRPC而不维护消费者的SDK,那么最好与他们共享您的服务定义,或提供关于如何向您的gRPC服务发起gRPC调用的清晰说明。

微服务项目充满挑战,尤其是在项目开始时,您会经常在架构决策会议中听到以下问题:

  • 让我们实现微服务,但应该多微小?
  • 我们需要基于哪种策略来构建/分解服务?

可根据业务能力划分微服务,有五个服务提供不同业务功能,如Shipping服务将产品运送给客户,以及使用结账阶段的购物车信息向客户的信用卡收费的支付服务。有五个业务能力:产品、购物车、结账、支付和运输。使用生成的存根连接(如结账使用Shipping gRPC存根调用Shipping服务功能)

单体到微服务的分解将替换服务函数调用为网络调用,这意味着您需要实现一个容错的客户端来进行服务间通信。gRPC提供了基本的连接池和资源访问等功能,因此在将自动生成的存根添加到Consumer服务作为Go依赖后,可以使用它们的gRPC存根在客户端访问服务函数。如图1.1所示,结账服务可以调用购物车服务以获取购物车商品、运输服务以获取客户地址,以及支付服务以向客户的信用卡收费,方法是将分别生成的运输、购物车和支付服务的存根添加到结账服务作为Go依赖。我们将在第5章详细讨论依赖管理;您将学习如何处理依赖关系以及如何在CI(持续集成)管道中自动化它们。

微服务架构为多语言开发环境打开了大门,这对于选择不同用例的合适语言非常有帮助。它还允许使用各种技术,例如在需要关系表结构的情况下使用MySQL,或在需要文档型数据模型的情况下使用Mongo。微服务架构还可以帮助您构建不同的小团队,将代码所有权分配给特定的服务池。

管理应用程序环境可能不是真正的问题,如果您有一个单体应用程序,因为您可以将这个应用程序部署到一组虚拟机中,并且一个典型的负载均衡器可以处理流量。不充分的资源利用率、扩展问题和高风险的部署促使人们转向微服务架构。但是,一旦您做出了转换,因为每个服务都是独立的,您需要开始考虑需要适当管理的分布式环境。

Kubernetes是一个开源容器编排平台,已经证明了自己在应用程序部署管理和许多其他生产级用例中的有效性。图1.1中显示的服务都将是云原生应用程序,并将为CI/CD管道中的使用定义Kubernetes部署规范。此外,每个服务都将在容器中运行,并可以根据负载水平进行扩展。

gRPC需要一个服务器地址来拨入以调用服务功能。Kubernetes的发现系统非常适合找到正确的地址,因为服务器地址是在服务规范中定义的微服务的服务名称。假设您为您的服务有适当的命名约定。在这种情况下,您还可以在消费者和服务之间实现完美的集成,无需借助服务发现产品来查看特定服务的实际地址。

每个服务都可以有不同的行为,如资源请求、扩展因子、语言运行时等。同样,它们只是Kubernetes部署中的配置,可以针对每个服务进行适当配置。例如,假设产品服务由于大多数客户在白天搜索和查看产品而需要比其他服务更多的容量或扩展因子。您不需要像在单体应用程序中那样同时扩展Kubernetes中的所有服务。这可以通过向特定服务添加扩展因子和资源容量来处理。

每个服务的主要输出将是一个云原生应用程序,这意味着您可以将此服务部署到任何其他容器运行时,例如AWS Fargate、AWS ECS,甚至用于本地开发的Docker等,只需稍作修改。

在微服务环境中,有许多操作是自动化的候选对象。服务工件构建、特定语言的gRPC存根生成、测试、代码质量检查以及服务部署等都是一些众所周知的例子。您在这个分布式系统中拥有的自动化越多,在开发生命周期中的压力就越小。

您可以在本地环境中轻松使用gRPC工具生成存根,但是如果在向远程仓库推送一些更改时生成它们不是更好吗?在将它们合并到主分支后,您还可以生成工件以部署它们到实验环境或稳定环境。现代版本控制系统(VCS)提供商,如GitHub、GitLab和Bitbucket,已经具有这种集成,因此在这种自动化水平上不需要太多自定义实现。

CI/CD作业执行后的绿色勾号并不意味着一切都好;应该有一种方法来检查是否使用了正确的机制。良好的单元测试覆盖率;适当的集成测试来检查第三方集成,如MySQL、Kubernetes或AWS;服务间通信的合同测试;静态代码分析;和漏洞检查是在主分支中拥有可靠代码库的良好开端。

在成功且可靠的代码库之后,可以生成并标记工件,以便部署到用户验收测试(UAT)环境,然后是最终用户的生产环境。部署方法论的一些最佳实践包括滚动升级、金丝雀部署和蓝绿部署。部署的主要目标是将工件(在我们的案例中是Docker映像)运送到Kubernetes环境,并准备在需要时回滚。做出回滚操作的决定并不容易。然而,如果您有适当的监控系统,您可以追踪错误率和用户反馈来决定何时回滚或对当前版本引入紧急修复。

监控是一种机制,允许团队观察和理解他们系统的状态,而可观察性是一种使团队能够调试系统的机制。主要通过指标、日志和追踪实现可观察系统。追踪上下文对于查看任何特定请求的生命周期至关重要,我们将在第9章详细看到。假设一个消费者使用SDK通过API网关访问API。它将请求传播到四到五个下游服务以处理所有操作,然后返回给客户。成功的响应并不意味着一切都好;如果这个生命周期中存在延迟,那就不好。在检测到延迟之后,可以通过按痕迹ID分组来分析请求流,这些痕迹ID包含有用的信息。我们将在第9章详细看到,可以通过一个简单的中间件快速将痕迹ID注入到请求和响应头中。

监控是微服务架构的关键部分,因为一旦您将单体应用程序分解为微服务架构,您就必须引入解决方案以获得更好的可见性。服务级指标、总体延迟和服务间通话层次结构是您可能希望在监控仪表板上看到的一些解决方案。除了系统级指标外,服务的日志也很必要,因为它们允许您追踪应用程序级异常,例如错误率的增加。

为您的系统提供仪表板、面板和图表是更好可观察性的良好开端。然而,我们应该专注于引入新的指标,并基于这些工具创建特定的警报,以在您远离仪表板时通知您。例如,Prometheus(https://prometheus.io),一个开源事件监控和警报工具,可以用来收集系统和应用程序指标,并可以基于这些指标配置新的警报,例如“一旦特定服务的内存使用率> 80%,则通知”。日志也是洞察的良好来源,因为您可以实时计算错误率。您甚至可以在现代日志管理工具中根据日志模式创建警报配置,例如Elastic Stack(Elasticsearch、Logstash和其他Elastic集成产品)。

良好的监控设置可以提供对服务间通信和服务到第三方集成的洞察。例如,它将可以检测服务与数据库之间或服务与组织控制之外的第三方API之间的性能问题。

公共访问对于您的产品和您的业务声誉非常重要。例如,如果用户可以向您的产品发送无限制的请求,这是公共访问不良架构设计的标志,因为没有限制系统的产品会导致服务器端资源耗尽,对性能产生负面影响。

API网关被广泛用于通过遵循某些原则来防止这类情况,例如快速建立适当的认证/授权系统,引入速率限制以限制用户的请求容量等。如果您已经使用Kubernetes,您可以通过内置功能来处理这一点,例如向NGINX控制器添加授权和速率限制配置;否则,您还有其他选择,例如使用API网关产品。

资源命名也至关重要,因为它会影响产品文档的质量。如果为端点使用了适当的命名,阅读API文档和顺利使用这些API端点就更容易。您还可以选择为您的产品实现SDK,这样消费者就可以依赖该SDK功能,而不是尝试构建请求、发送到API端点并处理响应。

软件开发团队的根本目标是实现一系列功能,以形成产品并创造直接或间接的商业价值。这种产品可以作为一个包分发,可以离线安装在电脑上,或者是基于互联网的在线使用。每种编程语言都有自己的打包方法;例如,对于Java项目,你可以使用WAR或JAR文件,或者对于Go项目,使用二进制可执行文件。我们称之为单体架构:一个或多个功能/模块作为一个产品打包,完成相关任务,在一个可分发的对象中。当出现可扩展性问题时,像微服务架构这样的替代方案很受欢迎,因为应用程序根据它们的业务能力被分解成服务。这种分解使每个服务能够独立部署,我们将在第8章详细讨论。服务间通信的稳定性对于在服务间提供数据一致性至关重要


当出现可扩展性问题时,像微服务架构这样的替代解决方案就变得流行,因为应用程序根据它们的业务能力被分解成服务

如果你没有为单体应用monolithic测试用例提供适当的隔离,那么每次在代码库中进行小改动时,你可能需要运行所有测试。代码库越大,编译和测试的时间就越长

连续部署中的频繁部署,单体monolithic可能是一个障碍,因为它们在合理的时间间隔内难以部署和测试。即使你只对特定组件引入了一个小改变,你也需要部署整个应用程序。

通过将它们置于负载均衡器后面,可以快速扩展单体应用,这使得客户端请求可以代理到物理服务器中的下游单体应用或容器运行时。然而,从成本角度来看,这可能没有意义,因为这些应用是彼此的完全复制,即使你不需要以相同的优先级扩展所有组件

一旦你决定使用单体架构,你就长期承诺了技术栈。单体应用中的层在进程内调用中紧密耦合,使用相同的技术开发以实现互操作性。

X-axis scale包括在负载均衡器后运行同一应用程序的多个副本。在Kubernetes中,负载平衡由服务资源处理(http://mng.bz/x4Me),它们将请求代理到位于Pod资源中的可用后端实例(https://kubernetes.io/docs/concepts/workloads/pods/),我们将在第8章详细介绍。这些实例共享负载,所以如果有N个副本,每个实例可以处理1/N的负载。这种缩放模型的一些主要缺点是,由于每个复制的实例都可以访问所有数据,实例需要比所需更多的内存,而且减少代码库增长的复杂性没有优势。

Y-axis scale中,缩放意味着按功能而不是多个副本来拆分应用程序。例如,你可能会将你的应用程序分解为一组具有几个相关功能的服务。现在我们了解了单体架构和可扩展性模型的优缺点,让我们看看微服务架构是Y轴缩放的一种形式。

在单体架构中,数据一致性通常由事务确保。事务是一系列应该成功完成的操作;如果即使一个操作失败,所有操作都会自动回滚。为了拥有一致的数据,事务首先开始,执行实际的业务逻辑,然后在成功的情况下提交事务,在失败的情况下回滚事务

saga patern

一旦你切换到微服务架构,数据状态就会分布在多个服务之间。每个服务都有自己的数据存储,这意味着单个事务无法处理数据的一致性。为了在分布式系统中拥有数据一致性,你有两个选择:两阶段提交(2PC)和saga。2PC协调构成分布式原子事务的所有过程,并决定它们是提交还是中止。saga是一系列本地事务的顺序,它更新每个服务并发布另一个消息以触发下一个服务上的另一个本地事务。

基于编排和基于协同工作的萨加是服务间通信的最流行模式,以拥有一致的数据。

基于协同工作的萨加: 每当创建一个萨加时,它可以按照以下模式完成:

  • 一旦萨加完成,服务将结果返回给客户端。它接收一个事件来更新其领域对象的状态为成功或失败。
  • 创建一个萨加,客户端开始轮询下一个服务以获得成功或失败的响应。创建萨加时直接返回的唯一标识符应该用于开始轮询。
  • 创建一个萨加,客户端使用WebSocket连接,其中服务使用WebSocket协议将结果发送回去。一旦返回成功或失败的结果,萨加将完成。

典型的订单创建流程中,订单服务中创建一个萨加,并且订单以待处理状态创建。订单持久化后立即发送一个名为order_created的事件,并被支付服务消费,该服务将尝试向客户收费并发送另一个事件:payment_created或payment_failed。如果失败,订单服务将被通知,订单将标记为失败。如果成功,物流服务将消费事件并启动物流过程。最后,它将为失败或成功创建另一个事件,这将导致订单状态被标记为失败或成功

通过队列的服务通信可以以两种方式处理:

  • 命令通道(command channel)——发布者直接向下一个服务发送消息,并带有replyToChannel参数,以便在完成操作并提交事务后通知消费者。这种模式的主要缺点是发布者需要知道下一个服务的位置。
  • 发布/订阅机制(Pub/Sub mechanism)——发布者发布一个领域事件,感兴趣的消费者可以消费消息以处理和提交本地事务。这种表示法的主要缺点是它可能是单点故障,因为所有订阅者使用一个代理技术,所有事件都发送给消费者。

让我们看看如何使用命令通道符号:需要在事件中额外信息以决定下一步要做什么的异步通信。除了构成实际数据的字段外,还注入了一个特定字段,称为replyTo通道,以便消费者服务可以将结果发送回该通道。为这些事件添加一些关联ID也是最佳实践,以查看特定一系列事件的整体情况

这种通信类型在另一种微服务通信模式中广泛使用,称为基于编排的萨加

让我们重新设计订单服务的创建流程,使用基于编排的萨加模式创建订单萨加。基于编排的萨加由编排器和参与者组成,编排器告诉参与者要做什么。编排器可以使用命令通道或请求/响应风格与参与者通信。它分别连接参与者,告诉他们执行他们的本地事务,并根据此响应决定下一步。

每当你向订单服务发送创建订单请求时,它会启动一个负责运行一系列步骤以完成操作的萨加。当它调用支付服务为特定订单向客户收费时,它可以返回成功或失败。如果成功,创建订单萨加继续下一步,在我们的案例中是物流。如果在支付服务中失败,萨加运行补偿事务以撤销操作,这一步是退款。如果创建订单萨加成功运行了所有步骤,订单状态将保存为成功。记住,如果萨加在任何特定步骤失败,它会从下到上运行补偿事务。例如,如果它在物流中失败,它将执行Payment:refund()和Order:cancel(),比如订单创建的回滚操作

服务发现是一种操作,其中管理服务位置并向外暴露,以便每个服务找到下一个服务以执行步骤。服务发现有两种类型:

  • 客户端服务发现——在这种表示法中,服务发现工具允许应用程序在启动时报告它们的位置,如图2.6所示。客户端应用程序直接连接到服务注册表,并通过提供一些标准(如服务名称或唯一标识符)查询特定服务的位置。
  • 服务端服务发现——负载均衡器与服务注册表集成以解析下游服务。客户端应用程序通过负载均衡器而不是使用服务注册表来解析确切位置连接到服务,如图2.7所示。

除了这两种发现机制外,如Kubernetes这样的容器编排平台内置了服务发现机制,允许你通过其名称访问任何服务,我们将在第8章详细介绍。现在我们了解了服务发现,它使服务能够相互通信,让我们看看gRPC是如何发挥作用的。

gRPC是由Google推出的现代轻量级通信协议和高性能RPC框架。它可以高效地连接微服务环境中的服务,内置支持负载均衡、跟踪、健康检查和认证。gRPC使用协议缓冲区提供易于使用和高效的通信,这是一种用于序列化结构化数据的开源机制。让我们考虑使用gRPC和协议缓冲区使服务相互通信(即交换消息)的最小步骤集,使用自动生成的Golang源代码。