当你第一次定义Protocol Buffer的消息的时候,你肯定会给消息设定一套规则需求。但是随着时间的推进,你的业务可能会发生了变化,与此同时,你的Protocol Buffer消息类型的需求也会随之变化。

也就是说:有一些字段可能会发生变化,可能会添加一些字段,也可能会删除一些字段。但是可能有很多程序正在使用/读取你的Protocol Buffer的消息,但是它们没法都随着需求进行更新。所以,在你对源数据进行演进的时候,一定不要引起破坏性变化,否则其它的程序可能就无法正常工作了。

主要有这两种情景:

  1. 向前兼容变更:使用新的.proto文件来写数据 --- 从旧的.proto文件读取数据

  2. 向后兼容变更:使用旧的.proto文件来写数据 --- 从新的.proto文件读取数据

有时候这两种情况同时存在,也就是全兼容变更。

为了达到此目的,Protocol Buffer制定了一些更新消息类型的规则:

  1. 不要修改任何现有字段的数字(tag)

  2. 你可以添加新的字段,那些使用旧的消息格式的代码仍然可以将消息序列化,您应该注意这些元素的默认值,以便新代码可以与旧代码生成的消息正确交互。类似的,新代码所创建的消息也可以被旧代码解析:旧的二进制在解析的时候会忽略新的字段。

  3. 字段可以被删除,只要它们的数字(tag)在更新后的消息类型中不再使用即可。你也可以把字段名改为使用“OBSOLETE_”前缀而不是删除字段,或者把这些字段的数字(tag)进行保留(reserved),以免未来其它开发者不消息使用了删除字段的数字。

  4. 对于数据类型的变化,例如int32到int64,string到bytes等等,可以参考官方文档:
    https://developers.google.com/protocol-buffers/docs/proto3#updating。但是建议还是尽量不要去修改字段的数据类型。

添加字段

原来的proto是这样的:

然后我添加一个name字段:

而这时,如果把新的消息发送到旧的代码的时候,旧代码不知道2这个数字tag对应的是什么,所以name这个字段就会被忽略掉。

反过来,如果我们使用新的代码读取旧的数据,那么就会找不到新的字段,这时候就会使用该字段类型的默认值(空字符串)。

所以,处理默认值的时候一定要非常的小心

对字段重命名

现在我把name这个字段的名改成了full_name,而它的数字不变:

这样做是没有任何问题的。

你可以随意改变字段的名字,只要它的数字tag不变就行,因为Protocol Buffer里面这个数字tag才是最重要的。

删除字段

现在我又把full_name字段删除了:

这时候,如果旧的代码找不到这个字段了,那么就会采用默认值。

反过来,如果我们使用新的代码读取旧的数据,那么已删除的字段将会被忽略/丢弃。

但是,在删除字段的时候,你应该一直都保留字段的数字tag以及字段名,像这样:

这样做是防止数字tag和名称被重复使用,避免在以后的代码库里造成冲突。

使用OBSOLETE

之前说了,可以把字段名改为 OBSOLETE_字段名 来代替删除字段,但是这样做的缺点就是:你还是需要把这个字段的值计算出来。我还是建议使用reserve的方式进行删除字段的管理。

Reserved

  • 你可以保留字段的数字tag和字段名;

  • 但是不可以在同一行语句里混合reserved数字tag和字段名,应该分成两个语句:

  • 保留字段数字tag的目的就是防止数字tag被重复使用;

  • 而保留字段名的目的就是防止出现一些程序bug;

注意:一定不要移除reserved的数字tags。

默认值

默认值在更新Protocol Buffer消息定义的时候有很重要的作用,它可以防止对现有代码/新代码造成破坏性影响。它们也可以保证字段永远不会有null值。

但是,默认值还是非常危险的:

  • 你无法区分这个默认值到底是来自一个丢失的字段还是字段的实际值正好等于默认值。

那么应该怎么办?

  • 需要保证这个默认值对于业务来说是一个毫无意义的值。例如 int32 pop(人口)默认值就可以设置为-1。

  • 再就是,可能需要在你的代码里来做一些对默认值的判断,从而进行处理。

枚举

enum同样可以进化,就和消息的字段一样,可以添加、删除值,也可以保留值。

但是如果代码不知道它接收到的值对应哪个enum值,那么enum的默认值将会被采用。

例如这个enum:

如果程序代码接收到了5这个数值,那么它找不到对应的枚举值,所以就会使用这个枚举的默认值0(UNSPECIFIED)。

gRPC in ASP.NET Core 3.x -- Protocol Buffer(3)更新消息类型相关推荐

  1. gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(下)

    前两篇文章半年前写的: gRPC in ASP.NET Core 3.0 -- Protocol Buffer(1), gRPC in ASP.NET Core 3.0 -- Protocol Buf ...

  2. gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(上)

    前两篇文章半年前写的: gRPC in ASP.NET Core 3.0 -- Protocol Buffer(1), gRPC in ASP.NET Core 3.0 -- Protocol Buf ...

  3. gRPC in ASP.NET Core 3.0 -- Protocol Buffer(1)

    开发环境: IDE: VSCode VSCode的扩展插件:vscode-proto3和Clang-Format这两个扩展 Windows还需要安装Clang,Windows 64位系统的地址如下:C ...

  4. gRPC in ASP.NET Core 3.x - gRPC 消息定义

    之前写了几篇关于 Protoco Buffer 的文章. gRPC in ASP.NET Core 3.x - gRPC 简介(1) gRPC in ASP.NET Core 3.x - gRPC 简 ...

  5. gRPC in ASP.NET Core 3.x - gRPC 简介(2)

    前一篇: gRPC in ASP.NET Core 3.x - gRPC 简介(1) 身份认证 这里指的不是用户的身份认证,而是指多个server和client之间,它们如何识别出来谁是谁,并且能安全 ...

  6. gRPC in ASP.NET Core 3.x - gRPC 简介(1)

    gRPC的结构 在我们搭建gRPC通信系统之前,首先需要知道gRPC的结构组成. 首先,需要一个server(服务器),它用来接收和处理请求,然后返回响应. 既然有server,那么肯定有client ...

  7. gRPC in ASP.NET Core 3.0 -- 前言

    现如今微服务很流行,而微服务很有可能是使用不同语言进行构建的.而微服务之间通常需要相互通信,所以微服务之间必须在以下几个方面达成共识: 需要使用某种API 数据格式 错误的模式 负载均衡 ... 现在 ...

  8. WTM(ASP.NET Core)使用ASP.NET Core自带TagHelper显示模型验证消息

    WTM框架使用TagHelper提供了丰富的前端控件,目前框架只支持LayUI,后期会增加更多框架整体的运转并不依赖于LayUI,开发人员可以使用最普通的Html来编写页面,框架提供的控件只是简化编写 ...

  9. ASP.NET Core 3.0 使用gRPC

    一.简介 gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架.gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建.它使用HTTP/2作为通信协议 ...

最新文章

  1. pdf转换为word问题
  2. mysql内存体系结构_Innodb存储引擎的体系架构之内存
  3. 用python实现TCP协议传输功能(服务端代码)
  4. python连接mongo数据库
  5. idea中ajax中文乱码
  6. Linux信号实现精确到微秒的sleep函数:通过sigsuspend函数解决时序竞态问题
  7. Ignite Compute helloworld-分布式计算
  8. java final对象_java面向对象基础_final详细介绍
  9. 工程伦理思考题汇总——张永强主编
  10. C# .net MVC 微信红包(服务号发送红包)
  11. 利用pandas进行数据分析
  12. JavaScript(第五天)—爱创课堂专业前端培训
  13. 微信小程序使用qrcode生成二维码(可用于微信收款)
  14. cad批量打印_CAD批量打印
  15. 不可错过的250款独立游戏(珍藏版)
  16. 嵌入式linux与windows之间的tftp文件传输(保姆级)
  17. python学习第六天
  18. 笑傲江湖客户端服务器地址修改,笑傲江湖.新手上路.MUD客户端
  19. matlab标志,使用MATLAB画出的图上面出现一个标志,不知道是怎么出现的
  20. Ue4----必备网络知识

热门文章

  1. Mac上Homebrew的使用 (Homebrew 使 OS X 更完整)
  2. 从Ubuntu命令行按进程名称杀死进程
  3. Vue使用Vuex一步步封装并使用store
  4. Vue 组件实例属性的使用
  5. 【机房收费系统】多么痛的领悟
  6. log4net日志插件的使用
  7. Android延时执行调用的几种方法
  8. 验证规则构建神器 FluentValidation.md
  9. dotnet 使用 Infer# 自动分析代码缺陷
  10. SignalR在React/Go技术栈的实践