【译】在分布式系统中解决,或平衡微服务的复杂度 - part 1

原文标题: Untangling Microservices, or Balancing Complexity in Distributed Systems

原文地址[1]

翻译:祝坤荣

微服务的蜜月期已经结束了。Uber正在将成千记的微服务重构成一个更加可管理的方案[1];Kelsey Hightower正在预测单体架构将是未来[2];Sam Newman甚至声明微服务不应该是第一选择,而应该是最后一个选择[3]。

这是怎么回事?尽管微服务承诺了简单和灵活,为什么这么多的项目变得难以维护?或者难道最终单体架构更好?

在这篇文章中,我想要讨论这些问题。你会看到一些将微服务编程一团分布式大泥球的常见设计问题 - 当然,也会看到如何避免他们。

但最开始,让我们先了解下什么是单体架构。

单体架构

微服务一直是被认为是单体应用代码的解决方案。但是单体应用是不是一个问题呢?根据维基百科的定义[4],一个单体应用是自包含且与其他计算应用独立的。与哪些其他应用独立呢?这不是我们在设计微服务时追求的吗?David Heinemeier Hansson[5]指出了单体应用的缺陷。他

因此,微服务不是“修复”单体应用。微服务需要解决的真正问题是交付业务目标的无力。一般,团队是由于指数级增长的 - 或更糟的不可预测性 - 进行变更的成本才交付不了业务目标的。换一句话说,系统不能满足业务的需要。不可控的变更成本不是单体应用的特性,而是大泥球的特性[6]:

大泥球是杂乱的结构,无序,泥泞,缠在一起的电线和胶带,面条代码的丛林。系统显示出无节制增长,重复,临时修复的明显迹象。系统中混乱的将信息在很多极长链路的系统部分中共享,这表示大部分重要信息都变成了全局的或被重复复制的。

对大泥球的复杂性的修改和进化可以由于多个原因引起:协调众多团队的工作,非功能性需求的冲突,或一个复杂的业务域。无论怎样,我们经常试图将这种复杂问题分解成微服务来解决。

微什么?

文字“微服务”指明了服务的一部分可以被度量并且它的价值应该是最小化的。但微服务到底意味着什么?我们看下一些常见的用法。

微团队

第一个工作在服务上的团队大小。而这个尺度可以按披萨来度量。你没听错。他们说如果工作在服务上的团队可以被2个披萨喂饱, 那么这就是微服务。我发现这很有启发,我曾经做一个项目而团队可以被一个披萨喂饱... 而我敢对任何人说这团大泥球是微服务。

微代码库

另一种广泛使用的方法时基于它的代码库来设计微服务。有些人将这个概念发挥到了极致,将服务的大小限制到了某些确定的代码行数。就是说,可以构成一个微服务的确切代码行数还没被找到。当这个软件架构的圣杯被发现,我们会进入下一个问题 - 构建微服务团建的编辑器宽度是多少?

有个更严重的问题,这个方法一个没那么极端的版本更流行。代码库的大小常被用来决定它是否是一个微服务。

某些时候,这个方法管用。更小的代码库,更小的业务域。因此,这容易理解,实现,发展。而且,更小的代码库不太可能变成一个大泥球 - 如果发生了,也比较容易重构。

不幸的是,前面提到的简单只是一个错觉。当我们开始基于服务本身来评估服务的设计时,我们忽略了系统设计的核心部分。我们忘记了系统自己,服务作为系统的组成

“有很多有用和有启发性的方法来定义一个服务的边界。大小是最不重要的部分。” - Nick Tune

我们开发系统!

我们开发系统,而不是服务的集合。我们使用基于微服务的架构来优化系统的设计,而不是设计独立的服务。无论别人怎么说,微服务不能,也永远不会完全解耦,和独立。 你不能用完全独立的组件来打造系统! 现在我们看下“系统”的定义[7]:

1.一组连接在一起并可一起操作的物件或设备2.一组为了一个特定目的一起使用的计算机设备或程序

服务会与其他服务进行不断交互来形成系统。如果你通过优化服务来设计一个系统,却忽略了他们之间的交互,最终你可能是这样的结局:

这些“微服务”可能自身很简单,但系统却变成了复杂性的地狱!

所以我们如何不只是处理了服务的复杂性,而是也考虑了整个系统的复杂性来进行微服务设计呢?

这是个困难的问题,但幸运的是,在很早以前就有答案。

系统视角的复杂性

四十年前,还没有云计算,没有全球规模的需求,不需要每11.7秒部署一次系统。但工程师仍然需要控制系统复杂度。尽管这些工具与现在不一样,但挑战 - 更重要的是, 解决方案 - 都是类似的,也可以被用于基于微服务设计的系统。

在他的书里,“组合/结构设计”[8],Glenford J. Myers讨论了如何用结构化的过程代码来降低复杂度。在书的第一页,他写到:

关于复杂性的主题中有比简单的尝试最小化程序中一部分的本地复杂度更重要的事。一个更重要的复杂度类型是全局复杂度:程序或系统的全局结构的复杂度(比如,程序主要部分的关联或独立程度)。

在我们的语境里,本地复杂度就是每个独立微服务的复杂度,全局复杂度是整个系统的复杂度。本地复杂度依赖于一个服务的实现部分;全局复杂度是被服务间的交互和依赖所定义的。

所以哪一个复杂度更重要 - 本地还是全局?让我们看看当只有一种复杂度被关心时的情况。

要将全局复杂度降到最小实际非常简单。我们只要评估下任何系统组件间的交互 - 即,将所有功能在一个单体服务中实现。就像我们早前看到的,这个策略在某些特定场景是有用的。而在其他场景,它会导致恐怖的大泥球 - 可能是最高级别的本地复杂度。

从另一方面,我们很清楚当你只优化本地复杂度而忽视系统全局复杂度时会发生什么 - 更大的分布式大泥团。

因此,当我们只关注复杂度的某一种,选哪一个并不重要。在一个复杂分布式系统,对向的复杂度都会暴涨。所以,我们不能只优化一个。相反,我们要平衡本地和全局复杂度。

有意思的是,在“组合/结构设计”一书中描述的复杂度平衡不仅与分布式系统有关,其也提供了如何设计微服务的见解。

翻译待续 ...

#引用索引

1.Gergely Orosz’s tweet on Uber[2]2.Monoliths are the future[3]3.Microservices guru warns devs that trendy architecture shouldn’t be the default for every app, but ‘a last resort’[4]4.Monolithic Application(Wikipedia)[5]5.The Majestic Monolith - DHH[6]6.Big Ball of Mud(Wikipedia)[7]7.Definition of a System[8]8.Composite/Structures Design - book by Glenford J. Myers[9]


本文来自祝坤荣(时序)的微信公众号「麦芽面包,id「darkjune_think」 开发者/科幻爱好者/硬核主机玩家/业余翻译

微博:祝坤荣

B站: https://space.bilibili.com/23185593/

交流Email: zhukunrong@yeah.net[10]

转载请注明。

References

[1] 原文地址: https://vladikk.com/2020/04/09/untangling-microservices/
[2] Gergely Orosz’s tweet on Uber: https://twitter.com/GergelyOrosz/status/1247132806041546754
[3] Monoliths are the future: https://changelog.com/posts/monoliths-are-the-future
[4] Microservices guru warns devs that trendy architecture shouldn’t be the default for every app, but ‘a last resort’: https://www.theregister.co.uk/2020/03/04/microservices_last_resort/
[5] Monolithic Application(Wikipedia): https://en.wikipedia.org/wiki/Monolithic_application
[6] The Majestic Monolith - DHH: https://m.signalvnoise.com/the-majestic-monolith/
[7] Big Ball of Mud(Wikipedia): https://en.wikipedia.org/wiki/Big_ball_of_mud
[8] Definition of a System: https://dictionary.cambridge.org/dictionary/english/system
[9] Composite/Structures Design - book by Glenford J. Myers: https://www.amazon.com/Composite-Structured-Design-Glenford-Myers/dp/0442805845
[10] zhukunrong@yeah.net: mailto:zhukunrong@yeah.net

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
!!注意:全文有99M,由于上传文件不得超过60M,所以分成两个压缩文件,这是part1.part2在以下网页: http://download.csdn.net/detail/hellowjl1/4682120 在本书,作者给出设计,实现和分析分布式算法的蓝图。本书适合学生、程序员、系统分析员和研究人员等不同类型的读者。本书包括这个领域最重要的算法和不可能解.而且都采用简单的自动机理论进行论述。对所有算法的正确性都给予证明.并且根据精确定义的复杂度标准分析算法的复杂度。其涉及的问题包括资源分配、通信、分布式处理器之间的一致性、数据一致性、死锁检测、领导者进程的选取、全局快照等。    本书的内容按照系统模型组织,首先是根据定时模型.然后在定时模型内再根据进程间的通信机制。不同系统的材料分别独立成章,便于查阅。    本书论述十分严谨,但又很直观.便于读者迅速理解。本书也为读者提供设计新的算法和证明新的不可能解的基本数学工具。而且,它教给读者怎样对分布式系统进行严格的推理 ―包括形式化建模,为它们所需的行为设计精确的指标,证明它们的正确性.并且用实际的度量标准来评价它们的性能。    本书对分布式算法进行全面介绍,包括最为重要的算法和不可能性结果。绝大部分的解都给出了数学证明。这些算法都根据精确定义的复杂度衡量方法进行分析。本书还讲述针对许多典型问题的算法、各类系统模型及其能力。章后提供大量习题并列出了详细的参考文献。    本书可作为高等院校计算机系研究生的教材,尤其适合对计算机理论或体系结构感兴趣的学生学习,还适合分布式设计人员、研究人员及其相关技术人员参考。 出版者的话 专家指导委员会 者序 前言 第1章 引言 1 1.1 相关主题 1 1.2 我们的观点 2 1.3 本书内容综述 3 1.4 参考文献注释 7 1.5 标记 7 第一部分 同步网络算法 第2章 建模i:同步网络模型 10 2.1 同步网络系统 10 2.2 故障 11 2.3 输入和输出 11 2.4 运行 11 2.5 证明方法 12 2.6 复杂度度量 12 2.7 随机化 12 2.8 参考文献注释 13 .第3章 同步环的领导者选择 14 3.1 问题 14 3.2 相同进程的不可能性结果 14 3.3 基本算法 15 3.4 通信复杂度为o(n log n)的算法 17 3.5 非基于比较的算法 19 3.5.1 时间片算法 20 3.5.2 变速算法 20 3.6 基于比较的算法的下界 21 3.7 非基于比较的算法的下界* 25 3.8 参考文献注释 26 3.9 习题 27 第4章 一般同步网络的算法 29 4.1 一般网络的领导者选举 29 4.1.1 问题 29 4.1.2 简单的洪泛算法 29 4.1.3 降低通信复杂度 31 4.2 广度优先搜索 32 4.2.1 问题 32 4.2.2 基本的广度优先搜索算法 33 4.2.3 应用 34 4.3 最短路径 35 4.4 最小生成树 36 4.4.1 问题 36 4.4.2 基本定理 36 4.4.3 算法 37 4.5 最大独立集 39 4.5.1 问题 40 4.5.2 随机化算法 40 4.5.3 分析* 42 4.6 参考文献注释 43 4.7 习题 43 第5章 链路故障时的分布式一致性 46 5.1 协同攻击问题―确定性版本 46 5.2 协同攻击问题―随机化版本 48 5.2.1 形式化模型 49 5.2.2 算法 49 5.2.3 不一致的下限 52 5.3 参考文献注释 54 5.4 习题 54 第6章 进程故障下的分布式一致性 56 6.1 问题 56 6.2 针对停止故障的算法 58 6.2.1 基本算法 58 6.2.2 减少通信 59 6.2.3 指数信息收集算法 61 6.2.4 带鉴别的byzantine一致性 66 6.3 针对byzantine故障的算法 66 6.3.1 举例 66 6.3.2 byzantine一致性问题的eig算法 68 6.3.3 使用二元byzantine一致的一般 的byzantine一致性问题 71 6.3.4 减少通信开销 72 6.4 byzantine一致性问题进程的个数 74 6.5 一般图的byzantine一致性问题 78 6.6 弱byzantine一致性 81 6.7 有停止故障时的轮数 82 6.8 参考文献注释 88 6.9 习题 89 第7章 更多的一致性问题 93 7.1 k一致性问题 93 7.1.1 问题 93 7.1.2 算法 93 7.1.3 下界* 95 7.2 近似一致性 102 7.3 提交问题 105 7.3.1 问题 105 7.3.2 两阶段提交 106 7.3.3 三阶段提交 107 7.3.4 消息数的下界 109 7.4 参考文献注释 111 7.5 习题 111 第二部分 异步算法 第8章 建模ii:异步系统模型 114 8.1 输入/输出自动机 114 8.2 自动机的操作 118 8.2.1 合成 118 8.2.2 隐藏 121 8.3 公平性 121 8.4 问题的输入和输出 123 8.5 属性与证明方法 124 8.5.1 不变式断言 124 8.5.2 轨迹属性 124 8.5.3 安全与活性属性 125 8.5.4 合成推理 126 8.5.5 层次化证明 128 8.6 复杂度衡量 130 8.7 不可区分运行 131 8.8 随机化 131 8.9 参考文献注释 131 8.10 习题 132 第二部分a 异步共享存储器算法 第9章 建模iii:异步共享存储器模型 136 9.1 共享存储器系统 136 9.2 环境模型 138 9.3 不可区分状态 140 9.4 共享变量类型 140 9.5 复杂度衡量 144 9.6 故障 144 9.7 随机化 145 9.8 参考文献注释 145 9.9 习题 145 第10章 互斥 146 10.1 异步共享存储器模型 146 10.2 问题 148 10.3 dijkstra的互斥算法 151 10.3.1 算法 151 10.3.2 正确性证明 154 10.3.3 互斥条件的一个断言证明 156 10.3.4 运行时间 157 10.4 互斥算法的更强条件 158 10.5 锁定权互斥算法 159 10.5.1 双进程算法 159 10.5.2 n进程算法 163 10.5.3 锦标赛算法 167 10.6 使用单写者共享存储器的算法 170 10.7 bakery算法 171 10.8 寄存器数量的下界 173 10.8.1 基本事实 174 10.8.2 单写者共享变量 175 10.8.3 多写者共享变量 175 10.9 使用读-改-写共享变量的互斥 179 10.9.1 基本问题 179 10.9.2 有界绕过次数 180 10.9.3 锁定权 185 10.9.4 模拟证明 187 10.10 参考文献注释 189 10.11 习题 190 第11章 资源分配 194 11.1 问题 194 11.1.1 显式资源说明和互斥说明 194 11.1.2 资源分配问题 195 11.1.3 哲学家用餐问题 196 11.1.4 解法的受限形式 197 11.2 对称哲学家用餐算法的不存在性 197 11.3 右-左哲学家用餐算法 199 11.3.1 等待链 199 11.3.2 基本算法 200 11.3.3 扩展 202 11.4 哲学家用餐随机算法* 204 11.4.1 算法* 205 11.4.2 正确性* 207 11.5 参考文献注释 212 11.6 习题 213 第12章 一致性 215 12.1 问题 215 12.2 使用读/写共享存储器的一致性 217 12.2.1 限制 218 12.2.2 术语 218 12.2.3 双价初始化 218 12.2.4 无等待终止的不可能性 219 12.2.5 单故障终止的不可能性结果 221 12.3 读/改/写共享存储器上的一致性 问题 223 12.4 其他共享存储器类型 224 12.5 异步共享存储器系统的可计算性* 224 12.6 参考文献注释 225 12.7 习题 226 第13章 原子对象 229 13.1 定义和基本结论 229 13.1.1 原子对象的定义 229 13.1.2 规范无等待原子对象自动机 235 13.1.3 原子对象的合成 237 13.1.4 原子对象和共享变量 237 13.1.5 显示原子性的一个充分条件 241 13.2 用读/写变量实现读-改-写原子对象 242 13.3 共享存储器的原子快照 243 13.3.1 问题 243 13.3.2 带无界变量的一个算法 244 13.3.3 带有界变量的一个算法* 247 13.4 读/写原子对象 250 13.4.1 问题 250 13.4.2 证明原子性的其他引理 250 13.4.3 带无界变量的一个算法 251 13.4.4 两个写者的有界算法 254 13.4.5 使用快照的算法 258 13.5 参考文献注释 259 13.6 习题 260 第二部分b 异步网络算法 第14章 建模iv:异步网络模型 264 14.1 发送/接收系统 264 14.1.1 进程 264 14.1.2 发送/接收通道 264 14.1.3 异步发送/接收系统 268 14.1.4 使用可靠fifo通道的发送/ 接收系统的特征 268 14.1.5 复杂度度量 269 14.2 广播系统 269 14.2.1 进程 269 14.2.2 广播通道 270 14.2.3 异步广播系统 270 14.2.4 采用可靠广播通道的广播系统 的特征 270 14.2.5 复杂度度量 271 14.3 多播系统 271 14.3.1 进程 271 14.3.2 多播通道 271 14.3.3 异步多播系统 272 14.4 参考文献注释 272 14.5 习题 272 第15章 基本异步网络算法 274 15.1 环的领导者选举 274 15.1.1 lcr算法 275 15.1.2 hs算法 278 15.1.3 peterson leader算法 278 15.1.4 通信复杂度的下界 281 15.2 任意网络的领导者选举 286 15.3 生成树的构造、广播和敛播 287 15.4 广度优先搜索和最短路径 290 15.5 最小生成树 295 15.5.1 问题描述 295 15.5.2 同步算法:回顾 296 15.5.3 ghs算法:概要 296 15.5.4 更详细的算法 297 15.5.5 特殊消息 299 15.5.6 复杂度分析 301 15.5.7 ghs算法的正确性证明 301 15.5.8 简单“同步”策略 302 15.5.9 应用到领导者选举算法 302 15.6 参考文献注释 303 15.7 习题 303 第16章 同步器 307 16.1 问题 307 16.2 局部同步器 309 16.3 安全同步器 313 16.3.1 前端自动机 314 16.3.2 通道自动机 315 16.3.3 安全同步器 315 16.3.4 正确性 315 16.4 安全同步器的实现 316 16.4.1 同步器alpha 316 16.4.2 同步器beta 317 16.4.3 同步器gamma 317 16.5 应用 320 16.5.1 领导者选举 321 16.5.2 深度优先搜索 321 16.5.3 最短路径 321 16.5.4 广播与确认 321 16.5.5 最大独立集 321 16.6 时间下界 321 16.7 参考文献注释 324 16.8 习题 324 第17章 共享存储器与网络 326 17.1 从共享存储器模型到网络模型 的转换 326 17.1.1 问题 326 17.1.2 无故障时的策略 327 17.1.3 容忍进程故障的算法 332 17.1.4 对于n/2故障的不可能性结果 335 17.2 从网络模型转换到共享存储器模型 336 17.2.1 发送/接收系统 336 17.2.2 广播系统 338 17.2.3 异步网络一致性的不可能性 338 17.3 参考文献注释 339 17.4 习题 339 第18章 逻辑时间 341 18.1 异步网络的逻辑时间 341 18.1.1 发送/接收系统 341 18.1.2 广播系统 343 18.2 使用逻辑时间的异步算法 344 18.2.1 时钟的走动 344 18.2.2 延迟未来事件 345 18.3 应用 346 18.3.1 银行系统 346 18.3.2 全局快照 348 18.3.3 模拟一台单状态机器 349 18.4 从实际时间算法到逻辑时间算法 的变换* 352 18.5 参考文献注释 352 18.6 习题 353 第19章 一致全局快照和稳定属性检测 355 19.1 发散算法的终止检测 355 19.1.1 问题 355 19.1.2 dijkstrascholten算法 356 19.2 一致全局快照 360 19.2.1 问题 360 19.2.2 chandylamport算法 361 19.2.3 应用 364 19.3 参考文献注释 366 19.4 习题 367 第20章 网络资源分配 369 20.1 互斥 369 20.1.1 问题 369 20.1.2 模拟共享存储器 370 20.1.3 循环令牌算法 370 20.1.4 基于逻辑时间的算法 372 20.1.5 logicaltimeme算法的改进 374 20.2 通用资源分配 376 20.2.1 问题 376 20.2.2 着色算法 377 20.2.3 基于逻辑时间的算法 377 20.2.4 无环有向图算法 378 20.2.5 哲学家饮水* 379 20.3 参考文献注释 383 20.4 习题 383 第21章 带进程故障的异步网络计算 386 21.1 网络模型 386 21.2 有故障环境一致性的不可能性 387 21.3 随机算法 388 21.4 故障检测器 390 21.5 k一致性 393 21.6 近似一致性 394 21.7 异步网络的计算能力* 395 21.8 参考文献注释 396 21.9 习题 396 第22章 数据链路协议 399 22.1 问题阐述 399 22.2 stenning协议 400 22.3 位变换协议 403 22.4 可重排序的有界标志协议 406 22.4.1 关于重排序和复制的不可能 性结论 407 22.4.2 容许丢失和重排序的有界标 志协议 408 22.4.3 不存在容许消息丢失和重排序 的高效协议 412 22.5 容许进程崩溃 414 22.5.1 简单的不可能性结论 415 22.5.2 更复杂的不可能性结论 415 22.5.3 实用的协议 418 22.6 参考文献注释 423 22.7 习题 423 第三部分 部分同步算法 第23章 建模v: 部分同步系统模型 428 23.1 mmt 定时自动机 428 23.1.1 基本定义 428 23.1.2 操作 432 23.2 通用定时自动机 434 23.2.1 基本定义 434 23.2.2 将mmt自动机转化为通用定时 自动机 437 23.2.3 操作 440 23.3 属性和证明方法 441 23.3.1 不变式 441 23.3.2 定时轨迹属性 443 23.3.3 模拟 444 23.4 构造共享存储器和网络系统的模型 449 23.4.1 共享存储器系统 449 23.4.2 网络 449 23.5 参考文献注释 449 23.6 习题 450 第24章 部分同步的互斥 452 24.1 问题 452 24.2 单寄存器算法 453 24.3 对时间故障的回复性 459 24.4 不可能性结果 461 24.4.1 时间下界 462 24.4.2 最终时间界限的不可能性结果* 462 24.5 参考文献注释 463 24.6 习题 463 第25章 部分同步的一致性 466 25.1 问题 466 25.2 故障检测器 467 25.3 基本结论 468 25.3.1 上界 468 25.3.2 下界 469 25.4 有效算法 470 25.4.1 算法 471 25.4.2 安全属性 472 25.4.3 活性和复杂度 473 25.5 涉及时间不确定性的下界* 475 25.6 其他结果* 480 25.6.1 同步进程、异步通道* 480 25.6.2 异步进程、同步通道* 481 25.6.3 最终时间界限* 481 25.7 小结 483 25.8 参考文献注释 483 25.9 习题 483 参考文献 486 索引 512

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值