我是靠谱客的博主 强健月亮,最近开发中收集的这篇文章主要介绍使用gRPC构建实际的微服务,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

早期的微服务实现利用了代表性状态传输(REST)架构作为事实上的通信技术。然而,充分利用REST的服务常常适用于面向外部的服务,这些服务直接暴露给消费者。由于它们基于传统的基于文本的消息传递(JSON、XML和CVS over HTTP等)――针对人类进行了优化,因此这些不是内部服务间通信的理想选择。

相反,使用一种基于文本的消息传递协议,我们可以利用针对服务间通信进行优化的二进制协议。云原生计算基金会的gRPC(一种高性能的开源通用远程过程调用框架)是服务间通信的理想选择,因为它使用协议缓冲区(protocol buffer)作为服务间通信的二进制数据交换格式。

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

我们在本文中将更深入地介绍为什么gRPC是构建微服务间通信的一种出色选择。

gRPC的基础知识

有了gRPC,客户可以对不同机器上的服务器应用程序直接调用方法,好像该机器就是本地对象。gRPC立足于传统的远程过程调用(RPC)技术的基础,但是实施在现代技术堆栈(比如HTTP2和协议缓冲区等)上,确保最大的互操作性。

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

图1表明了gRPC的使用,在线零售应用程序作为库存和产品搜索服务的一部分。 Inventory服务的合约使用gRPC IDL来定义,该IDL在inventory.proto文件中已有指定。因此,Inventory服务的开发人员应先使用该服务来定义所有业务功能,然后利用proto文件生成服务端框架代码。与之相仿,可以使用同样的proto文件生成客户端代码(存根,stub)。

图1

由于gRPC与编程语言无关,你可以使用异构语言来构建服务和客户端。在这个例子中,我们使用Ballerina(ballerina.io)生成了Inventory服务代码,使用Java生成了客户端代码。你可以使用GitHub上的这个源代码(https://github.com/kasun04/grpc-microservices)来试试该示例。

库存(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:ServiceConfig service 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
} }
复制代码

至于客户端,再次用Inventory服务的gRPC服务定义来生成产品搜索服务,这是一个Java(Spring Boot)服务。你可以使用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库使用协议缓冲区,并编组(marshal)远程过程调用,该调用随后通过HTTP2来发送。在服务器端,请求解组(un-marshalled),使用协议缓冲区执行相应的过程调用。响应遵循从服务器到客户端的类似的执行流程。

使用gRPC开发服务和客户端的主要优点是,你的服务代码或客户端代码不需要为解析JSON或类似的基于文本的消息格式(在代码内或隐含在Jackson等底层库中,对服务代码而言隐藏起来)操心。二进制格式解组、转换成对象。此外,我们要处理多个微服务并确保和维护互操作性时,对通过IDL定义服务接口给予一流支持是强大的功能。

用gRPC构建微服务的实例

基于微服务的应用程序由多个服务组成,并使用众多编程语言构建。基于业务使用场景,你可以选择最合适的技术来构建服务。gRPC在这种多语言架构中起到非常重要的作用。如图2所示,产品搜索服务与另外多个服务进行通信,这些服务是使用gRPC作为通信协议构建的。因此,我们可以为每个服务定义服务合约:库存、电子品类和服装品类等。现在,如果你想要打造一种多语言架构,可以使用不同的实现技术来生成服务框架。

图2显示了用Ballerina lang编写的库存服务、用Golang编写的电子服务和用Vert.x(Java)编写的服装服务。客户端还可以为这每个服务合约生成存根。

图2

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

因此作为一般实践,我们可以将gRPC用于内部微服务之间的所有同步通信。其他同步消息传递技术(比如充分利用REST的服务和GraphQL)更适合面向外部的服务。

感兴趣的可以自己来我的Java架构群,可以获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同学,欢迎加群,一起学习,相互讨论。



转载于:https://juejin.im/post/5c4819cde51d453ba8103eb6

最后

以上就是强健月亮为你收集整理的使用gRPC构建实际的微服务的全部内容,希望文章能够帮你解决使用gRPC构建实际的微服务所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部