如何在.NET Core中为gRPC服务设计消息文件(Proto)

如何在.NET Core中为gRPC服务设计消息

使用协议缓冲区规范定义gRPC服务非常容易,但从需求转换为.NET Core,然后管理服务的演变时,需要注意几件事。

创建gRPC服务的核心是.proto文件,该文件以与语言无关的格式描述了该服务。使用.proto文件,Visual Studio可以为您的服务生成基类(您只需编写特定于业务的代码),或者可以生成用于可靠访问服务的客户端类。

.proto文件必须符合Google的协议缓冲区规范(通常称为ProtoBuf)。原始文件的内容使您可以指定服务的接口。服务接口由两部分组成:

  • 您的gRPC服务提供的方法
  • 这些方法的参数和返回值的数据结构

您可以使用Protocol Buffers规范中[1]定义的标量类型来构建这些数据结构(在ProtoBuf中称为“消息”)。可用的类型包括布尔值,字符串,字节数组和各种数字类型(浮点型,整数型和长型)。没有日期或固定的十进制类型。在接下来的专栏中,我将向您展示如何添加时间戳类型。对于小数,您可以使用float ...并伴随着float带来的精度损失。

如果您要开始一个新项目,则要使用自2016年以来的proto3语法。但是,您必须在.proto文件的第一行“非空”行上明确指定proto3标准。引用规范[2]),否则将使用proto2规范解析您的.proto文件。指定您的文件使用proto3看起来像这样:

syntax = "proto3";

消息和C#类

使用proto3规范,用于客户信息的消息格式可能如下所示:

message CustomerResponse {
  int32 custid = 1;
  string firstName = 2;
  string lastName = 3;
  int32 age = 4;
  fixed32 creditLimit = 5;
}

等号后的数字指定消息中字段的位置,从位置1开始(在我的示例中,firstName将是消息中的第二个字段)。这些数字在消息中必须是唯一的(即,您不能在同一位置使用两个字段)。您不必按数字顺序列出字段,但是如果您这样做的话,则可以更轻松地发现重复的字段编号(尽管Visual Studio将发现任何重复的编号,并在构建应用程序时将其报告在“错误列表”中)。如果需要,您也可以跳过职位。此定义仅使用奇数,例如:

message CustomerResponse {
  int32 custid = 1;
  string firstName = 3;
  string lastName = 5;
}

在.NET Core中,消息格式被转换为类,每个字段都成为与消息同名的类的属性。命名这些属性时,.NET Core还将字段名称的第一个字符转换为大写。因此,例如,我上一个示例中的custId字段将成为我代码中CustomerResponse类上的CustId属性。

在此过程中,还得删除字段名称中的所有下划线,并且将以下字母大写(即,Last_name字段名称变为LastName属性)。

该过程还涉及将.NET类型映射到ProtoBuf类型(例如,ProtoBuf int32变为.NET int,ProtoBuf的int64变为long,fixed32变为uint),这需要向.NET Core添加一些新类。例如,ProtoBuf支持字节数组,其类型为字节。名为ByteString的新.NET数据类型支持该字段类型。要加载ByteString,请使用ByteString类的静态CopyFrom方法,并传递一个字节数组,如下所示:

byte[] bytes = new byte[1000];
cr.Valid = ByteString.CopyFrom(bytes);

要从ByteString检索字节数组,请使用对象的CopyTo方法,并传递要将字节复制到的数组和起始位置:

cr.Valid.CopyTo(bytes,0);

数组和字典

您也可以使用【repeated】的关键字将集合包括在定义中(在ProtoBuf中,不是集合的字段称为“单数”)。如果我的客户消息需要一组重复的交易金额,则可以指定如下字段:

message Customer {
   int32 id = 1;
   repeated fixed32 transactionAmounts = 4;

重复的字段在转换为类的属性时,也使用新的类型:Google.Protobuf.RepeatedField。例如,我的示例将生成Google.Protobuf.RepeatedField(无符号整数)的属性。您可以使用{}语法来初始化数组,如下所示:

CustomerResponse cr = new CustomerResponse
            {
                CreditLimit = {10, 15, 100}
            };

您可能更可能使用其各种Add方法将项目放入集合中:

cr.CreditLimit.Add(200);

您可以使用LINQ方法(例如First())或按位置访问RepeatedField中的项目。可以正常工作,例如:

uint tranAmount = cr.CreditLimit [1];

ProtoBuf还支持称为map的Dictionary-type集合,该集合允许您为字典的键和值指定类型。我的客户消息可能会使用“友好名称”来跟踪客户的各种信用卡,以定义一个字典,该字典包含密钥(“彼得卡”,“我的旅行卡”)和值(信用卡号)的字符串):

message CustomerResponse {
  int32 custId = 1;
  map<string, string> cards = 2;

有趣的是,在Visual Studio 2019预览版中,编辑器不会像其他类型一样突出显示map对象(尽管编译得很好)。

相应的属性将为Google.Protobuf.Collections.MapField类型,您可以通过将其Add方法传递给键和一个值来加载它,就像其他任何Dictionary一样。

管理变更

上线后(客户端开始使用它)更改.proto文件相对容易。例如,您可以将具有新位置编号的字段添加到服务器端软件使用的.proto文件中,而不会打扰仍在使用该文件的早期版本的客户端:客户端只是忽略未在其.proto文件中列出的字段。

同样,在相反的情况下(当服务器.proto文件没有客户端的.proto字段具有的字段时),客户端只会发现服务器未发送的属性被设置为其默认值。顺便说一句,在服务器的.proto文件中定义的,未在客户端的.proto文件中定义的字段仍会发送到客户端,但是.NET不能提供一种方便的方式来访问它(至少现在还没有)。

确实,随着服务的发展和修改其.proto文件,您仅应遵守两个规则:

  • 不要更改现有字段的位置编号
  • 不要回收职位编号(即不要用新的字段3替换过时的字段3)

但是,从.proto文件生成的属性不可为空,因此,如果未将属性设置为值,则它将被设置为其默认值。这意味着数字被设置为0;数字被设置为0。将string设置为string.Empty(长度为零的字符串);布尔变成虚假的;ByteString属性默认为ByteString对象,其IsEmpty属性设置为true;并且RepeatedField和MapField属性均默认为其对应的对象,每个对象均不包含任何项目,并且其Count属性设置为0。

由于这种行为,存在从服务的.proto文件中删除字段并且不更新所有客户端(或者只是在服务器上生成响应时未在对象上设置属性)的危险。危险是客户端无法区分未使用的字段和已设置为其默认值的属性之间的区别。如果将我的客户的有效属性设置为false,则客户端将无法确定客户是否无效或服务器是否不再生成该字段。

您可能需要考虑将属性初始化为某个“不合理的”值(例如,数字为-1),以便客户端可以区分设置为默认值的属性和已删除的字段之间的区别。因为这对于布尔值是不可能的(布尔值没有不合理的值),所以您要特别警惕删除(甚至不再使用)布尔类型的字段。

效率和局限性

正如我在较早的概述中[3]所讨论的那样[4],gRPC服务的功能之一是它们的消息比基于HTTP的(RESTful)服务小得多。如果您真的想利用这种效率,请注意位置1到15仅需要一个字节的额外开销(即超出存储值的数据),而位置16到2047则需要两个字节。将消息格式保持在16位以下似乎是个好主意。

有关将数据打包到尽可能小的空间的选择类型方面的其他效率提示,请参阅规范中的标量类型说明[5]。

顺便说一句,您不能使用以下任何一种作为字段位置编号:负数,0、19,000到19,999(保留给ProtoBuf使用)或大于536,870,911的数字。我是否也可以建议,如果您想使用这些数字,那么您将遇到在本专栏中我无法解决的问题。

真的。别那样做。

以上就是如何在.NET Core中为gRPC服务设计消息文件(Proto)的详细内容,更多关于.NET Core中为gRPC服务设计消息文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • ASP.NET Core 3.0 gRPC拦截器的使用

    一. 前言 前面两篇文章给大家介绍了使用gRPC的入门以及双向流的使用,今天介绍的是gRPC中的拦截器.拦截器就像MVC的过滤器或者是ASP.NET Core middleware 一样,具有面向切面的思想,可以在调用服务的时候进行一些统一处理, 很适合在这里处理验证.日志等流程.本片文章就以记录日志为例来进行讲解. 二. Interceptor 类介绍 Interceptor类是gRPC服务拦截器的基类,是一个抽象类,它定了几个虚方法,分别如下: public virtual TRespons

  • 图析ASP.NET Core引入gRPC服务模板

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安装.NET Core3.0预览版的SDK.至于开发工具我用的时VS2019,当然你也可以使用VS Code进行. gRPC的简单介绍 gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. 有关 gRPC 基础知识的详细信息,请参阅 gRPC 文档页. gRPC 的主要优点是: 现代高性

  • .Net Core中使用Grpc的方法

    一.Grpc概述 gRPC 基于如下思想:定义一个服务, 指定其可以被远程调用的方法及其参数和返回类型.gRPC 默认使用protocol buffers作为接口定义语言,来描述服务接口和有效载荷消息结构.如果有需要的话,可以使用其他替代方案. 定义的服务分为4中类型: 单项 RPC,即客户端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用.这种最常用. 服务端流式 RPC,即客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息.客户端从返回的数据流里一直读取直到没有

  • ASP.NET Core 3.0使用gRPC的具体方法

    一.简介 gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架. gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建.它使用HTTP/2作为通信协议,使用 Protocol Buffers 作为序列化协议. 它的主要优点: 现代高性能轻量级 RPC 框架. 约定优先的 API 开发,默认使用 Protocol Buffers 作为描述语言,允许与语言无关的实现. 可用于多种语言的工具,以生成强类型的服务器和客户端. 支持客户端,服务器双向流调

  • 如何在.NET Core中为gRPC服务设计消息文件(Proto)

    如何在.NET Core中为gRPC服务设计消息 使用协议缓冲区规范定义gRPC服务非常容易,但从需求转换为.NET Core,然后管理服务的演变时,需要注意几件事. 创建gRPC服务的核心是.proto文件,该文件以与语言无关的格式描述了该服务.使用.proto文件,Visual Studio可以为您的服务生成基类(您只需编写特定于业务的代码),或者可以生成用于可靠访问服务的客户端类. .proto文件必须符合Google的协议缓冲区规范(通常称为ProtoBuf).原始文件的内容使您可以指定

  • 在 ASP.NET Core 中为 gRPC 服务添加全局异常处理

    目录 一.咨询区 Dmitriy 二.回答区 valentasm 三.点评区 以下文章来源于公众号:DotNetCore实战 一.咨询区 Dmitriy 在 ASP.NET Core 中使用GRPC.ASPNETCore 工具包写 gRPC 服务,想实现 gRPC 的异常全局拦截, 代码如下: app.UseExceptionHandler(configure => {     configure.Run(async e =>     {         Console.WriteLine(&

  • 使用VS2022在ASP.NET Core中构建轻量级服务

    目录 1. 使用 VS2022 创建 ASP.NET Core 项目 2. 在 ASP.NET Core 中启用一个轻量级的服务 3. 在 ASP.NET Core 中使用 IEndpointConventionBuilder 扩展方法 4. 在 ASP.NET Core 中使用轻量级服务检索记录 5. 在 ASP.NET Core 中使用轻量级服务创建记录 6. 在 ASP.NET Core 中使用轻量级服务删除记录 7. ASP.NET Core 中轻量级服务的配置方法 8. 在 ASP.N

  • ASP.NET Core中使用EPPlus导入出Excel文件的完整步骤

    前言 这篇文章说明了如何使用EPPlus在ASP.NET Core中导入和导出.xls/.xlsx文件(Excel).在考虑使用.NET处理excel时,我们总是寻找第三方库或组件.使用Open Office Xml格式(xlsx)读取和写入Excel 2007/2010文件的最流行的.net库之一是EPPlus.这个库现在已经支持.NET Core许久了.这适用于Windows,Linux和Mac. 因此,让我们创建一个新的ASP.NET Core WEB API应用程序并安装EPPlus.C

  • ASP.NET Core中引用OpenAPI服务添加示例

    目录 文章目录 前言:一.将 Swagger 引入 WebAPI 项目二.添加 OpenAPI 服务引用参考文档 前言: 本文使用 .NET Core SDK 3.1 的版本.在我们使用微服务的时候,各个微服务之间会经常调用接口,但是手动写Http请求的代码非常繁琐,在 Visual Studio 2019 的 .NET Core 项目中提供了添加连接的服务的功能,使得我们的工作变得简单容易. 一.将 Swagger 引入 WebAPI 项目 将 Swagger 引入 ASP.NET Core

  • asp.net Core中同名服务注册的实现代码

    目录 1.使用.net Core自带容器 2.AutoFac中的实现 通常情况下,在使用注入时一个服务接口对应一个实现类,注入方式采用构造函数注入即可,但如果存在多个类实现同一个接口的情况下,则需要根据实际情况来选择不同的实现类. 如以下代码中的MyEmailService和EmailService都实现了IEmailService接口: public class MyEmailService : IEmailService { public string Send(string Email)

  • 谈谈如何在ASP.NET Core中实现CORS跨域

    CORS(Cross-origin resource sharing)是一个W3C标准,翻译过来就是 "跨域资源共享",它主要是解决Ajax跨域限制的问题. CORS需要浏览器和服务器支持,现在所有现代浏览器都支持这一特性.注:IE10及以上 只要浏览器支持,其实CORS所有的配置都是在服务端进行的,而前端的操作浏览器会自动完成. 在本例中,将演示如何再ASP.NET Core中实现CORS跨域. 前期准备 你需要windows系统. 你需要安装IIS. 推荐使用VS2015 Upda

  • 如何在.NET Core应用中使用NHibernate详解

    前言 Nhibernate 来源于非常优秀的基于Java的Hibernate 关系型持久化工具.NHibernate最近发布了 5.1.3 版本, 支持 .NET Standard 2.0 , 这意味着可以在 .NET Core 2.0 应用中使用, 本文就已 WebAPI 应用为例, 介绍一下如何在 .NET Core 应用中如何使用 NHibernate .下面话不多说了,来一起看看详细的介绍的吧 使用方法如下: 1. 新建一个基于 .NET Core 的 Web API应用, 命令如下:

随机推荐