写点什么

使用 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:448367
用户头像

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

关注

评论 4 条评论

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

京东云与中兴新支点国产操作系统完成产品兼容性互认证

京东科技开发者

Promise规范与原理解析

京东科技开发者

Vue3设计思想及响应式源码剖析

京东科技开发者

智慧园区维护平台(源码+文档+部署+讲解)

深圳亥时科技

uniapp 极速上手鸿蒙开发

万少

uni-app 鸿蒙

跨越平台界限:探索Native AOT的交叉编译技术

代码忍者

毕节正规等保测评机构有吗?在哪里?

行云管家

等保 堡垒机 网龄安全 毕节

运营商的网络运营成本管理

鲸品堂

网络 电信运营商 企业号 2024年12月PK榜

【免费大屏】积木BI大屏与老版的积木大屏对比有哪些优势?

JEECG低代码

数据分析 数据可视化 数据大屏 大屏设计器

2025全球计算大会:集齐计算产业 “王牌”,见证全球计算联盟正式启航

新消费日报

零售行业三问答看这里!

行云管家

网络安全 零售 堡垒机 零售行业

通过阿里云 Milvus 与 PAI 搭建高效的检索增强对话系统

阿里云大数据AI技术

大数据 阿里云 向量检索 Milvus PAI

未来社会中的AI:人机共生的愿景与路径

天津汇柏科技有限公司

AI 人工智能 人机交互

降本50%以上,Zilliz助力豆神打造因材施教的AI教育平台

Zilliz

向量数据库 zilliz cloud 豆神教育

票务管理系统(源码+文档+部署+讲解)

深圳亥时科技

Calcite UDF 实战之 ShardingSphere 联邦查询适配 MySQL BIT_COUNT

端小强

ShardingSphere Calcite

【HarmonyOS NEXT】ArkTs 模块的导出和引入

冉冉同学

鸿蒙 HarmonyOS OpenHarmony HarmonyOS NEXT

RAG开发中,如何用Milvus 2.5 BM25算法实现混合搜索

Zilliz

Milvus rag 混合检索 BM25

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