当你第一次定义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(2)Go语言的例子(下)

    第一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html gRPC in ASP.NET Core 3.x -- Protocol Buf ...

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

    上一篇文章(大约半年前写的):https://www.cnblogs.com/cgzl/p/11246324.html 建立Go项目 在GOPATH的src下面建立一个文件夹 protobuf-go, ...

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

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

  4. gRPC在 ASP.NET Core 中应用学习(二)

    前言: 上一篇文章中简单的对gRPC进行了简单了解,并实现了gRPC在ASP.NET Core中服务实现.客户端调用:那么本篇继续对gRPC的4中服务方法定义.其他使用注意点进一步了解学习 一.gRP ...

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

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

  6. 微软推出ASP.NET Core 2.0,并支持更新Visual Studio 2017

    微软推出ASP.NET Core 2.0的一般可用性,并发布.NET Core 2.0.该公司还推出了其旗舰集成开发环境(IDE)的更新:Visual Studio 2017版本15.3和Visual ...

  7. asp.net core 2.2 生产环境直接更新View页面并立即生效

    有的时候我们会直接在生产环境上更新页面文件,比如更改了JS代码,CSS代码或页面的文案,布局等.这种没有改到后台代码的情况一般就是直接发布页面文件了,在asp.net core 2.2以前的版本(没有 ...

  8. 【架构篇】ASP.NET Core 基于 Consul 动态配置热更新

    背景 通常,.Net 应用程序中的配置存储在配置文件中,例如 App.config.Web.config 或 appsettings.json.从 ASP.Net Core 开始,出现了一个新的可扩展 ...

  9. ASP.NET Core框架揭秘[博文汇总-持续更新]

    第1部分 跨平台开发体验 1 跨平台开发体验 001 跨平台开发体验: Windows [上篇]         002 跨平台开发体验: Windows [中篇]        003 跨平台开发体 ...

随机推荐

  1. pip 更换镜像源

    国内的pip源 阿里云:https://mirrors.aliyun.com/pypi/simple/ 清华:https://pypi.tuna.tsinghua.edu.cn/simple 中国科技 ...

  2. laravel上传git如何忽略你不想提交的文件

    1.在文件根目录下面有一个文件 .gitignore .gitignore文件用来忽略被指定的文件或文件夹的改动,被记录在.gitignore文件里的文件或文件夹,是无法被git跟踪到的,换句话说,被 ...

  3. 性能优化-css,js的加载与执行

    前端性能优化 css,js的加载与执行 javascript是单线程的 一个网站在浏览器是如何进行渲染的呢? html页面加载渲染的过程 html渲染过程的一些特点 顺序执行,并发加载 词法分析 并发 ...

  4. Visual Studio 问题汇总

    VS2019 16.3.6   1   JSON 文件没有进行格式化验证 开发时运行正常,部署在IIS中有错误提示. 2  .NET Core 3.0 没有提供中文包 所有注释都是英文的.

  5. Python基础笔记2

    @time 2019/12/17 12:04 一.列表 1.增加数据:append.insert方法 names = ["兰陵王", "孙悟空", " ...

  6. Pytest学习9-常用插件

    pytest-django:为django应用程序编写测试. pytest-twisted:为twisted应用程序编写测试,启动反应堆并处理测试函数的延迟. pytest-cov:覆盖率报告,与分布 ...

  7. [POI2008] STA-Station - 树形dp

    很显然的递推式ans[q] = ans[p] + n - 2*siz[q]; 这么个题你卡我常干嘛,害得我加快读 (谁叫我是vector党呢 #include <bits/stdc++.h> ...

  8. [P3935] Calculating - 整除分块

    容易发现题目要求的 \(f(x)\) 就是 \(x\) 的不同因子个数 现在考虑如何求 \(\sum_{i=1}^n f(i)\),可以考虑去算每个数作为因子出现了多少次,很容易发现是 \([n/i] ...

  9. 跨域 node git

    promise 异步回调地狱:就是多个异步请求嵌套的表现 瑕疵:后期维护难 解决:通过promise技术 什么是promise:就是一种异步编程的解决方案 有三个状态:进行中.成功了,失败了 var ...

  10. git&github 的使用

    git(/ɡɪt/[5], 音频(帮助·信息))是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布.最初目的是为更好地管理Linux内核开发而 ...