论模式与反模式
在架构设计中,往往会存在一些被行业普遍认可的设计模式。当然此设计模型与门面模式、工厂模式、代理模式等设计模式不同,更多是更加上层的技术方案层面。这些设计模式被广为流传,很多时候会成为技术方案设计中不成文的规定,也会成为架构方案评审的重要标尺之一,他指导了形形色色的系统架构设计,被认为是前辈高人历经各种项目洗礼后反诉琢磨思索所沉淀出来的行业宝贵财富,类似武侠小说中的秘籍。
(1)模式的目标
那么,模式所追求的是什么呢?或许不同的人有不同的理解,正所谓“横看成岭侧成峰,远近高低各不同”。然而,如果我们撇开纷繁复杂的理由,直击问题的根本,我认为模式所追求的是建设成本经济化。所谓建设成本经济化,一方面是指开发阶段可以快速高效,用较小的资源投入和成本消耗实现业务的落地;另一方面则是指后续长期的迭代和维护,可以更加低廉,系统生命周期可以拉长,从而更具备经济性。那么这个追求该如何落地呢?
(2)模式的落地措施
首先,去冗余。模式中第一招就是去冗余,尽可能的去冗余,任何事物最好只有一份。去冗余的目标在于一致性。众所周期,在关系型数据库的三大范式中,其中之一就是针对数据一致性,而要想低成本的实现数据一致性,去冗余便是首选的推荐方案。因为没有冗余,数据只有一份,用到的时候直接去源头查询即可。假设一份数据存在多个地方,要想实现数据一致性,就必须耗费精力去保证数据添加时各处同时成功,数据更新时各处也要同步,否则会细出现奇奇怪怪的问题。未达到该目标就需要额外的技术方案来保证,无疑增加了方案的复杂度,也会导致建设成本的提升。
其次,便是高复用。高复用可谓是渗透在我们生活的方方面面,成了大家最基本的思维方式和行事准则。在 IT 领域也毫不例外。从最基础的代码拷贝复用,到封装成类库被引用,到做成框架被使用,再到运行时环境(从 IaaS 到 PaaS),处处体现复用的身影,而且复用的范围也被逐渐的扩大,甚至希望一切都只需要一次开发,处处被引用。前些年被广为流传的中台战略,业务中台、技术中台、数据中台等甚嚣尘上的设计理念,虽然内涵丰富许多,但其中核心思想之一就是复用。近年来继技术中台之后逐渐热门的平台工程,又是复用的另一种声音。可见复用是基础思维。也难怪,经济基础决定上层建筑,复用确确实实体现了经济性。尤其是复用次数越多,范围越广,经济性愈加显著。当然复用的经济性除了提现在减少重复建设之外,还有一个深层次的原因。因为服用会推动精细化分工,从而实现更加专业化。其实这也是中台战略的重要吸引点之一。作为建设方,因为复用的过程,其实也是承接客户的过程,复用方越多,意味着接触的客户越多,也就意味着经历的场景也越多。随着各种场景的打磨和推动,建设者的视眼逐渐被打开,对出品的认知也会更加多元和深刻,从而体现在出品之上的便是更强大的能力、更友好的体验、更灵活的适配性......从而进一步行为相对优势,其他潜在客户也会进一步被吸引,形成正向激励。最终可以实现更低廉的成本交付更优秀的“产品”,有点类似国际产业分工。
最后,是方案统一化。我们都喜欢整齐划一,在技术方案设计除非可以,大部分情况下也概莫能外。一般的架构管控上,都希望达到高度统一性,所选用的类库、组件、框架要统一,版本要统一,服务器要统一,部署方式要统一,运行时环境要统一。总之,尽可能的统一。因为统一就意味着可复用的技术积累、更少的故障、维护更简单......或者说统一就意味着可以更加标准化,标准化之后就可以更加自动化,自动化就既可以节约人力投入,又可以减少因为差异带来的异常事件。也是大型的组织,整体上也是呈现统一化。无论是产品阶段的设计工具、UI 工具,还是研发阶段的开发工具、技术架构,还是测试阶段的自动化工具,都是统一的,甚至很多企业的服务器都是定制化的标准化产物。当然,对于大型企业而言,标准化很难限定为只有一个选项,更多时候可能有几种型号供选择。就好比服装的尺码,固定的 S、M、L、XL、XXL,而不是每个人都提出自己的需求再量身定做一个。
(3)反模式的目标
模式化既然看起来那么完美,那么契合经济目标、管理目标,有符合大众的思考方式和价值取向,甚至与日常生活经验也高度匹配。那么是不是意味着模式化就可以包揽一切呢?马克思哲学告诉我们,这世间不存在绝对的事物,一切都是相对的。模式化也不例外。
前文说过,模式化的主要追求是建设成本经济化。而一个系统的成本,除了建设阶段(含长期维护迭代在内)的成本,还有一部分便是营运成本。所谓的运营成本是指系统要支撑业务顺畅运行所需要花费的硬件成本、软件成本、人力成本甚至风险成本。硬件成本比较容易理解,如 Web 服务器、数据库服务器、存储磁盘、消耗的带宽等,软件成本包括调用第三方服务所消耗的成本,人力成本主要指日常运维成本、巡检成本以及出问题之后的应急处理成本,风险成本是指一旦系统出现波动对业务所带来的负面影响。譬如对于电商类系统,如果系统不稳定,导致添加购物车失败,或者付款时卡住无法成功,假设用户购买的是非必需品或本身属于冲动型消费,很可能会因为断断续续的体验而果断放弃并且不会再完成此次购买行为,反映到业务层面,便是丢失了一笔订单和对应的营业收入。
模式化的冗余,对于中小型业务系统可能利大于弊,确实降低了维护数据一致性的成本,但是对于大型系统,查询数据时需要跨多个数据源进行关联查询,一方面会导致单词查询的时长加长,进而导致相应时间拉长,体验的下滑;另一方面多数据源关联查询也会导致系统并发能力的下降,为了支撑业务量级,需要比更好的关联查询条件下更多的资源,甚至还会导致系统稳定性指标的下跌。总之,需要投入更大的营运成本,而且还可能效果差强人意。模式化的复用,有可能也会导致请求的集中以及跨网络,跟冗余一样,既增加了响应时间,又导致并发能力下降和稳定性的下降。最后方案统一化也可能出现削足适履的场面发生,因为标准是固定的,系统方案无法采用更匹配业务规模的方式。
由此,有前辈高人提出了反模式化的设计思想。即在特殊场景下,与模式化反其道而行之,采用更能提高并发能力、缩短响应时间、提高稳定性,以及极为重要的降低资源投入的技术方案。反模式化的核心追求是营运成本的经济化。
(4)反模式的落地措施
那么,反模式化的落地措施有哪些呢?
首先,与模式化针锋相对的就是冗余。通过适当的冗余,减少数据查询时的关联,从而降低跨网络、跨数据源的数据汇集。因为冗余,复杂的多表关联查询,可以改为单表查询,对于高并发型系统,因为本身业务体量大,核心表的记录数一般都比较大,这种情况下,跨表关联查询本身就是就不靠谱的事情。改为单表查询后,几乎可以实现几个数量级的效果跃迁。可以说,数据量越大,并发量越高,冗余所能体现的价值越高。
其次,是集成。这一点与模式化中的高复用有一定的参照关系。所谓集成,便是将需要跨网络请求的内容,开发阶段或部署阶段直接通过相应手段内嵌到自身,从而尽可能的规避跨网络的请求。举一个常见的例子,对于业务系统,一般都涉及到信息加解密和权限认证。一般企业加解密可能有统一的服务来提供,但是对于大型系统,请求非常频繁,如果每次请求都需要跨网络调用其他服务,性能损耗和稳定性都会大打折扣,因此一种可替代的选择,便是将加解密做成类库,需要用到的地方直接引用。权限认证也是一个非常常见的功能,很多时候也都有专门的认证服务提供相应的能力,同样的大型系统中也会导致调用方耗时增加、被调用方压力过大导致服务不稳定进而导致调用方的不稳定。通畅的做法也是直接将权限数据预先加载到各个服务内部,将之前的跨网络服务请求改为自身内存匹配,效率自然是数量级的提升。因此,集成对于解决分布式场景下的大并发问题有较好的效果,也是被经常采纳的有效方案之一。
再次,是差异化的技术方案。即不再强制追求技术方案的一致性,取而代之的是根据业务量而选择更满足需求的替代方案,当然这主要还是适应于高并发或其他特殊场景。譬如公司主流的网关是 Spring Cloud Gateway,但是高并发场景下,他的处理能力不是太理想,而基于 nginx 和 openresty 的 Kong 具备更高的并发支持能力以及更灵活、更实时的控制效果,那么这种业务系统,采用 Kong 作为 API 网关无疑更为明智,萧规曹随不知变通反而会导致更大的成本付出。还有一些公司主流的变成语言是 Java,但是系统需要与硬件交互,虽然 Java 也能实现,但是相比 C 语言,效果要差很远,这时候按照反模式的思想,选择 C 语言来针对性的实现这个需求应该更加合适。
最后,反模式的另一个措施是路径最短化。该如何理解呢?一般业务系统都是多层架构,从网络防火墙,再到流量网关,再到应用网关,再到业务系统,最后再到各个业务服务。这个链路会随着业务系统的复杂度而拉长。如果每一个请求都完整的按照这个链路处理,很多情况下是存在浪费的。反模式的思想是,再每一层增加检测机制,只要不符合条件的请求,直接中断。所有的检查机制又都是按照成本代价由低到高排列。
(5)该如何选择模式与反模式
介绍完模式与反模式之后,想必大家会思考一个问题,即这两个看似几乎矛盾的方案到底该如何选择呢?
要回答这个问题,我们需要回到他们的目标追求上。模式化追求的是建设成本经济化,而反模式追求的主要是营运成本经济化。而任何一个系统几乎都同时存在建设成本和营运成本,只是系统承载的业务体量不同会导致复杂度不同,而复杂度不同必然会导致建设成本和营运成本的双重攀升。当然,相比之下,营运成本会更为明显,毕竟当系统上升一个数量级,开发难度固然会加大,建设成本也自然水涨船高,但是规模之后带来的营运时的挑战则会更加明显。对于支持十万在线和百万在线的系统,要保持正常营运所投入的资源数量往往会超越直线增长,毕竟数量越多,损耗越多,单位数量的资源所能发挥的效率也就下降。
因此,要选择是按照常规模式化的方式来建设系统,还是采用反模式化的非常规思路建设系统,重要的取舍因素在于系统所将要承载的业务体量。越是大型系统,越是需要尽可能的利用反模式化,降低系统的依赖、跨网络请求、复杂处理逻辑等;反之,则可以尽可能的遵循模式化设计理念,降低系统的建设成本。
(6)延升思维
模式化与反模式化看似对齐的方案,但背后却仍然有相对清晰的选择依据。其实不仅仅是 IT 架构如此,很多事情莫不是如此。这带给我们几点启示。
其一、凡事不要看表面,要学会透过表象看本质。正如哲学里边经常讲的,很多事物看似矛盾,背后实则有内在的一致性逻辑。
其二、不存在普适性的原则,可以应付一切问题,即不存在「银弹」。更多的时候,我们要深入理解每一个原则背后的假设条件和追求目标,从而在实际应用时可以根据具体的情况选择与之相匹配的最适合的方案。避免囫囵吞枣,在一知半解的情况下简单粗暴的套用原则,从而出现因为不契合从而带来负面效果的局面。正所谓活学活用,才算是学到了家。照搬照抄,只是入门。
其三、还给我们一个启示,不要迷信任何原则。就像科学一样,任何科学都有其假设条件,也就说一旦假设条件不成立,科学可以被证伪。原则和模式亦是如此。
版权声明: 本文为 InfoQ 作者【凌晞】的原创文章。
原文链接:【http://xie.infoq.cn/article/8b8c4dd7a720d46cb1317a2af】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论