如何在.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的数字。我是否也可以建议,如果您想使用这些数字,那么您将遇到在本专栏中我无法解决的问题。

真的。别那样做。

References

[1] Protocol Buffers规范中: https://developers.google.com/protocol-buffers/docs/proto3#scalar
[2] 规范: https://developers.google.com/protocol-buffers/docs/proto3
[3] 较早的概述中: https://visualstudiomagazine.com/articles/2019/08/28/grpc-web-services.aspx
[4] 那样: https://visualstudiomagazine.com/articles/2019/08/28/grpc-web-services.aspx
[5] 标量类型说明: https://developers.google.com/protocol-buffers/docs/proto3#scalar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

五大原则之----里氏替换原则(LSP)

阐述&#xff1a;子类型&#xff08;subtype&#xff09;必须能够替换掉它们的基类型&#xff08;basetype&#xff09; 先提出一个问题&#xff1a;正方形是不是一种特殊的长方形&#xff08;IS - A关系&#xff09;&#xff1f; 先不要回答这个问题&#xff0c;看下面的分析。…

数学学得好,才可以发现别人发现不了的挣钱良机

全世界有3.14 % 的人已经关注了数据与算法之美2011年&#xff0c;美国波士顿地区的一种彩票 “Cash WinFal”爆出了一个存在已久的漏洞。让人惊奇的是&#xff0c;一对 73 岁的夫妇已经利用这个漏洞赚了超过 600 万美元 。一时间风雨满城&#xff0c;马萨诸塞州也宣布要开始调查…

java富文本如何转义_富文本编辑器wangEditor中转义字符的问题

前段时间做项目的时候&#xff0c;要使用富文本编辑器&#xff0c;采用的是wangEditor&#xff0c;结果当用户在为文本添加样式的时候&#xff0c;发现居然无法直接保存&#xff0c;遂查看后台数据。发现很多样式都被过滤掉了&#xff0c;后台接受的数据中根本没有样式。在网上…

Async和Await异步编程的原理

1. 简介 从4.0版本开始.NET引入并行编程库&#xff0c;用户能够通过这个库快捷的开发并行计算和并行任务处理的程序。在4.5版本中.NET又引入了Async和Await两个新的关键字&#xff0c;在语言层面对并行编程给予进一步的支持&#xff0c;使得用户能以一种简洁直观的方式实现并行…

Lang.NEXT 2012相关Session

2012年4.2-4日的Lang.NEXT 2012是.NET(CLR, DLR 以及其他平台)上语言及相关工具的设计开发者的盛会。会议的相关Session已经放出&#xff0c;绝对值得好好的学习&#xff0c;地址是&#xff1a;http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012?sortsequential&…

细数那些让人难以抗拒的经典数学书

如果有人不相信数学是简单的,那是因为他们没有意识到人生有多复杂。——冯诺依曼近期有关数学的好消息还是蛮多的&#xff0c;先有阿里巴巴举办全国数学竞赛&#xff0c;奖金百万&#xff0c;只为爱好数学的你。快来看看下面这些竞赛试题&#xff0c;我想应该难不倒我们的小伙伴…

java对jar包的复制_Java安全之jar包调试技巧

Java安全之jar包调试技巧调试程序首先还是创建一个工程&#xff0c;将jar包导入进来调试模式的参数启动中需要加入特定参数才能使用debug模式&#xff0c;并且需要开放调试端口JDK5-8:-agentlib:jdwptransportdt_socket,servery,suspendy,address5005JDK9&#xff1a;-agentlib…

最近忙的事

最近忙于背ccna题库&#xff0c;实际上。。我基本上感觉是中文背两次英文的还要看两次&#xff0c;这样才行。至于实验&#xff0c;貌似。。不敢去碰&#xff0c;因为每次做同一个实验遇到的问题那可是都不一样啊。还有。。四级&#xff0c;还有。。论文等等&#xff0c;说起来…

一次Redis client组件性能分析

BeetleX也扩展了RedisClient驱动&#xff0c;写这些高并发应用的驱动性能测试分析是必不可少的。在最近一次测试中发现测试采样度不足&#xff0c;引起的一些问题&#xff1b;通过这一次的问题也警醒一下自己在以后设计上要考虑更多细节的特性需求。发现问题在写组件的时候往往…

男生追女生的超强数学建模分析

全世界有3.14 % 的人已经关注了数据与算法之美问题分析男生追女生&#xff0c;对男生来说最重要的是学习、爱情两不误。因此我们引进男生的学业成绩函数Y(t)。首先&#xff0c;我们不考虑男生的追求攻势&#xff0c;则影响该函数的因素主要是两个人的关系程度。为了便于分析&am…

java设计模式face_java设计模式之-------原型模式

一、模式定义用原型实例指定要创建对象的种类&#xff0c;并通过拷贝这些原型创建新的对象。二、模式场景假设此处结合23中设计模式记忆篇作出假设&#xff0c;不关心逻辑是否合理。柳岩在跳舞的时候烧伤了脸&#xff0c;再也回不到原来的型状。他就克隆一张脸。类图如下&#…

乐观锁与悲观锁各自适用场景是什么?

机制乐观锁是一种思想&#xff0c;具体实现是&#xff0c;表中有一个版本字段&#xff0c;第一次读的时候&#xff0c;获取到这个字段。处理完业务逻辑开始更新的时候&#xff0c;需要再次查看该字段的值是否和第一次的一样。如果一样更新&#xff0c;反之拒绝。之所以叫乐观&a…

你被这些网络迷题难倒过吗?

全世界有3.14 % 的人已经关注了数据与算法之美消失的正方形这是数学游戏大师马丁加德纳在《从惊讶到思考》一书中提到过的例子。重新摆放分割的小块图形后&#xff0c;上面的正方形中少了一个小方格&#xff0c;它去了哪里&#xff1f;我们不妨实际操作一下&#xff0c;做两个全…

tplink-wr841n无线路由接入到局域网三层交换机方法

把tplink-wr841n无线路由接入到局域网三层交换机方法&#xff1a;1.设置无线路由wan口动态获取IP&#xff0c;获取上级三层交换机分配的IP。不与本地局域网一个网段。2.设无线路由的lan口IP为管理IP,与wan口在不同一网段。WAN口IP地址和LAN口IP地址不能处于同一子网&#xff0c…

php值比较大小,PHP_PHP浮点比较大小的方法,本文实例讲述了PHP浮点比较大 - phpStudy...

PHP浮点比较大小的方法本文实例讲述了PHP浮点比较大小的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;/*** 浮点数一般是不能用来比较大小的&#xff0c;但是我们可以用一种变通的的方式* 用var_dump输出浮点是看不出效果的,可以用serialize查看* 1.round 2.浮点…

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架

什么是BlazorBlazor是一个使用.NET生成交互式客户端WebUI的框架:使用C#代替JavaScript来创建信息丰富的交互式UI。共享使用.NET编写的服务器端和客户端应用逻辑。将UI呈现为HTML和CSS&#xff0c;以支持众多浏览器&#xff0c;其中包括移动浏览器。与新式托管平台&#xff08;如…

看来要先拒绝37%的女人,才能找到真爱

全世界有3.14 % 的人已经关注了数据与算法之美在每期《非诚勿扰》节目上&#xff0c;面对一位位男嘉宾&#xff0c;24位单身女生要做出不止一次“艰难的决定”&#xff1a;到底要不要继续亮灯&#xff1f;把灯灭掉意味着放弃了这一次机会&#xff0c;继续亮灯则有可能结束节目之…

Java程序员从笨鸟到菜鸟之(三十)javascript弹出框、事件、对象化编程

一&#xff1a;弹出框 JavaScript中有三种弹出框:警告(alert)、确认(confirm)以及提问(prompt)。 1.警告(alert) 在访问网站的时候&#xff0c;你遇到“咚”的一声&#xff0c;一个小窗口出现在你面前&#xff0c;上面写着一段警示性的文字&#xff0c;或是其它的提示信息。如…

php如何将页面嵌入在另一盒子里,如何将一个盒子在显示在浏览器的正中间_html/css_WEB-ITnose...

1、通过CSS来实现1)position: absolute; top:50%; left:50%; margin-left:-101px; margin-top:-101px;2) position:absolute; left:0; top:0; right:0; bottom:0; margin:auto;2、通过JS来实现说明 在普通文档流里&#xff0c;margin: auto; 的意思是设置元素的margin-top和mar…

.Net日志之nlog

1. 介绍NLog是适用于各种.NET平台&#xff08;包括.NET标准&#xff09;的灵活&#xff0c;免费的日志记录平台&#xff0c;支持数据库、文件、控制台。2. 输入到文件2.1 引用nuget包<PackageReference Include"NLog" Version"4.7.6" /><PackageR…