4.14.6 —种混合方式

 
前面提到的那些选择各自都有其适用的范围。一个组织会选择基于片段组装的方式来构建 网站,但对于移动应用来说,BFF可能是更好的方式。关键是要保持底层服务能力的内聚 性。比如,预定音乐和改变客户信息的逻辑应该处在相应的服务中,避免这些逻辑在系统中到处散布。将太多的逻辑放入到刚才提到的那种中间层中是一个常见的陷阱,在实际中 需要非常小心地做权衡来避免这个问题。
 
4.15与第三方软件集成
 
前面提到的拆分已有系统的方式针对的是我们自己开发的系统,但如果需要处理那些不受 我们控制的系统呢?由于种种原因,和我们一起工作的组织都购买了 COTS或者利用SaaS (Software as a Service,软件即服务平台),而通常我们对这些系统的控制力都很有限。那 么如何合理地与之进行集成呢?
 
如果你正在阅读此书,那么你很有可能工作在一个需要写代码的组织中。你可能为内部或 者外部的用户编写软件,或者两者皆有。不管怎样,即使你所在的组织拥有很强的定制化 软件开发的能力,你还是需要外部组织提供的商业或者开源软件产品。为什么会这样呢?
 
第一,你的组织对软件的需求几乎不可能完全由内部满足。考虑你使用的所有产品,从类 似Excel的办公自动化工具到操作系统,再到工资系统。自己创建所有这些产品的工作量 是巨大的。第二,也是最重要的一点是,这样做非常低效!自己构建邮件系统的代价要远 远大于使用现成的工具,即使选用的是商业工具。
 
我的客户经常纠结这样的问题:“应该自己做,还是买? ” 一般来讲,我和同事的建议是, 对于一般规模的组织来说,如果某个软件非常特殊,并且它是你的战略性资产的话,那就 自己构建;如果不是这么特别的话,那就购买。
 
举个例子,一般规模的组织不会把工资系统当作它的战略性资产,因为全世界的人领工 资的方式都大同小异。类似地,大部分组织倾向于购买现成的CMS (Content Management System,内容管理系统),因为这一类工具对它们的业务来说并不是那么关键。我参与过 Guardian网站的早期构建工作,定制的内容管理系统对于新闻行业来说非常关键,所以他 们决定自己构建。
 
所以,使用一些商业的第三方软件是合情合理的,但很多人会逐渐开始咒骂这些系统,这 又是为什么呢?
 
4.15.1缺乏控制
 
使用类似CMS和SaaS这样的COTS产品会面临的一个挑战是,如何与之进行集成并对其 进行扩展,因为大部分技术决策都不受你的控制。如何与该工具进行集成?厂家决定的。 使用什么编程语言对其进行扩展?也取决于厂家。你是否能够把该工具的配置文件存到版 本管理中,然后在持续集成中重新创建和配置该工具?这依赖于厂家所做的决定。
 
如果你足够幸运,从开发的角度使用该工具的难易程度会成为工具选择流程中的一个考虑因素。但即便如此,你还是放弃了一部分控制。所以更好的方式是,尽量把集成和定制化 的工作放在自己能够控制的部分。
 
4.15.2定制化
 
很多企业购买的工具都声称可以为你做深度定制化。一定要小心!这些工具链的定制化往 往会比从头做起还要昂贵!如果你决定购买一个产品,但是它提供的能力不完全适合你, 也许改变组织的工作方式会比对软件进行定制化更加合理。
 
内容管理系统能够很好地说明这种危险。我用过的很多CMS工具设计上就不支持持续集 成,其提供的API非常难用,并且底层工具很小的升级都会破坏你做的那些定制化。
 
Salesforce的问题尤其突出。这么多年来它一直在推Force.com平台,而这个平台需要使用 一种叫作Apex的语言,该语言只能应用在Force.com的生态系统中。
 
4.15.3意大利面式的集成
 
另一个挑战是如何与工具进行集成。如前面讨论过的,服务之间的集成是一件非常重要的 事情,理想情况下应该存在一些为数不多的标准化集成方式。但如果一个产品决定使用专 有的二进制协议,另一个使用SOAP,还有一个使用XML-RPC,你该怎么办?更糟糕的 是,那些允许你直接访问其内部数据存储的工具,会引人前面讨论过的那些耦合问题。
 
4.15.4在自己可控的平台进行定制化
 
COTS和SAAS产品当然是有用的,但不适用于重头开始构建系统的场景(或者说这么做 不合理)。那么如何解决这些挑战呢?关键是把事情移到自己可控的部分做。
 
核心思想是,任何定制化都只在自己可控的平台上进行,并限制工具的消费者的数量。为 了更好地理解这个概念,接下来看两个例子。
 
1.例子:CMS作为服务
 
从我的经验来看,CMS是一个最经常需要做定制化或者与之集成的产品。因为除非你想要 的是基本的静态站点,否则一般的企业都希望在自己的网站上提供动态内容,比如客户信 息或最新的产品。这些动态内容的来源通常是组织内已经存在的其他服务。
 
CMS最常见的卖点是,你可以对其进行定制化,从而把各种特殊的内容放进来并显示给外 部世界。然而普通的CMS开发环境通常都非常糟糕。
 
普通的CMS提供的主要功能是内容的创建与管理。大多数CMS甚至连页面布局都做不好, 它们通常只提供一些可拖拽的工具,然而这并不能满足你的需求,你还需要一些懂HTML 和CSS的人来好好调整CMS模板。在其之上开发定制化代码将会是非常糟糕的体验。
 
那么到底应该怎么办呢?你可以选择在CMS上面套一层自己的服务作为对外的网站,如 图4-11所示。这时CMS就成为了一个服务,其职责是管理内容的创建和获取。在自己写 的那个前端服务中,你可以按照自己的方式来写代码和做集成。你对网站的扩展具有很好 的控制力(很多商业CMS提供了自己专用的插件来处理负载),那么就可以使用更合理的 模板系统。
图4-11:使用CMS把你自己的服务隐藏起来
 
大多数CMS还提供了创建内容的API,所以你可以选择把创建的这部分也使用自己的服 务包裹一层。在曾经做过的一些项目中,我们甚至使用过一个外观(fapde)对获取内容 的API进行抽象。
 
前几年,在ThoughtWorks这种模式应用得很广泛,光是我自己就做过不止一次。一个值 得注意的例子是这样的:一个客户想要为他的产品制作一个网站,刚开始他想完全在CMS 上构建这套系统,但还没确定使用哪个。就在这时我们建议了这种方式,然后开始构建前 端网站。在CMS选定之前,用一个假的静态内容服务来替代它。后来甚至在CMS确定之 前,直接在生产环境使用了该静态内容服务。等到CMS终干选好了之后,没有做任何修 改就顺利地把原来的服务给替换掉了。
 
这种方法吋以最大程度地限制CMS的使用范围,并把定制化的工作移到你自己的技术 栈中。
 
2.例子:多职责的CRM系统
 
我们还经常会遇到CRM (Customer Relationship Management,客户关系管理)工具,即 使最坚强的架构师也会对它感到恐惧。这个行业的主要厂家包括Salesforce和SAP,这些 工具试图为你包揽所有的事情。所以这些工具可能会出现单点失败,并且还可能会变成一 团乱七八糟的依赖。我见过的很多CRM工具的实现都是粘性(内聚性的反方向)服务的 典范。
 
这种工具的使用范围往往一开始会比较小,但随着时间的发展它会在你的组织中变得越来 越重要,以至于后续的方向和选择都会围绕它来做。但这么重要的系统竟然不是自己做 的,而是第三方厂家提供的,这是个很严重的问题。
 
我最近在做的一件事情就是夺回控制权。我所服务的组织意识到虽然很多事情都使用 CRM在管>里,但是这个平台并没有带来与其代价相对应的收益。与此同时,很多内部系 统都在使用CRM提供的差强人意的API来做集成。我们希望对系统架进行演化,使用自 己的服务来对业务进行建模,从而为潜在的迁移打下基础。
 
我们做的第一件事情是,识别出正在被CRM系统控制的核心领域概念。其中之一是“项 目”的概念,员工会被分配到不同的项目上。由于多个其他的系统需要项目的信息,所以 我们就创建了项目服务。这个服务将项目以RESTful资源的形式暴露出来,外部系统可以 把它们的集成点迁移到这个新的、易用的服务上来,而这个项目服务仅仅是隐藏了底层的 集成细节而已。如图4-12所示。
图4-12:使用外观服务来隐藏底层的CRM
 
在本书写作时,这项工作还在继续进行中。持续识别出其他CRM管理的领域概念,然后 在其之上封装出外观。等到迁移时机到来时,可以查看每一个外观来决定,是自己编写软 件还是使用一些现成的方式来完成这些工作。
 
4.15.5绞杀者模式
 
你通常难以完全控制遗留系统和COTS平台,所以当你使用它们时要考虑如果需要移除或 者绕过它们的话,应该如何操作。一个有用的模式叫作绞杀者模式(Strangler Application Pattern, http://martinfowler.com/bliki/StranglerApplication.html)0 与在 CMS 系统前面套一层 自己的代码非常类似,绞杀者可以捕获并拦截对老系统的调用。这里你就可以决定,是把 这些调用路由到现存的遗留代码中还是导向新写的代码中。这种方式可以帮助我们逐步对老系统进行替换,从而避免影响过大的重写。
 
在微服务的上下文中,通常不会使用单一的单块应用来拦截所有对已有遗留系统的调用, 相反你可能会使用一系列的微服务来实施这些拦截。在这种情况下,捕获并重定向这些原 始调用可能会变得更加复杂,可能需要使用一个代理来为你做这些事情。
 
4.16 小结
 
前面了解了很多不同的集成选择,我也谈了什么样的选择能够最大程度地保证微服务之间 的低耦合:
 
•无论如何避免数据库集成
 
•理解REST和RPC之间的取舍,但总是使用REST作为请求/响应模式的起点 
•相比编排,优先选择协同
 
•避免破坏性修改、理解Postel法则、使用容错性读取器
 •将用户界面视为一个组合层
 
这里覆盖了很多内容,每个话题都不可能讲得非常深入。但起码你知道有哪些点需要学 习,以及正确的方向是什么,这对你的进一步学习很有帮助。
 
我们也花了一些时间来研究如何应对那些不完全受控的系统,比如COTS产品。细想一下 你会发现,这些原则也很容易应用到我们自己编写的软件中。
 
这里列出的一些方法,对遗留系统来说同样好用,但是如果我想要把一个大系统分解成为 可重用的小系统,应该怎么做呢?下一章会着重讲解这个问题。
 
 
 
 
posted @ 2019-12-05 21:31  mongotea  阅读(150)  评论(0编辑  收藏  举报