作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Laszlo Gyori的头像

Laszlo Gyori

Laszlo是一名解决方案架构师, software developer, 也是微服务架构方面的专家, gRPC, and REST. 他拥有布达佩斯理工学院信息技术硕士学位.

Expertise

Previously At

塔塔咨询服务
Share

在当今的技术环境中,大多数项目都需要使用api. api桥接可能代表单个服务的服务之间的通信, 复杂的系统,但也可以驻留在单独的机器或使用多个, 不兼容的网络或语言.

许多标准技术解决了分布式系统的服务间通信需求, such as REST, SOAP, GraphQL, or gRPC. 而REST是一种受欢迎的方法, gRPC是一个有价值的竞争者, 提供高性能, typed contracts, 和优秀的工具.

REST Overview

具象状态传输(Representational state transfer, REST)是检索或操作服务数据的一种方法. REST API通常构建在HTTP协议上, 使用URI来选择资源和HTTP谓词(例如.g.(GET、PUT、POST)来选择所需的操作. 请求和响应主体包含特定于操作的数据, 而它们的头文件提供元数据. 为了说明这一点,让我们看一个通过REST API检索产品的简化示例.

在这里,我们请求ID为的产品资源 11 并指示API以JSON格式响应:

GET /products/11 HTTP/.1
接受:application / json

给定这个请求,我们的响应(省略不相关的头)可能看起来像:

HTTP/1.1 200 OK
内容类型:application / json

{id: 11,名称:"Purple Bowtie", sku: "purbow",价格:{金额:100,currencyCode: "USD"}}

虽然JSON可能是人类可读的,但在服务之间使用它并不是最佳的. 引用属性名称的重复性质(即使是经过压缩的)可能导致消息臃肿. 让我们看看解决这个问题的另一种方法.

gRPC Overview

gRPC (Remote Procedure Call)是一个开源软件, contract-based, 跨平台通信协议,通过向外部客户端公开一组功能来简化和管理服务间通信.

建立在HTTP/2之上, gRPC利用了双向流和内置传输层安全性(TLS)等特性。. gRPC通过序列化的二进制有效负载实现更有效的通信. It uses protocol buffers 默认情况下作为结构化数据序列化的机制,类似于REST对JSON的使用.

然而,与JSON不同的是,协议缓冲区不仅仅是一种序列化格式. 它们还包括三个主要部分:

  • 中的契约定义语言 .proto 我们将遵循proto3,这是最新的协议缓冲区语言规范.)
  • 生成访问器函数代码
  • 特定于语言的运行时库

服务上可用的远程功能(定义在 .proto 文件)在协议缓冲文件的服务节点内列出. As developers, 我们可以使用协议缓冲区的丰富类型系统来定义这些函数及其参数. 该系统支持各种数字和日期类型, lists, dictionaries, 和空值来定义输入和输出消息.

这些服务定义需要对服务器和客户机都可用. Unfortunately, 控件的直接访问之外,没有默认机制来共享这些定义 .proto file itself.

This example .proto file定义了一个函数来返回给定ID的产品条目:

syntax = "proto3";

package product;

服务产品目录{
    rpc GetProductDetails (ProductDetailsRequest)返回(ProductDetailsReply);
}

消息ProductDetailsRequest {
    int32 id = 1;
}

消息ProductDetailsReply {
    int32 id = 1;
    string name = 2;
    string sku = 3;
    Price price = 4;
}

message Price {
    float amount = 1;
    字符串currencyCode = 2;
}
Snippet 1: ProductCatalog Service Definition

proto3严格的类型和字段排序使得消息反序列化比解析JSON要轻松得多.

Comparing REST vs. gRPC

总结一下,比较REST和. gRPC are:

 RESTgRPC
Cross-platformYesYes
Message Format自定义,但通常是JSON或XMLProtocol buffers
消息有效负载大小Medium/LargeSmall
处理的复杂性高级(文本解析)较低(定义良好的二元结构)
Browser SupportYes (native)Yes (via gRPC-Web)

在哪里期望不那么严格的合同和频繁的负载添加, JSON和REST非常适合. 当合同趋向于保持静态,速度是最重要的, gRPC通常胜出. 在我参与的大多数项目中,gRPC被证明比REST更轻,性能更高.

gRPC服务实现

让我们构建一个简化的项目来探索采用gRPC是多么简单.

创建API项目

首先,我们将创建一个 .Visual Studio 2022 Community Edition (VS)中的。NET 6项目. We will select the ASP.. NET核心gRPC服务 模板和命名我们将使用的项目 InventoryAPI) 这是第一个解 (Inventory).

Visual Studio 2022中的“Configure your new project”对话框. 在这个屏幕中,我们在项目名称字段中输入“InventoryAPI”, 我们在Location字段中选择了“C:\MyInventoryService”, 并在解决方案名称字段中键入“Inventory”. 我们没有选中“将解决方案和项目放在同一目录中”.

现在,我们来选择 .NET 6.0(长期支持) 我们框架的选项:

Visual Studio 2022中的附加信息对话框. 在这个屏幕中,我们选择了.NET 6.0(长期支持)”,从框架下拉菜单中选择. 我们没有选中“启用Docker”.

定义我们的产品服务

现在我们已经创建了项目,VS显示了一个示例gRPC原型定义服务 Greeter. We will repurpose Greeter的核心文件,以满足我们的需要.

  • 为了创建我们的合同,我们将替换 greet.proto with Snippet 1, renaming the file product.proto.
  • 的内容来创建我们的服务 GreeterService.cs 文件与代码片段2,重命名该文件 ProductCatalogService.cs.
using Grpc.Core;
using Product;

名称空间InventoryAPI.Services
{
    公共类ProductCatalogService: ProductCatalog.ProductCatalogBase
    {
        public override Task GetProductDetails(
            ProductDetailsRequest请求,ServerCallContext上下文)
        {
            return Task.FromResult(新ProductDetailsReply
            {
                Id = request.Id,
                名称=“紫色领结”,
                Sku = "purbow",
                Price = new Price
                {
                    Amount = 100,
                    CurrencyCode = "USD"
                }
            });
        }
    }
}
Snippet 2: ProductCatalogService

服务现在返回一个硬编码的产品. 要使服务工作,我们只需要更改服务注册 Program.cs 引用新的服务名称. 在本例中,我们将重命名 app.MapGrpcService(); to app.MapGrpcService(); 使我们的新API可运行.

公平警告:不是你的标准协议测试

虽然我们可能会尝试, 我们不能通过针对其端点的浏览器测试我们的gRPC服务. 如果我们尝试这样做, 我们将收到一条错误消息,指示必须通过gRPC客户端与gRPC端点进行通信.

Creating the Client

To test our service, 让我们使用VS的基本控制台应用模板并创建一个gRPC客户端来调用API. I named mine InventoryApp.

为了方便起见,让我们引用一个相对文件路径,我们将通过它来共享我们的契约. 我们将手动将引用添加到 .csproj file. 然后,我们将更新路径和设置 Client mode. 注意:我建议您在使用相对引用之前熟悉并对本地文件夹结构有信心.

Here are the .proto 引用,因为它们同时出现在服务和客户端项目文件中:

服务项目文件
(要复制到客户端项目文件的代码)
Client Project File
(粘贴编辑后)
  
    
  
  
    
  

现在,要调用我们的服务,我们将替换 Program.cs. 我们的代码将实现以下几个目标:

  1. 创建一个表示服务端点位置的通道(端口可能不同), so consult the launchsettings.json 文件中的实际值).
  2. 创建客户端对象.
  3. 构造一个简单的请求.
  4. Send the request.
using System.Text.Json;
using Grpc.Net.Client;
using Product;

var channel = GrpcChannel.ForAddress (http://localhost: 7200);
var client = new ProductCatalog.ProductCatalogClient(渠道);

var request = new ProductDetailsRequest
{
    Id = 1
};

Var response =等待客户端.GetProductDetailsAsync(请求);

Console.WriteLine (JsonSerializer.Serialize(response), new JsonSerializerOptions
{
    writeindentation = true
}));
Console.ReadKey();
Snippet 3: New Program.cs

准备发射

为了测试我们的代码,在VS中,我们将右键单击解决方案并选择 设置启动项目. 在解决方案属性页对话框中,我们将:

  • 选择旁边的单选按钮 多个启动项目,并在Action下拉菜单中设置这两个项目 (InventoryAPI and InventoryApp) to Start.
  • Click OK.

现在我们可以通过单击启动解决方案 Start 在VS工具栏中(或按 F5 key). 将显示两个新的控制台窗口:一个告诉我们服务正在侦听, 另一个显示检索到的产品的详细信息.

gRPC合同共享

现在让我们使用另一种方法将gRPC客户机连接到我们的服务定义. 客户端最容易访问的契约共享解决方案是通过URL提供我们的定义. 其他选项要么非常脆弱(通过路径共享文件),要么需要更多的努力(通过本机包共享契约)。. 通过URL共享(如SOAP和Swagger/OpenAPI所做的)是灵活的,并且需要更少的代码.

To get started, make the .proto 文件作为静态内容可用. 我们将手动更新代码,因为构建操作上的UI设置为“Protobuf Compiler”.,此更改指示编译器复制 .proto 文件,以便可以从web地址提供服务. 如果通过VS UI改变了这个设置,构建就会中断. 那么,我们的第一步是将代码片段4添加到 InventoryAPI.csproj file:

  
    
      Always
    
  

  
    
  
代码片段4:添加到 InventoryAPI 服务项目文件

的顶部插入代码片段5中的代码 ProductCatalogService.cs 文件设置一个端点以返回我们的 .proto file:

using System.Net.Mime;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
Snippet 5: Namespace Imports

现在,我们在前面添加代码片段6 app.Run(), also in the ProductCatalogService.cs file:

var provider = new FileExtensionContentTypeProvider();
provider.Mappings.Clear();
provider.Mappings[".proto"] = mediatypnames.Text.Plain;
app.UseStaticFiles(新StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(路径.Combine(app.Environment.ContentRootPath,“原型”)),
    RequestPath = "/proto",
    ContentTypeProvider = provider
});

app.UseRouting();
代码片段6:要生成的代码 .proto 可通过API访问的文件

添加了片段4-6后, .proto 文件应该在浏览器中可见.

A New Test Client

现在我们想要创建一个新的控制台客户端,我们将使用VS的依赖向导连接到我们现有的服务器. 问题是这个向导不支持HTTP/2. 因此,我们需要调整服务器以通过HTTP/1进行通信并启动服务器. 我们的服务器现在正在制作它 .proto 我们可以构建一个新的测试客户端,它通过gRPC向导连接到我们的服务器.

  1. 要将我们的服务器更改为通过HTTP/1通信,我们将编辑我们的 appsettings.json JSON file:
    1. Adjust the Protocol 田野(在小路上找到的) Kestrel.EndpointDefaults.Protocols) to read Https.
    2. Save the file.
  2. 让我们的新客户读这个 proto 信息,服务器必须正在运行. 最初,我们从VS的设置启动项目对话框中启动了之前的客户端和服务器. 调整服务器解决方案以仅启动服务器项目,然后启动解决方案. (现在我们已经修改了HTTP版本, 我们的老客户端已经不能和服务器通信了.)
  3. 接下来,创建新的测试客户端. 启动另一个VS实例. 中详述的步骤将重复 创建API项目 节,但这次,我们将选择 Console App template. 我们将命名我们的项目和解决方案 InventoryAppConnected.
  4. 创建了客户端机箱后,我们将连接到gRPC服务器. 在VS解决方案资源管理器中展开新项目.
    1. Right-click Dependencies 然后,在上下文菜单中选择 管理连接的服务.
    2. 在“已连接服务”页签中,单击 添加服务引用 and choose gRPC.
    3. 在添加服务引用对话框中,选择 URL 选项,并输入 http 服务地址的版本(记住从获取随机生成的端口号) launchsettings.json).
    4. Click Finish 添加易于维护的服务引用.

你可以随意把你的作业对照一下 此示例的示例代码. Since, under the hood, VS已经生成了我们在第一轮测试中使用的相同的客户端, 的内容可以重复使用 Program.cs 文件从上一个服务逐字删除.

当我们更改合约时,我们需要修改客户端gRPC定义以匹配更新后的定义 .proto definition. 要做到这一点,我们只需要访问VS的Connected Services并刷新相关的服务条目. 现在,我们的gRPC项目已经完成,并且很容易保持我们的服务和客户端同步.

你的下一个项目候选人:gRPC

我们的gRPC实现提供了使用gRPC的好处的第一手资料. REST和gRPC都有自己的理想用例,这取决于契约类型. However, 当两种选择都适合时, 我鼓励您尝试grpc——它将使您在未来的api中处于领先地位.

了解基本知识

  • gRPC的用途是什么?

    gRPC是一个提供系统间通信的框架.

  • REST api和gRPC有什么区别?

    REST api通常使用JSON或XML消息格式,而gRPC使用协议缓冲区. 为了表示错误,REST api使用HTTP状态码,而gRPC使用错误码. gRPC的消息大小往往比REST api小得多.

  • 协议缓冲区是如何工作的?

    协议缓冲区是gRPC的合约消息格式. gRPC库使用这种格式作为它的序列化结构.

  • gRPC比REST快吗?

    当我们将gRPC与REST性能进行比较时,gRPC明显比REST快.

  • What is gRPC-Web?

    gRPC- web是一个浏览器端JavaScript客户端,用于与gRPC服务通信.

就这一主题咨询作者或专家.
Schedule a call
Laszlo Gyori的头像
Laszlo Gyori

Located in Budapest, Hungary

Member since February 14, 2022

About the author

Laszlo是一名解决方案架构师, software developer, 也是微服务架构方面的专家, gRPC, and REST. 他拥有布达佩斯理工学院信息技术硕士学位.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Expertise

Previously At

塔塔咨询服务

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.