写点什么

分块云计算

  • 2009 年 6 月 29 日
  • 本文字数:6188 字

    阅读完需:约 20 分钟

在我的眼中,过去数年间的多股潮流,都指向同一个方向,现在该到将它们总结归纳的时候了。这篇文章没有什么新奇观点,只是将我的思考与观察做一个概括。我不自禁要将心中的图景描绘出来(即便这幅画的背景全由我的痛苦教训涂抹而成)。这就开始吧。

多年忽视分块

即使过了 16 年,我依然清楚记得 [Booch OOAD] 书中讨论如何使用分层与分块(有的读者可能更偏好"模块"这个同义词)。那时候我开班讲授一门面向对象分析与设计的课程,这本书是教材。我感觉讨论分层很容易,因为当时接触甚多(后来仍然深受影响,下一节会谈及),但要讨论分块就有点难。

在我参与的实际项目中,我们确实一直采取分块的做法,但讲授的时候很难用短小的例子示范分块。而且就我记忆所及,我们采取分块只是出于技术上的限制,并不像分层那样是自然而然地发生的。.

分块没能“物尽其用”的感觉一直伴随着我,我也就听之任之。

滥用分层

2001 年写第一本书 [Nilsson NED] 的时候,我对分层的盲目溺爱到达顶峰。图 1 的分层示意图已经是简化过的版本。

图 1. 过去的典型分层(简化版本)

图 1 可见,中间层包括了 Façade 层、业务逻辑层和数据访问层。在数据层还有公共存储过程(sproc)层、私有存储过程层,有时候数据表之上还有视图层……(UI 部分也是分层的,可想而知……)。

我把这种分层方案称为我的“默认架构”,顾名思义,我每次着手新项目都以此作为出发点。当然具体的架构形态随着时间会有所变化,但重点是我先入为主地认为项目都离不开这种严格的分层方案。

我观察到:

  • 当数据库 Schema、视图、私有存储过程、公共存储过程、数据访问层,一层层手工编写下来((为了保证一切都恰如意料,比如性能)),很多时候,就没有多少时间花在业务层上了。于是业务层往往非常薄,不外乎做些左手交右手的工作,捎带若干占位用的注释。
  • 由图 1 可见,数据存储受到重重防卫,从 UI 到数据存储经过的保护层不是一般多。然而在多数情况下,由于使用 Recordset 模式完成从数据库到 UI 的数据传输,造成数据库 Schema 严重暴露。而当 UI 完成修改回传数据的时候,差不多就是直接写入到数据库了……所谓保护不过如此。
  • 引入每一层的依据是“有比没有好”,而不是因为“证明有需要”。违反 YAGNI 原则的绝佳例子,对吧?

如今,我的典型初始分层方案与以往截然不同。一开始只用一个领域模型层,先把握住我们真正关心的部分,也就是业务问题的解决方案。

然后当有必要的时候才增加层次,比如需要用户界面的时候才会加上 UI 层。只要合适,UI 层甚至可以直接叠在领域模型之上。要是不合适,再考虑别的需要。

接下来,如果我们希望把领域模型持久化到关系数据库,才把这部分需要放入场景中加以考虑。通常用一个对象 / 关系映射就能解决得很好,大约能自动解决 80% 的领域模型到数据库的数据映射需求。请看图 2。

图 2. 时下典型分层一例

我还尝试令数据库 Schema 成为领域模型反映出来的“结果”,自动生成数据库 Schema。这样做意味着避免了大量繁重的工作,让我们有时间投入到真正关心的部分——领域模型本身。(同样的做法还可以用到 UI 上。)

如此一来,我不用再拘泥严格的分层方案,转而把精力集中于寻找恰当的分块。又由于整个解决方案被分为若干小块,从而每一个分块的分层形式可以更加灵活,因为规模更小了。

按技术拆分团队

写上面一节的时候,我想起了 2005 年在挪威 Lillehammer 举行的软件架构研讨会 [Fowler LayeringPrinciples]。当时我们在会上讨论如何把大的团队拆分成若干小团队。

无论那次会议之前或之后,我都有拆分团队的经验,多次拆分中既有按技术拆分的,也有按功能拆分的。我尤其记得一个项目,对其中一名团队成员来说,按功能拆分是失败的,因为他没有什么经验,所以几乎每一个方面他都不得不苦苦挣扎。.

在另一个项目中,按技术拆分看起来非常成功,不过那个项目的成员都很有经验。即使在这个成功项目里,也有很多情况如果按功能拆分会取得更高的效率。比如跨单元的小改动,牵涉到的人可以更少。

总而言之,我偏向按功能拆分团队。每个人肯定有自己特别擅长的部分,但如果不用协调及等待其他人完成相应的工作,那么大部分工作都可以更快地完成。

企业领域模型

前些年很流行建立整个企业“一统天下”的数据模型。背后的想法是如果一朝找到并描述出这样的数据模型,就能从中创造出巨大的业务价值。于是传达给业务人员的是这样的信息:

“现在给我们两年时间不受干扰,到时候我们会交给你一个定义好的模型,你想要的一切都能不费吹灰之力就创造出来。”

依我之见,“企业数据模型”是大大失败了。原因肯定不少,但下面这几点可能在最重要之列:

  • 即便是中等规模的企业,数据模型的规模也过于庞大。
  • 数据模型试图用静态的方法描绘一个动态的目标。而且描绘一个庞大的目标比小的目标要困难得多。
  • 大模型或多或少要作一般化的处理,并因此失去上下文信息。

我个人强烈相信大的任务要一口一口地啃,而上下文是王道。

A 前面说过,我认为建立企业数据模型的尝试常常以失败告终。现在我又发现一种有点讽刺的情形——还有项目几乎在重复同样的尝试,只不过这一次换成了“企业领域模型”。论据没变,我想结果和造成结果的原因也不会变……

公平来说,更常见的情况倒不是真的追逐“企业领域模型”,而是想建立单一的大型领域模型。此外,团队不时发现有需要切分大的领域模型,但又发现不容易找到满意的方案。

无论如何,我都强烈建议当领域模型出现增大迹象的时候,将它分块。还有别忘了模型是有上下文的。

很有趣,我还听闻一些非常大的 SOA 项目采取的第一个步骤就是打算建立一套“企业文档模型”。它会比企业数据 / 领域模型更成功吗?要是打赌的话,我宁愿下注在另一边。

整合数据库

就算有意避免巨型的单一领域模型,把模型隔离成几个部分,每一个部分还是有可能膨胀到相当规模。发生这种情况的时候,往往会发现数据库并没有分块。各个领域模型置于同一个数据库之上,也就是共用一个整合的数据库,见图 3。

图 3. 分块的领域模型,使用整合数据库

把多个领域模型置于单一数据库之上,只是整合数据库的其中一种情形。实际上跟多个独立应用共享同一个数据库是一样的。类似情况可谓屡见不鲜。

很不幸这样的安排给维护造成了极大的负担。任何影响到数据库 Schema 的改动都必须同步修改相应 Schema 的所有消费者。消费者越多,情况越糟。往往造成改动被限制到最低程度,很可能进而导致从代码中榨取的业务价值大大减少。

大胆地说一句,如今在我眼中,整合数据库是一种反模式。啊,总算说出来了,感觉真好。

那么,有什么别的办法呢?我认为领域模型的分块应该一直延续到数据库,让数据库也遵循同样的分块方案。这种与整合数据库 [Fowler IntegrationDatabase] 相反的模式称为单应用数据库 [Fowler ApplicationDatabase],见图 4。

图 4. 分块的领域模型,使用各自的单应用数据库

分块之间的通信是通过领域模型之上的服务完成的,不允许抄捷径直接访问其他领域模型的应用数据库。这意味着可以(也通常会)有效地将不同的应用数据库部署到不同的服务器上(或者部署到云中)。

一般认为报表是整合数据库的优势所在。要是换一种方式去处理报表,可以把它看成一个独立的应用,有着自己的数据存储。数据从其他分块搜集而来。其中一种办法是将每个分块都看作一个提供事件源的应用 [Fowler Events],让那些事件源都吐出报表应用感兴趣的事件就可以了。

顺便一提,上面的讨论令我记起曾经为 ADDDP[Nilsson ADDDP] 写过一段文字 [Nilsson Bricks](不过最终没有放进书里),介绍另一种应用数据库的用法。不过当时写作的重点落在性能,而非可维护性。文中我介绍了如何根据系统不同部分的特点,让系统发挥最大的功效。

再顺便一提,一定要读一读 Greg Young 写的 DDDD 系列文章 [Greg Young],他的精彩作品也可以归到这个主题之下。他建议严格切分读和写,籍此取得非常高的可伸缩性等等成效。

整合的 UI

论点其实差不多,只不过用到 UI 上没有整合数据库 vs. 应用数据库那么有力。与其用一个 UI 套上几个服务,何不让每个服务都有自己的 UI,然后将不同的 UI 用一个 UI 容器框架集成起来?见图 5。

图 5. UI 也分块

这样一来,某个分块的开发者可以全方位地处理问题,从 UI 一直到存储,不必与其它团队同步。对实际生产率的潜在影响是巨大的。

巨型的团队

经常有人向我们求助,抱怨说他们 100 人的大团队没办法达到期望的生产效率。

每一次,我都得到同样的结论。不要那样做!100 名开发者在同一个团队里,太可怕了,失败风险太大了。即使你再加 20 个人!

虽然已经出版了 30 年,读过《人月神话》[Brooks MMM] 的人还是少得出奇。真糟糕。(书名“人月神话”的意思是,向一个进度落后的项目增加更多开发者,只会让它更落后。书里还阐述了很多重要的思想。)

所以,就算退一步说你真的有一个规模庞大的问题要解决,你也真的需要 100 名开发者。请一定要小心谨慎地将大团队分成若干个小规模的、尽可能相互隔离的团队,以便每个团队能够全速运行。

但是当你把大团队分成比如说 100 个新团队的时候,显然不会因此就消灭了复杂性。例子里面分成 10-20 个团队比只有 1 个团队好,并不表示分成 100 个会更好。请注意平衡。

SOA 与松散耦合

说到平衡,两年前我曾经很不理解 SOA 的一些说法,还写了博客帖子 [Nilsson SOA-Qs] 请教答案。

我不理解的其中一点是为什么要极端的细粒度。为什么不用“定界上下文(Bounded Context)” [Evans DDD] 的思维来看待服务呢,为什么需要粒度细到只有一行代码的服务……

Jim Webber 在一篇文章里 [Webber Anemic Service Model] 讨论过这个问题,我认为他说得很有道理。对松散耦合的关注成了唯一的决定因素,以至于忘了搭配上它的好朋友——高内聚,才导致出现令我困惑不解的奇怪说法。

所以,我把前面讨论的分块看作是“做对了的 SOA”。

强迫一种风格

最初我把标题定为“强迫一种信仰”,但又顾虑到 Google 带来的很多人会失望。我在这里谈的风格 / 信仰,是指我们当中有很多人喜欢思考和讨论 TDD、DDD、BDD、模式、重构、干净的代码等等。但世上还有更多开发者并不同意我们所说的是“唯一的道路”。

有时候会采取的解决办法是完全不理会实际情况,强迫所有的开发者都用同一种风格。会发生什么事呢?我猜下面这几种情况会很常见:

  • 有的开发者会非常低效。
  • 低效的开发者还会很不开心。
  • 最后整个团队围绕的风格是所有成员的“最小公分母”。
  • 于是当初赞同强迫推行那种风格的开发者,现在也变得低效和不开心。

能保持一致是好的,但不能不惜代价去保持一致。实际上我觉得很多时候让不同的分块用不同的风格开发,反而有好处。不同开发者之间的技能差异是其中一个原因。还有另一个经常被忽视的原因,不同的分块当然是有差异的,所以相应地采取不同的风格反而有利。比如有的分块从领域模型方式中肯定得不到什么好处,那么不采取领域模型的路线也没关系,实际上也建议不要那么做!

即使放宽了对分块内部的约束,你还是可以(也应该)对外部表现设立严格的要求,比如要保证自动化测试成功。

我意识到以上做法违反了集体代码所有制的原则,因为人们都圈在自己的分块里。在分块内部,(如果该分块选择了集体所有的风格)肯定是代码集体所有的。

对了,在单个分块内,我认为应该强迫一种风格。

变化率差异

这件事情你可能觉得显而易见,不过我还是要特别指出来:不同分块的变化率可能有极大的差异。在数据库驱动的项目里,有句话在项目前期的会议上经常听到,我也常常拿来开玩笑:

“我们已经定好了数据库 Schema,现在可以开始干活了!”

没有取笑谁的意思,我自己也说过这样的话。

虽然我有些犹豫要不要说出来,不过有的分块也许的确能用那样的方式取得很好的结果,定好数据库 Schema,以后就不再改了。

而同时其他的分块可以采用 DDD 项目的典型风格:

“好吧,我们现在了解得还不深,不过让我们先按目前的理解来做,随着我们了解加深,领域模型可以天天改,也一定会天天改!”

现在两种风格可以愉快地并存。以前肯定也有并存的情况,只不过现在明确了界限,成功机会提高了。

名字的来历

有人说任何值得讨论的事物都应该赋予一个名称,我当然不希望这种架构风格仅仅因为没有名称就失去讨论的资格。

那么“分块云计算(Chunk Cloud Computing)”是个好名称吗?争议肯定是少不了的,先放在一边,听我说一下来历吧。

在本届欧洲软件架构研讨会上,Christoffer Skjoldborg 提了一个叫做“Chunk Cloud”的论题。“Chunk”就是一小片(分块),“Cloud”是现在的炒作题材。他的描述很接近我近来观察到的一种应用架构方式。(本文就是努力在描述这种架构方式。“强迫一种风格”小节尤其得自 Chris 的启发。)Chris 描述的时候说得有点极端,不过我想主要是为了让他的观点流传开。

最后的“Computing”是研讨会上 Nicklas Andersson( http://nickeandersson.blogs.com )加上去的,大概是因为 CCC 看着比较酷吧。

最佳实践?

不知道你怎么样,我听到“最佳实践”的时候会警觉起来。可能是由于那些与 Dreyfus 模型 [Dreyfus model of skill acquisition] 相关的讨论,还由于见识到一些无视上下文的“最佳实践”……

我不认为“块云计算”是一种最佳实践。我只认为它是一种架构风格,而我经常发现适用这种风格的场合。但别忘了,要看情况。

新问题?

当然有了!可是你不觉得老问题没意思么?我知道这种风格有很多新问题,以后还会冒出更多(肯定的)。最多人提出来的两个问题是同样的数据出现在好几个地方,以及不同的分块之间有数据不一致的风险。这两个问题都必须解决,但请容我放到另一篇文章里。

还有一个经常提出的问题是“怎么做”,尤其是怎么将领域模型拆成几个小块。我会再找时间详谈。

更进一步的观察对此方向是肯定还是否定?

稳妥地说,两方面的观察(及观点)都有,我也期盼着看到您的想法!

参考资料

[Booch OOAD] Booch, Grady; Object-Oriented Analysis and Design with Applications;

[Brooks MMM] Brooks, Fredrerick P; The Mythical Man-Month;

[Dreyfus model of skill acquisition] http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition

[Evans DDD] Evans, Eric; Domain-Driven Design; 2003

[Fowler ApplicationDatabase] Fowler, Martin; http://martinfowler.com/bliki/ApplicationDatabase.html

[Fowler Events] Fowler, Martin; ] http://martinfowler.com/eaaDev/EventNarrative.html

[Fowler IntegrationDatabase] Fowler, Martin; http://martinfowler.com/bliki/IntegrationDatabase.html

[Fowler LayeringPrinciples] Fowler, Martin; http://martinfowler.com/bliki/LayeringPrinciples.html

[Greg Young] http://codebetter.com/blogs/gregyoung

[Nilsson ADDDP] Nilsson, Jimmy; Applying Domain-Driven Design and Patterns; 2006

[Nilsson Bricks] Nilsson, Jimmy; http://www.jnsk.se/weblog/posts/bricks.htm

[Nilsson NED] Nilsson, Jimmy; .NET Enterprise Design; 2001

[Nilsson SOA-Qs] Nilsson, Jimmy; http://www.jnsk.se/weblog/posts/soa-QSemantics.htm

[Webber Anemic Service Model] Webber, Jim; http://jim.webber.name/2008/04/19/30b4f0e9-f67a-4310-bf38-ca0a3423206e.aspx

阅读英文原文: Chunk Cloud Computing


感谢郑柯对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2009 年 6 月 29 日 22:454147
用户头像

发布了 225 篇内容, 共 52.4 次阅读, 收获喜欢 38 次。

关注

评论

发布
暂无评论
发现更多内容

最棒的 7 个 Laravel admin 后台管理系统推荐 - 卡拉云

蒋川

laravel vue admin

重学架构之微博评论高性能高可用计算架构

陈华英

架构实战营 #架构实战营

7 种最棒的 Vue Loading 加载动画组件测评与推荐 - 穷尽市面上所有加载动画效果(Vue loader)类型 - 卡拉云

蒋川

Vue vue admin vue loading

基于IOT物联网设计的智能家居系统-智慧门锁

DS小龙哥

物联网 智能门锁 3月月更

Mybatis中的SQL节点的解析

捡对象的cy

mybatis

尤达 DDD 领域驱动设计思想 第三章作业(识别SmartRM系统货柜机免密支付购物场景里的聚合)

代廉洁

尤达DDD领域驱动设计思想

LabVIEW保存、读取配置文件

不脱发的程序猿

LabVIEW 保存、读取配置文件

如何在 Go 代码中运行 C 语言代码

宇宙之一粟

C语言 Go 语言 3月月更

LabVIEW设计自定义滚动条

不脱发的程序猿

LabVIEW 设计自定义滚动条

SpringCloud-Ribbon学习记录

昊运

SpringCloud

扎“芯”了——CP探针卡的国产替代道阻且长

杰哥-IC男奋斗史

芯片技术 芯片上游

ninance尼南斯系统开发模式分析

NFT元宇宙平台开发

一步步教你开发鸿蒙系统应用,So Easy!

博文视点Broadview

「尚硅谷」java实战项目谷粒商城简介_idea_通用mapper

编程江湖

VUE创建视频流应用

devpoint

Vue Video播放器 3月月更

web前端Node安装步骤

编程江湖

尚硅谷Flink(Java)新版视频教程发布

@零度

flink 大数据开发

搜索引擎Elasticsearch简介实践

yuexin_tech

elasticsearch

Linux网络管理工具:ifconfig,从入门到精通!

Ethereal

ShardingSphere-Proxy分库分表(一)

神秘码农

分库分表

大厂面试官都不敢问的java线程的底层实现

刘祥

Java 线程

《软件开发的201个原则》思考:2. 质量在每个人眼中都不同

非晓为骁

程序员 个人成长 开发

「架构实战营」微博评论高性能可用计算架构

hxb

「架构实战营」

为什么要进行企业知识管理,这三个重点问题要明确

小炮

微博评论高性能高可用场景

风中奇缘

架构实战营 「架构实战营」

大数据培训面试Flink八股文分享

@零度

flink 大数据开发

架构学习【05】——“微博评论”高性能高可用计算架构

tiger

架构实战营

OpenHarmony 标准系统 HDF 框架之 GPIO 驱动开发

Anna

开发者 OpenHarmony 学习成长

大数据使用Airflow实现简单的工作流调度

编程江湖

Redis线程模型

javaadu

redis 面试题

什么是 503 服务不可用错误?

Ethereal

分块云计算_架构_Jimmy Nilsson_InfoQ精选文章