【设计理念】编码与演化

编码与演化

  • 对于服务端(server-side)应用程序,可能需要执行滚动升级 ,一次将新版本部署到少数几个节点,检查新版本是否运行正常,然后逐渐部完所有的节点。这样无需中断服务即可部署新版本,为频繁发布提供了可行性,从而带来更好的可演化性。
  • 对于客户端(client-side)应用程序,升不升级就要看用户的心情了。用户可能相当长一段时间里都不会去升级软件。

这意味着,新旧版本的代码,以及新旧数据格式可能会在系统中同时共处。系统想要继续顺利运行,就需要保持双向兼容性:

  • 向后兼容 新代码可以读旧数据。新代码的作者当然知道由旧代码使用的数据格式,因此可以显示地处理它(最简单的办法是,保留旧代码即可读取旧数据)。
  • 向前兼容 旧代码可以读新数据。向前兼容性可能会更棘手,因为旧版的程序需要忽略新版数据格式中新增的部分。

编码数据的格式

程序通常(至少)使用两种形式的数据:

  1. 在内存中,数据保存在对象,结构体,列表,数组,哈希表,树等中。 这些数据结构针对CPU的高效访问和操作进行了优化(通常使用指针)。
  2. 如果要将数据写入文件,或通过网络发送,则必须将其编码(encode)为某种自包含的字节序列(例如,JSON文档)。 由于每个进程都有自己独立的地址空间,一个进程中的指针对任何其他进程都没有意义,所以这个字节序列表示会与通常在内存中使用的数据结构完全不同。

所以,需要在两种表示之间进行某种类型的翻译。 从内存中表示到字节序列的转换称为编码(Encoding)(也称为序列化(serialization)或编组(marshalling)),反过来称为解码(Decoding) (解析(Parsing),反序列化(deserialization),反编组(unmarshalling)) 。

JSON,XML和CSV

是文本格式,因此具有人类可读性(尽管语法是一个热门辩题)。除了表面的语法问题之外,它们也有一些微妙的问题:

  • 数字的编码多有歧义之处。XML和CSV不能区分数字和字符串(除非引用外部模式)。JSON虽然区分字符串和数字,但不区分整数和浮点数,而且不能指定精度。例如,大于$2^{53}$的整数不能在双精度浮点数中精确表示,因此在使用浮点数(例如JavaScript)的语言进行分析时,这些数字会变得不准确。
  • JSON和XML对Unicode字符串(即人类可读的文本)有很好的支持,但是它们不支持二进制数据。所以人们通过使用Base64将二进制数据编码为文本来绕开这个限制。XML和JSON都有可选的模式支持。但许多基于JSON的工具嫌麻烦不会使用模式。由于数据的正确解释(例如数字和二进制字符串)取决于模式中的信息,因此不使用XML/JSON模式的应用程序可能需要对相应的编码/解码逻辑进行硬编码。
  • CSV没有任何模式,因此应用程序需要定义每行和每列的含义。如果应用程序更改添加新的行或列,则必须手动处理该变更。 CSV也是一个相当模糊的格式(如果一个值包含逗号或换行符,会发生什么?)。尽管其转义规则已经被正式指定,但并不是所有的解析器都正确的实现了标准。

对于仅在组织内部使用的数据,使用最小公分母编码格式的压力较小。例如,可以选择更紧凑或更快的解析格式。虽然对小数据来说,收益可以忽略不计,但一旦达到TB级别,数据格式的选择就会产生巨大的影响。

JSON比XML简洁,但与二进制格式一比,还是太占地方。这一事实导致大量二进制编码版本JSON & XML的出现,JSON(MessagePack,BSON,BJSON,UBJSON,BISON和Smile等)。这些格式已经被各种各样的领域所采用,但是没有一个像JSON和XML的文本版本那样被广泛采用。

Thrift与Protocol Buffers

Apache Thrift 和Protocol Buffers(protobuf)是基于相同原理的二进制编码库。 Protocol Buffers最初是在Google开发的,Thrift最初是在Facebook开发的。 Thrift和Protocol Buffers都需要一个模式来编码任何数据。要在protobuf对数据进行编码,如下所示:

message Person {
    required string user_name = 1;
    optional int64 favorite_number = 2;
    repeated string interests = 3;
}

Thrift和Protocol Buffers每一个都带有一个代码生成工具,它采用了类似于这里所示的模式定义,并且生成了以各种编程语言实现模式的类。应用程序代码可以调用此生成的代码来对模式的记录进行编码或解码。

编码的记录就是其编码字段的拼接。每个字段由其标签号码(样本模式中的数字1,2,3)标识,并用数据类型(例如字符串或整数)注释。如果没有设置字段值,则简单地从编码记录中省略。字段标记对编码数据的含义至关重要。可以更改架构中字段的名称,因为编码的数据永远不会引用字段名称,但不能更改字段的标记,因为这会使所有现有的编码数据无效。

可以添加新的字段到架构,只要给每个字段一个新的标签号码。如果旧的代码(不知道你添加的新的标签号码)试图读取新代码写入的数据,包括一个新的字段,其标签号码不能识别,它可以简单地忽略该字段。数据类型注释允许解析器确定需要跳过的字节数。这保持了前向兼容性:旧代码可以读取由新代码编写的记录。

只要每个字段都有一个唯一的标签号码,新的代码总是可以读取旧的数据,因为标签号码仍然具有相同的含义。唯一的细节是,如果你添加一个新的领域,你不能要求required。如果您要添加一个字段并将其设置为必需,那么如果新代码读取旧代码写入的数据,则该检查将失败,因为旧代码不会写入您添加的新字段。因此,为了保持向后兼容性,在模式的初始部署之后添加的每个字段必须是可选的或具有默认值。

Avro

Apache Avro是另一种二进制编码格式,与Protocol Buffers和Thrift有趣的不同。 它是作为Hadoop的一个子项目在2009年开始的,因为Thrift不适合Hadoop的用例。

Avro也使用模式来指定正在编码的数据的结构。 它有两种模式语言:一种(Avro IDL)用于人工编辑,一种(基于JSON),更易于机器读取。

record Person {
    string userName;
    union { null, long } favoriteNumber = null;
    array<string> interests;
}

当应用程序想要编码一些数据(将其写入文件或数据库,通过网络发送等)时,它使用它知道的任何版本的模式编码数据,例如,架构可能被编译到应用程序中。这被称为作者的模式。

当一个应用程序想要解码一些数据(从一个文件或数据库读取数据,从网络接收数据等)时,它希望数据在某个模式中,这就是读者的模式。这是应用程序代码所依赖的模式,在应用程序的构建过程中,代码可能是从该模式生成的。

Avro的关键思想是作者的模式和读者的模式不必是相同的 - 他们只需要兼容。当数据解码(读取)时,Avro库通过并排查看作者的模式和读者的模式并将数据从作者的模式转换到读者的模式来解决差异。 Avro规范确切地定义了这种解析的工作原理,如图所示。

使用Avro,向前兼容性意味着您可以将新版本的架构作为编写器,并将旧版本的架构作为读者。相反,向后兼容意味着你可以有一个作为读者的新版本的模式和作为作者的旧版本。

数据流类型

数据可以通过多种方式从一个流程流向另一个流程。

数据库中的数据流

在数据库中,写入数据库的过程对数据进行编码,从数据库读取的过程对数据进行解码。一般来说,几个不同的进程同时访问数据库是很常见的。这些进程可能是几个不同的应用程序或服务,或者它们可能只是几个相同服务的实例(为了可扩展性或容错性而并行运行)。无论哪种方式,在应用程序发生变化的环境中,访问数据库的某些进程可能会运行较新的代码,有些进程可能会运行较旧的代码,例如,因为新版本当前正在部署在滚动升级,所以有些实例已经更新,而其他实例尚未更新。

这意味着数据库中的一个值可能会被更新版本的代码写入,然后被仍旧运行的旧版本的代码读取。因此,数据库也经常需要向前兼容。

数据库通常允许任何时候更新任何值。这意味着在一个单一的数据库中,可能有一些值是五毫秒前写的,而一些值是五年前写的。

服务中的数据流

Web以这种方式工作:客户(Web浏览器)向Web服务器发出请求,使GET请求下载HTML,CSS,JavaScript,图像等,并向POST请求提交数据到服务器。 API包含一组标准的协议和数据格式(HTTP,URL,SSL/TLS,HTML等)。

Web浏览器不是唯一的客户端类型。例如,在移动设备或桌面计算机上运行的本地应用程序也可以向服务器发出网络请求,并且在Web浏览器内运行的客户端JavaScript应用程序可以使用XMLHttpRequest成为HTTP客户端(该技术被称为Ajax )。在这种情况下,服务器的响应通常不是用于显示给人的HTML,而是用于便于客户端应用程序代码(如JSON)进一步处理的编码数据。尽管HTTP可能被用作传输协议,但顶层实现的API是特定于应用程序
的,客户端和服务器需要就该API的细节达成一致。

在某些方面,服务类似于数据库:它们通常允许客户端提交和查询数据。但是,虽然数据库允许使用我们在第2章 中讨论的查询语言进行任意查询,但是服务公开了一个特定于应用程序的API,它只允许由服务的业务逻辑(应用程序代码)预定的输入和输出。这种限制提供了一定程度的封装:服务可以对客户可以做什么和不可以做什么施加细粒度的限制。

REST不是一个协议,而是一个基于HTTP原则的设计哲学。它强调简单的数据格式,使用URL来标识资源,并使用HTTP功能进行缓存控制,身份验证和内容类型协商。与SOAP相比,REST已经越来越受欢迎,至少在跨组织服务集成的背景下,并经常与微服务相关。根据REST原则设计的API称为RESTful。

RPC模型试图向远程网络服务发出请求,看起来与在同一进程中调用编程语言中的函数或方法相同(这种抽象称为位置透明)。

消息传递的数据流

RPC和数据库之间的异步消息传递系统。它们与RPC类似,因为客户端的请求(通常称为消息)以低延迟传送到另一个进程。它们与数据库类似,不是通过直接的网络连接发送消息,而是通过称为消息代理(也称为消息队列或面向消息的中间件)的中介来临时存储消息。

与直接RPC相比,使用消息代理有几个优点:

  • 如果收件人不可用或过载,可以充当缓冲区,从而提高系统的可靠性。
  • 它可以自动将消息重新发送到已经崩溃的进程,从而防止消息丢失。
  • 避免发件人需要知道收件人的IP地址和端口号(这在虚拟机经常出入的云部署中特别有
    用)。
  • 它允许将一条消息发送给多个收件人。
  • 将发件人与收件人逻辑分离(发件人只是发布邮件,不关心使用者)。

原文地址:https://www.cnblogs.com/Ryan16231112/p/12255644.html

时间: 2024-10-11 17:08:44

【设计理念】编码与演化的相关文章

二进制转换、字符编码的演化、Python里使用的编码、浮点数、浮点数的精确度问题

二进制转换 二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二",由18世纪德国数理哲学大师莱布尼兹发现.当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中的二进制则是一个非常微小的开关,用"开"来表示1,"关"来表示0. 古时候敌人来了,如何通信呢? ①派人跑着去通知,速度太慢,等人回来,仗也打完了.

字符编码的演化

GB2312又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆.新加坡等地也使用此编码.共7445个图形字符,其中汉字占6763个. 1995年发布GBK1.0,gbk编码能够用来同时表示繁体字和简体字,该编码标准兼容GB2312,共收录汉字21003个,同时包含中日韩文字里的所有汉字. 2000年发布GB18030,是对GBK编码的扩充,覆盖中文.日文.朝鲜语和中国少数民族文字,其中收录27484个汉字.兼容GBK和GB2312字符集. BIG5编码:台湾地区繁体中文标准字符集

python 第二章 二进制运算、字符编码、数据类型

>>> len(s.ljust(50,'*'))50>>> 1.二进制转换: bin(342) '0b101010110' 2.ASCII码与二进制: 每一个ASCII码都是用8位表示,ASCII码一共有255个.每一位0或者1所占的空间单位为bit(比特),这是计算机中最小的表示单位,8位表示一个字节. 8bit = 1bytes(字节),最小的存储单位,1bytes缩写为1B 1KB = 1024B 1MB = 1024KB 1GB = 1024MB 1TB = 1

字符集和字符编码

1. 概述 现在的编程语言对字符串的处理一般封装比较好,所以平时编写代码,很少要自己考虑字符编码问题.以前学习xml时,由于xml的存储涉及到编码格式,查过一些资料,知道一些概念,GB2312.Unicode.Utf-8.Utf-16.UCS-2等,但这些概念之间什么关系,仍然一知半解.最近要做国际化,需要把不支持Unicode的程序升级为Unicode,借着这个机会,把其中的知识梳理了一遍,对字符编码的理解算更系统化了,在此总结一下. 2. 字符集和字符编码 首先明确两个概念,"字符集&quo

CSS 设计理念

今天整理CSS2.1的规范,发现这个,分享给大家. CSS2.1 作为 CSS2 和 CSS1 的后序版本,基于一下一组设计理念: 向前和向后兼容.CSS2.1 的用户代理能够理解 CSS1 的样式表. CSS1 的用户代理能够读取 CSS2.1 的样式表,并且丢弃他们不能理解的部分.同时,对于不支持 CSS 的用户代理可以显示样式增强的文档.当然通过 CSS 增强的样式将不被渲染,但所有的内容可以被表现. 作为结构化文档的补充.样式表补充结构化文档(例如,HTML 和 XML应用程序),为标记

【转】使用 WebGL 进行 3D 开发,第 2 部分: 使用 WebGL 库以更少的编码做更多的事情

转自HTML5开发社区 使用 WebGL 进行 3D 开发,第 1 部分: WebGL 简介使用 WebGL 进行 3D 开发,第 2 部分: 使用 WebGL 库以更少的编码做更多的事情使用 WebGL 进行 3D 开发,第 3 部分: 添加用户交互 WebGL API 让 JavaScript 开发人员能够直接利用如今的 PC 及移动设备硬件中强大的内置 3D 图形加速功能.现代浏览器透明地支持 WebGL,它使人们可以为主流 Web 用户创建高性能的 3D 游戏.应用程序以及 3D 增强的

ActiveReports 9 新功能:创新的报表分层设计理念

原文:ActiveReports 9 新功能:创新的报表分层设计理念 在最新发布的ActiveReports 9报表控件中添加了多项新功能,以帮助你在更短的时间里创建外观绚丽.功能强大的报表系统,本文将重点介绍创新的报表分层设计理念,对报表内容进行分组管理与设计,易于实现报表套打等功能,主要内容如下: (一)什么是报表层 (二)为什么要使用报表层 (三)报表层的其他优点 (一)什么是报表层 在ActiveReports 9 中首创提出报表层的设计理念,报表分层设计是对报表中不同控件进行分组管理和

字符编码的故事(转)

原文出自:   http://www.cnblogs.com/yjf512/archive/2012/04/21/2461084.html 字符是什么 字符是什么?就是有意义的图形,比如a,中等.在不同的国家代表不同的意思. 但是在计算机世界中只有0和1,好了,如何用0和1将这些字符表示出来呢?这就是编码存在的意义. 编码一点也不高深,就是一个计算机的01和字符ab的简单映射. 于是故事开始了... 很久很久以前,计算机世界只有美国人.美国人的文字造诣很低的,他们的所有文字就只有26个字母,甚至

(8)java基础知识-字符编码

字符编码 将各种文字.图形.标点.数字整合在一个集合叫做字符集. 把这些字符集按照不用规则进行编码就形成了不同的字符编码. 如 你 用显微镜把盘片放大,会看见盘片表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化:凸起的地方代表数字1,凹的地方代表数字0.硬盘只能用0和1 来表示所有文字.图片等信息.那么字母”A”在硬盘上是如何存储的呢?可能小张计算机存储字母”A”是1100001,而小王存储字母”A”是 11000010,这样双方交换信息时就会误解.比如小张把1100001发送给小王,小王并