This commit is contained in:
keming 2020-10-22 00:11:21 +08:00
parent 726784be63
commit b3489c954a

16
ch4.md
View File

@ -11,13 +11,13 @@
[TOC]
应用程序不可避免地随时间而变化。新产品的推出,对需求的深入理解,或者商业环境的变化,总会伴随着**功能feature**的增增改改。[第一章](ch1.md)介绍了[**可演化性(evolvability)**](ch1.md#可演化性:拥抱变化)的概念:应该尽力构建能灵活适应变化的系统(参阅“[可演化性:拥抱变化]()”)。
应用程序不可避免地随时间而变化。新产品的推出,对需求的深入理解,或者商业环境的变化,总会伴随着**功能feature** 的增增改改。[第一章](ch1.md)介绍了[**可演化性(evolvability)**](ch1.md#可演化性:拥抱变化)的概念:应该尽力构建能灵活适应变化的系统(参阅“[可演化性:拥抱变化]()”)。
在大多数情况下,修改应用程序的功能也意味着需要更改其存储的数据:可能需要使用新的字段或记录类型,或者以新方式展示现有数据。
我们在[第二章](ch2.md)讨论的数据模型有不同的方法来应对这种变化。关系数据库通常假定数据库中的所有数据都遵循一个模式:尽管可以更改该模式(通过模式迁移,即`ALTER`语句),但是在任何时间点都有且仅有一个正确的模式。相比之下,**读时模式schema-on-read**(或 **无模式schemaless**)数据库不会强制一个模式,因此数据库可以包含在不同时间写入的新老数据格式的混合(参阅 “文档模型中的模式灵活性” )。
当数据**格式format**或**模式schema**发生变化时,通常需要对应用程序代码进行相应的更改(例如,为记录添加新字段,然后修改程序开始读写该字段)。但在大型应用程序中,代码变更通常不会立即完成:
当数据**格式format** 或**模式schema** 发生变化时,通常需要对应用程序代码进行相应的更改(例如,为记录添加新字段,然后修改程序开始读写该字段)。但在大型应用程序中,代码变更通常不会立即完成:
* 对于 **服务端server-side** 应用程序,可能需要执行 **滚动升级 rolling upgrade** (也称为 **阶段发布staged rollout** ),一次将新版本部署到少数几个节点,检查新版本是否运行正常,然后逐渐部完所有的节点。这样无需中断服务即可部署新版本,为频繁发布提供了可行性,从而带来更好的可演化性。
* 对于 **客户端client-side** 应用程序,升不升级就要看用户的心情了。用户可能相当长一段时间里都不会去升级软件。
@ -191,7 +191,7 @@ Thrift有一个专用的列表数据类型它使用列表元素的数据类
Apache Avro 【20】是另一种二进制编码格式与Protocol Buffers和Thrift有趣的不同。 它是作为Hadoop的一个子项目在2009年开始的因为Thrift不适合Hadoop的用例【21】。
Avro也使用模式来指定正在编码的数据的结构。 它有两种模式语言一种Avro IDL用于人工编辑一种基于JSON更易于机器读取。
Avro也使用模式来指定正在编码的数据的结构。 它有两种模式语言一种Avro IDL用于人工编辑一种基于JSON更易于机器读取。
我们用Avro IDL编写的示例模式可能如下所示
@ -225,7 +225,7 @@ record Person {
**图4-5 使用Avro编码的记录**
为了解析二进制数据,您按照它们出现在架构中的顺序遍历这些字段,并使用架构来告诉您每个字段的数据类型。这意味着如果读取数据的代码使用与写入数据的代码完全相同的模式,则只能正确解码二进制数据。阅读器和作者之间的模式不匹配意味着错误地解码数据。
为了解析二进制数据,您按照它们出现在架构中的顺序遍历这些字段,并使用架构来告诉您每个字段的数据类型。这意味着如果读取数据的代码使用与写入数据的代码完全相同的模式,则只能正确解码二进制数据。读者和作者之间的模式不匹配意味着错误地解码数据。
那么Avro如何支持模式演变呢
@ -300,7 +300,7 @@ Avro为静态类型编程语言提供了可选的代码生成功能但是它
正如我们所看到的Protocol BuffersThrift和Avro都使用模式来描述二进制编码格式。他们的模式语言比XML模式或者JSON模式简单得多它支持更详细的验证规则例如“该字段的字符串值必须与该正则表达式匹配”或“该字段的整数值必须在0和100之间“。由于Protocol BuffersThrift和Avro实现起来更简单使用起来也更简单所以它们已经发展到支持相当广泛的编程语言。
这些编码所基于的想法绝不是新的。例如它们与ASN.1有很多相似之处它是1984年首次被标准化的模式定义语言【27】。它被用来定义各种网络协议其二进制编码DER仍然被用于编码SSL证书X.509例如【28】。 ASN.1支持使用标签号码的模式演进类似于Protocol Buf-fers和Thrift 【29】。然而这也是非常复杂和严重的文件记录所以ASN.1可能不是新应用程序的好选择。
这些编码所基于的想法绝不是新的。例如它们与ASN.1有很多相似之处它是1984年首次被标准化的模式定义语言【27】。它被用来定义各种网络协议其二进制编码DER仍然被用于编码SSL证书X.509例如【28】。 ASN.1支持使用标签号码的模式演进类似于Protocol Buffers和Thrift 【29】。然而这也是非常复杂和严重的文件记录所以ASN.1可能不是新应用程序的好选择。
许多数据系统也为其数据实现某种专有的二进制编码。例如大多数关系数据库都有一个网络协议您可以通过该协议向数据库发送查询并获取响应。这些协议通常特定于特定的数据库并且数据库供应商提供将来自数据库的网络协议的响应解码为内存数据结构的驱动程序例如使用ODBC或JDBC API
@ -382,7 +382,7 @@ Web浏览器不是唯一的客户端类型。例如在移动设备或桌面
此外服务器本身可以是另一个服务的客户端例如典型的Web应用服务器充当数据库的客户端。这种方法通常用于将大型应用程序按照功能区域分解为较小的服务这样当一个服务需要来自另一个服务的某些功能或数据时就会向另一个服务发出请求。这种构建应用程序的方式传统上被称为**面向服务的体系结构service-oriented architectureSOA**,最近被改进和更名为**微服务架构**【31,32】。
在某些方面,服务类似于数据库:它们通常允许客户端提交和查询数据。但是,虽然数据库允许使用我们在第2章 中讨论的查询语言进行任意查询但是服务公开了一个特定于应用程序的API它只允许由服务的业务逻辑应用程序代码预定的输入和输出【33】。这种限制提供了一定程度的封装服务可以对客户可以做什么和不可以做什么施加细粒度的限制。
在某些方面,服务类似于数据库:它们通常允许客户端提交和查询数据。但是,虽然数据库允许使用我们在[第2章](./ch2.md)中讨论的查询语言进行任意查询但是服务公开了一个特定于应用程序的API它只允许由服务的业务逻辑应用程序代码预定的输入和输出【33】。这种限制提供了一定程度的封装服务可以对客户可以做什么和不可以做什么施加细粒度的限制。
面向服务/微服务架构的一个关键设计目标是通过使服务独立部署和演化来使应用程序更易于更改和维护。例如每个服务应该由一个团队拥有并且该团队应该能够经常发布新版本的服务而不必与其他团队协调。换句话说我们应该期望服务器和客户端的旧版本和新版本同时运行因此服务器和客户端使用的数据编码必须在不同版本的服务API之间兼容——正是我们所做的本章一直在谈论。
@ -394,7 +394,7 @@ Web浏览器不是唯一的客户端类型。例如在移动设备或桌面
2. 一种服务向同一组织拥有的另一项服务提出请求,这些服务通常位于同一数据中心内,作为面向服务/微型架构的一部分。 (支持这种用例的软件有时被称为 **中间件middleware**
3. 一种服务通过互联网向不同组织所拥有的服务提出请求。这用于不同组织后端系统之间的数据交换。此类别包括由在线服务如信用卡处理系统提供的公共API或用于共享访问用户数据的OAuth。
有两种流行的Web服务方法REST和SOAP。他们在哲学方面几乎是截然相反的往往是各自支持者之间的激烈辩论即使在每个阵营内也有很多争论。 例如,**HATEOAS超媒体作为应用程序状态的引擎**经常引发讨论【35】。
有两种流行的Web服务方法REST和SOAP。他们在哲学方面几乎是截然相反的往往是各自支持者之间的激烈辩论即使在每个阵营内也有很多争论。 例如,**HATEOAS超媒体作为应用程序状态的引擎** 经常引发讨论【35】。
REST不是一个协议而是一个基于HTTP原则的设计哲学【34,35】。它强调简单的数据格式使用URL来标识资源并使用HTTP功能进行缓存控制身份验证和内容类型协商。与SOAP相比REST已经越来越受欢迎至少在跨组织服务集成的背景下【36】并经常与微服务相关[31]。根据REST原则设计的API称为RESTful。
@ -410,7 +410,7 @@ REST风格的API倾向于更简单的方法通常涉及较少的代码生成
#### 远程过程调用RPC的问题
Web服务仅仅是通过网络进行API请求的一系列技术的最新版本其中许多技术受到了大量的炒作但是存在严重的问题。 Enterprise JavaBeansEJB和Java的**远程方法调用RMI**仅限于Java。**分布式组件对象模型DCOM**仅限于Microsoft平台。**公共对象请求代理体系结构CORBA**过于复杂不提供前向或后向兼容性【41】。
Web服务仅仅是通过网络进行API请求的一系列技术的最新版本其中许多技术受到了大量的炒作但是存在严重的问题。 Enterprise JavaBeansEJB和Java的**远程方法调用RMI** 仅限于Java。**分布式组件对象模型DCOM** 仅限于Microsoft平台。**公共对象请求代理体系结构CORBA** 过于复杂不提供前向或后向兼容性【41】。
所有这些都是基于 **远程过程调用RPC** 的思想该过程调用自20世纪70年代以来一直存在【42】。 RPC模型试图向远程网络服务发出请求看起来与在同一进程中调用编程语言中的函数或方法相同这种抽象称为位置透明。尽管RPC起初看起来很方便但这种方法根本上是有缺陷的【43,44】。网络请求与本地函数调用非常不同