开工福利|免费学 2200+ 精品线上课,企业成员人人可得! 了解详情
写点什么

使用 gRPC 构建真实世界的微服务

  • 2018-12-06
  • 本文字数:2850 字

    阅读完需:约 9 分钟

使用gRPC构建真实世界的微服务

早期的微服务实现主要使用 REST 架构作为事实上的通信技术。通常,RESTful 服务对于面向外部的服务会很有用,这些服务直接暴露给消费者。它们是基于传统的文本消息传递(JSON、XML、基于 HTTP 的 CVS 等),但这些消息主要是面向人类的,并不是服务间通信的理想选择。


除了使用基于文本的消息传递协议,我们还可以使用针对服务间通信而优化的二进制协议。云原生计算基金会(CNCF)的 gRPC(gRPC 远程过程调用)就是服务间通信的一个理想选择,因为它使用 protobuf 作为服务间通信的二进制数据交换格式。


当我们使用不同的技术和编程语言构建多个微服务时,需要有一个标准的方法来定义服务接口和底层消息交换格式。gRPC 提供了一种简洁而强大的使用 protobuf 来定义服务合约的方法。因此,gRPC 可能是构建内部微服务间通信最可行的解决方案。


在本文中,我们将仔细探究为什么 gRPC 是构建微服务间通信的绝佳选择。

gRPC 基础

在使用 gRPC 时,客户端可以直接调用不同机器上的服务器应用程序,就好像是在调用本地对象一样。gRPC 以传统的远程过程调用(RPC)技术为基础,但是在现代技术栈(如 HTTP2、protobuf 等)之上实现的,以确保能够提供最大的互操作性。


gRPC 本身支持使用 gRPC 接口定义语言(IDL)来定义服务合约。因此,作为服务定义的一部分,你可以指定可远程调用的方法以及参数和返回类型的数据结构。


下图画出了 gRPC 与在线零售应用程序中的应用,这个应用程序是库存和产品搜索服务的一部分。库存服务的合约是使用 gRPC IDL 定义的,在 inventory.proto 文件中指定。库存服务的开发人员首先定义好所有的业务功能,然后根据 proto 文件生成服务端框架代码。类似地,可以使用相同的 proto 文件生成客户端存根代码。



由于 gRPC 与编程语言无关,你可以使用异构语言来构建服务和客户端。在这个例子中,我们使用 Ballerina(ballerina.io)生成服务端代码,使用 Java 生成客户端代码。你可以参考 GitHub 上的源代码示例


库存(inventory.proto)的服务合约如下所示:


syntax = "proto3";package grpc_service;import "google/protobuf/wrappers.proto";service InventoryService {   rpc getItemByName(google.protobuf.StringValue) returns (Items);   rpc getItemByID(google.protobuf.StringValue) returns (Item);   rpc addItem(Item) returns (google.protobuf.BoolValue);}
message Items { string itemDesc = 1; repeated Item items = 2;}
message Item { string id = 1; string name = 2; string description = 3;}

复制代码


服务合约易于理解,可以在客户端和服务之间共享。如果服务合约发生任何更改,则必须重新生成服务和客户端代码。


例如,下面是为 Ballerina 生成的 gRPC 服务代码。对于在 gRPC 服务中定义的每个操作,都会生成相应的 Ballerina 代码。(Ballerina 提供了开箱即用的功能来生成服务或客户端代码,“ballerina grpc –input inventory.proto –output service-skeleton –mode service”或“ballerina grpc –input inventory.proto –output bal-client –mode client”)。


import ballerina/grpc;import ballerina/io;endpoint grpc:Listener listener {   host:"localhost",   port:9000};
@grpc:ServiceConfigservice InventoryService bind listener { getItemByName(endpoint caller, string value) { // Implementation goes here. // You should return a Items }
getItemByID(endpoint caller, string value) { // Creating a dummy inventory item Item requested_item; requested_item.id = value; requested_item.name = "Sample Item " + value ; requested_item.description = "Sample Item Desc for " + value; _ = caller->send(requested_item); _ = caller->complete(); }
addItem(endpoint caller, Item value) { // Implementation goes here. // You should return a boolean }
}

复制代码


同样,从库存服务的 gRPC 服务定义生成产品搜索服务客户端(一个 Spring Boot Java 服务)。你可以使用 maven 插件为 Spring Boot/Java 服务生成客户端存根(客户端代码嵌在 Spring Boot 服务中)。调用生成的客户端存根的代码如下所示。


package mfe.ch03.grpc;import com.google.protobuf.StringValue;import io.grpc.ManagedChannel;import io.grpc.ManagedChannelBuilder;
public class InventoryClient { public static void main(String[] args) { ManagedChannel channel = ManagedChannelBuilder.forAddress("127.0.0.1", 9000) .usePlaintext() .build(); InventoryServiceGrpc.InventoryServiceBlockingStub stub = InventoryServiceGrpc.newBlockingStub(channel); Inventory.Item item = stub.getItemByID(
StringValue.newBuilder().setValue("123").build()); System.out.println("Response : " + item.getDescription()); }}

复制代码

底层通信

当客户端调用服务时,客户端 gRPC 库使用 protobuf 封装远程过程调用,然后通过 HTTP2 发送出去。在服务器端,请求被解封,并且通过 protobuf 执行相应的过程调用。响应遵循类似的流程,从服务器端发送到客户端。


gRPC 的主要优点是你的服务代码或客户端代码不需要去解析 JSON 或其他基于文本的消息格式。网络上传输的内​​容是二进制格式,会被组装成对象。此外,当我们需要处理多个微服务并确保和维护互操作性时,通过 IDL 定义服务接口是一个强大的功能。

一个使用 gRPC 的微服务用例

基于微服务的应用程序由多种服务组成,并使用了多种编程语言。你可以根据业务用例选择最合适的技术来构建你的服务。gRPC 在这种多语言架构中起着非常重要的作用。我们将进一步扩展之前的在线零售用例。如下图所示,产品搜索服务与多个其他服务通信,这些服务使用 gRPC 作为通信协议。因此,我们可以为每个服务定义服务合约:库存、电子产品、服装等。现在,如果你想要使用多语言架构,可以使用不同的实现技术来生成服务框架代码。


下图显示了使用 Ballerina 的库存服务、使用 Go 语言的电子服务和使用 Vert.x(Java)的服装服务。客户端也可以为每个服务合约生成存根。



仔细看一下上图中的微服务通信风格,可以看出,gRPC 被用在所有的内部通信上,而面向外部的通信主要基于 REST 或 GraphQL。当我们使用 REST 进行面向外部的通信时,大多数外部客户端可以将服务作为 API(可以利用 API 定义技术,如 Open API),因为大多数外部客户端都知道如何与 HTTP RESTful 服务通信。此外,我们可以使用诸如 GraphQL 之类的技术让消费者根据特定的客户需求来查询服务,这是 gRPC 无法提供的。


因此,作为一般实践,我们可以使用 gRPC 进行内部微服务之间的同步通信,而其他同步消息传递技术(如 RESTful 服务和 GraphQL)更适合面向外部的服务。

英文原文

https://thenewstack.io/build-real-world-microservices-with-grpc


2018-12-06 10:448067
用户头像

发布了 731 篇内容, 共 456.1 次阅读, 收获喜欢 2003 次。

关注

评论 4 条评论

发布
用户头像
例子的操作步骤不够详细
2018-12-09 10:32
回复
用户头像
2018-12-07 16:46
回复
没有更多了
发现更多内容

ClassIn:如何打造更稳定的Zabbix监控系统

OceanBase 数据库

oceanbase 数据库·

Flink 批作业的运行时自适应执行管控

Apache Flink

大数据 flink 实时计算

2023-01-10:智能机器人要坐专用电梯把货物送到指定地点, 整栋楼只有一部电梯,并且由于容量限制智能机器人只能放下一件货物, 给定K个货物,每个货物都有所在楼层(from)和目的楼层(to),

福大大架构师每日一题

算法 rust Solidity 福大大

盘点微服务架构下的诸多身份验证方式

API7.ai 技术团队

微服务 身份认证 APISIX

数据治理:数据质量管理策略!

用友BIP

为什么开发者这么看重SQL?看完这些应用场景你就明白了

雨果

sql 数据库管理工具 SQL开发工具

大数据就业培训班哪家好?

小谷哥

架构实战营4.1 数据库存储架构随堂练习

西山薄凉

「架构实战营」

马斯克收购推特后,亲自与员工探讨了……

博文视点Broadview

APISIX+Dubbo+Nacos 最佳实践

阿里巴巴中间件

阿里云 云原生 dubbo nacos APISIX

2022 OceanBase 年度报告|用技术让海量数据的管理和使用更简单!

OceanBase 数据库

数据库 oceanbase

LogicFlow自定义业务节点

小鑫同学

前端 vite Vue 3

《PyTorch 深度学习实战》学习笔记 --NumPy(上)

IT蜗壳-Tango

阿里P9耗时28天,总结历年亿级活动高并发系统设计手册

架构师之道

Java 高并发 架构师

阿里云连续3年跻身Gartner全球云数据库管理系统领导者象限

云布道师

阿里云

NFTScan:优质 NFT 应具备什么?

NFT Research

区块链 NFT

JDK结构介绍

Steven

先行试点,创新改造:中信期货关键业务系统自主可控的实践之路

OceanBase 数据库

高并发中的atomic

Steven

走进AI图像生成核心技术 - Diffusion

Baihai IDP

人工智能 AI AIGC Diffusion 扩散模型

钉钉 IM 基于 RocketMQ 5.0 的云原生应用实践

阿里巴巴中间件

阿里云 RocketMQ 云原生

Java高手速成 | 新增类Record的工作实例

TiAmo

新特性 Java’

先行“蜀道”, 四川农信核心系统分布式转型

OceanBase 数据库

如何用「标准差」度量研发波动

feijieppm

项目管理 研发效能 技术管理 文化 & 方法 效能度量

龙湖千丁基于 ACK@Edge 的云原生智慧停车系统架构实践

阿里巴巴中间件

阿里云 云原生

神经网络基础部件-损失函数详解

嵌入式视觉

激活函数 Relu sigmoid tanh swish激活函数

SeekBar(拖动条)

芯动大师

android SeekBar 拖动条

Dubbo-kubernetes 基于 Informer 服务发现优化之路

阿里巴巴中间件

阿里云 Kubernetes 云原生 dubbo

每个Java程序员都必须知道的四种负载均衡算法

JAVA旭阳

Java 架构 后端

安信证券资管清算重要业务在原生分布式数据库的创新实践

OceanBase 数据库

数据库 oceanbase

DiT:Transformers 与扩散模型强强联手

Zilliz

AI 算法模型

使用gRPC构建真实世界的微服务_语言 & 开发_Kasun Indrasiri_InfoQ精选文章