上一篇文章中 ,我引入了一个新的概念S++,按说我应该继续下去,但是我觉得在这之前还是要先谈谈架构,因为服务化意味着大的系统被拆小,一个人可以没有组织,但是一群人没有组织就是乌合之众了,所以服务化和架构有着密不可分的联系。本文会有三次谈架构,这次会从架构的一般逻辑来谈起,估计会有些枯燥。
架构是一种平衡手段,架构为特定的目标服务,通过平衡资源的分配从而达成有限的资源下实现特定的目标。
通常,我们做架构设计的目标是平衡空间、时间、可靠性、复杂度、可维护性、易用性、成本等等指标,选择应用更迫切需要满足的指标优先满足,同时尽可能的减少对其他指标的影响。简单说,架构就是要明确取舍。而且,我们选择的架构不能够影响应用本身的业务逻辑,也就是说架构对应用来说应该是透明的。
以上是我对架构的一些基本看法,关于架构是什么很多人都有独到的见解,我就不多谈了,另外我很喜欢郭蕾推荐给我的 Kevin老师执笔的《架构漫谈》 。本章主要探讨在面向服务的发展历程中曾经被广泛使用的几种架构的对比和特点,以便于我们去理解未来章节中我们对架构取舍的一些基本出发点。
SOA发展过程中既有无中心架构,也有集中架构,前者用于互联网企业间的交互,后者在企业内部使用。
确切的讲SOA没有“去中心化”架构,只有“无中心化”架构。我们前面讨论了,架构是为了实现特定的目标的,而这目标源于需求和现实,那么”无中心化“架构就是SOA在互联网环境下的必然的架构选择。其实也没得可选,因为SOA要解决企业间的通过互联网相互访问的需求,而互联网是一个自由的无政府环境,根本就不存在一个共同认可的架构中心节点。两者对比如下:
其实无论是去中心还是集中架构,都是组织需要而非技术需要,需求决定技术架构。在企业内部,无论任何架构都要满足组织对管控的需求,而这种需求必须由一个统一的中心节点来提供,所以SOA化在组织内部大多数是以ESB作为基础来实现的。
现实社会中,纯粹的自由和绝对的集权都是无法做到的,任何组织也是这样。所以绝对的去中心和绝对的集中模式都是极端架构,并不可取(只有在解决极端需求的时候才会被用到)。
事实上,分布式多中心的架构是现实社会中最为常见的,比如物流行业,没可能每个人的包裹都能从寄件人那里直接送给收件人(去中心成本不可接受),但也不可能全国只有一个物流集散中心,所以大多采用按区域分布式部署物流集散中心。同样的,比如电信、连锁、企业管理机构等等,只要是我们能想的到的协作型组织,大多都是分布式多中心架构的。
下图是一个单一中心的示意图,图中显示的是一个多语种信息交流中心的基本结构,他的作用就是帮助每一个需要交流的人,在一个平台上可以通过任意的语言和任意的通讯方式进行无障碍的交流(当然,这是一个为了方便的说明问题而虚构出来的平台,虽然目前有些社交平台提供了类似的功能)。
这样一个中心,可以是自发的产物,因为有需求,人们需要交流、需要交换物品等等。人是社会化的动物,集市这样的东西是必然的产物。那么,自然的各地都会出现这样那样的集市,多中心的架构就自然形成了,如下图每一个区域中心都具备单一中心的功能。多中心的架构是自然社会发展过程中,人们自发的一种对功能和效率平衡的一种架构。
下图是多中心架构被极端化后形成的去中心架构,去中心架构并非没有中心,因为中心节点需要完成的功能都是必须的,所以如果在不降低功能需求的情况下,去中心架构事实上是把中心的功能融合到每一个终端节点上了。对于集成架构而言,去中心架构几乎没有任何优势而言。
在我看来,在企业内部实施去中心架构,实质上去掉的不仅仅是中心,更重要的是弱化甚至去掉了企业的管控需求。在一个非极端环境下将架构极端化,那么还要架构干什么?架构还怎么起到平衡资源的作用?
在此引用一篇文章http://kb.cnblogs.com/page/521880/,我觉得写的挺好,基本上不需要我去讲解什么是微服务了。 在此借用两幅图简单说明一下。
第一幅图展现了传统“大”服务架构下应用的开发部署模式,应用作为一个整体存在,业务对象作为应用内部的不同功能模块,不同业务对象之间通过应用内部的流程进行拼接。
微服务架构通过将原业务系统按业务对象作为基本单元进行纵向拆分,以交互层次作为标准进行横向拆分,从而形成多应用交互的微应用架构体系。
那么,其实微服务并不是什么新鲜事,至少SOA理念中几乎包含了所有微服务的理念。本质上说,微服务“微“的并不是服务,而是应用,其实SOA也是倡导服务系统走专业化的道路的,这我们在最开始做ESB的时候就在推销这个概念,比如将传统核心按业务条线拆分成不同的专业系统等。相对应的,为了方便起见我们将WebServices时代的SOA称为”大服务“以示区别。
上述引用的文章中微服务架构推荐一个服务一个系统,事实上我们看到的是一个业务实体一个系统,这符合我们对业务系统内部用面向对象的方式进行建模的传统。当然,也是因为传统的“服务“的概念和我们的提出的服务不是相同的,这一点上微服务和大服务对服务的概念是相同的,比如引用中的”行程管理服务“其实是由针对一个业务实体的多种操作来组成的。
如果服务依然是对对象实体的抽象,那么SOA所有这些概念不过都是在炒作,和面向对象没有任何实质上的进展和差异。事实上,我们知道WebServices本质上就是一种远程对象,与我们熟知的Corba、COM、EJB等几乎没有任何本质差异。如果说SOA已死,对大服务来说SOA就从来没活过,那不过是远程对象穿了个马甲而已;如果说微服务当立,我看不出与大服务有什么本质的差异,倒不如说微应用当立更好。
其实,当系统架构演化为微服务架构以后,系统所面临的新问题变得和微服务解决掉的问题几乎一样多:
(纯吐槽:越来越多的人标榜自己的东西是轻量级的,我不得不吐槽一下,在我看来轻量级就是简单甚至粗糙的代名词。如果是完成同样的功能,我不相信你的能比别人的东西轻量,除非别人是傻子,你用一行代码能完成的他要用十行代码。你比他轻量,正常情况下意味着你的东西比他的功能少。)
传统SOA架构下,解决企业内部系统间应用交互问题主要的方式就是采用ESB进行连接。但在微服务架构下,由于ESB“过重”,会导致频繁的系统间交互效率大大降低,所以微服务架构回归了去中心化的点对点调用方式。但是系统拆分带来的问题,是不是能简单的用轻量点对点通讯就能解决了呢?这个觉得这个想法有点儿朴素了。下面我们看看ESB为什么会这么“重”,微服务架构能否安全的绕开这些”重”的东西。
在“大”应用拆分之前,应用的安全性是整个大应用统一考虑的,比如身份认证、权限、防篡改、防抵赖、加密等等。之所以有这些诸多的安全措施,是因为企业应用环境并非一个安全可靠的环境,内部的外部的黑客都有可能进入网络对内部系统进行攻击,尤其是内部黑客更是畅通无阻。
那么,是不是大服务拆成微服务之后,这些黑客就消失了呢?这个想法显然是无法接受的,事实上被拆分后的微服务由于维护能力和专业能力不够,使用技术杂乱等等原因,使得黑客更容易得手。
一个不设防的微服务,对于内部黑客来说,只要从浏览器模拟一个服务请求,就可以轻松的进行危险的操作。这种“轻量”我认为无异于掩耳盗铃。
“系统之间的耦合,从来没有像今天一样多”。对于微服务架构而言,原本系统内部对象之间的交互行为,被简单粗暴的暴露到系统之间来。
“我原来的代码是这样的:t.open();a.calculate(b);b.save();t.close();现在a和b在两个系统里面,谁能告诉我现在这段代码归谁管?”
“我这里会出错的,你们谁call我的,自己注意回滚操作!“
“我这个技术参数是必要的,因为我后面要调用C系统,这个技术参数是他要的,不要问我为什么,因为我也不知道!”
这些问题相信大家都遇到过,如果只是简单的把系统拆开,那么原本存在于系统内部的强耦合性会更加突出的表现出来,这导致微服务的应用开发并不比传统应用更简单,相反的还会引入诸如事务一致性等原来不存在的问题。
微服务架构引入了一个新的可靠性问题,当一个传统大应用的复杂业务逻辑出现问题的时候,比如一个业务X需要调用A,B,C,D四个模块的方法,由于这个业务逻辑X是在系统内部通过同步的API进行调用的,任何一个模块的错误会直接导致整个业务X出错,从而直接反馈给ESB,对于ESB而言最简单的保证可靠性的方法就是隔离掉错误的服务X。
但是当大服务被拆分成4个微应用之后,如果业务X的入口在A系统,而出错点在D系统,由于各系统都是独立的A并不知道D出了问题(即便知道也不知道怎么处理),对于管理者来说简单的隔离D可能是唯一能够做到的,于是会造成一连串的连锁反应,而且系统间访问都是异步的,这会在最终问题被处理之前引发大规模的错误和回滚请求。
这种强耦合导致的系统间不可靠性,其实SOA的解决方案就是将业务X从系统中剥离出来,将X放到ESB上来进行调度(理论上应该如此,先不说ESB能否胜任)。
对于这样一段传统的业务代码:
try{ t.open(); a.calculate(b); b.save(); c.mark(b); }catch(Exception e){ t.roolback(); //出错处理和业务逻辑是分离的 }finally{ t.close(); }
我们通过传统的编程方式,可以方便的将错误处理和业务逻辑进行分离。但是,一旦将a,b,c拆成三个系统,问题就变得非常复杂了。首先,我们无法在传统的编程语言中支持异步调用,比如调用b.save()如果是异步的那么上面的这段代码根本就不能工作;第二,即便解决了异步问题,也就是说b.save()返回后还能成功的将程序调用堆栈恢复到c.mark()之前,你依然需要在业务代码中加入错误处理的分支,也就是说b.save出错了应该回滚之前的操作。
所以,如果用传统语言来实现这样的业务逻辑,大多数的选择是这样的: a系统:
func calculate(b){ try{ t.open(); …… b.remotecall("save",b); //同步调用,在b.save中去调用 //c.mark(); if(isError(b.return)) throw new Exception("b.save error"); }catch(Exception e){ t.rollback(); }finally{ t.close(); } }
我们可以看到,即便是同步调用也大大增大了代码的复杂度,如果是异步调用,就需要一个框架来实现,业务逻辑会被拆的七零八落难以理解和维护。而且,这段代码实在是太丑陋了,为什么要在calculate中去调用save呢?为什么要在save中调用mark呢?显然应该有更加优雅的方法来实现。
“我们刚刚花了几年把所有系统都改成WebServices接口了,你们又要改JSON,能不能告诉我什么时候能稳定下来?”技术总是不断地进步,应用总是不断地在落后,这是一个必然趋势。我们今天用业界先进的技术来搭建新的应用系统,两年之后这个昔日先进的系统就变成落后的存量系统了。所以,异构存量系统的集成问题是永恒的话题和需求,那么互联网模式这种统一技术架构,统一接口规范的大一统想法是不切实际的,除非你肯花大量的资源去不断的跟踪技术的变化,不断的投入去改造老系统的技术平台。
微服务架构适合于利用统一的技术平台新建系统,但是随着系统的发展,系统之间的异构化逐步的成主要的矛盾,这种去中心架构也将不再能够满足系统间交互的需求。
组织需求与架构选择
前面分析我们看到,架构是组织需求决定的。组织需要精细的成熟的管理,就偏向权力密集的集中架构多一些;组织需要创新和快速迭代多一些,就偏向更自由的去中心架构多一些。但是,一种非黑即白的架构选择显然是不合理的,大多数的组织既需要精细成熟的管理,也需要自由奔放的创新,所以就需要一种架构能够支撑更复杂的混合需求。
那么我们前面讨论的自然进化来的多中心架构就成为一种合适的选择,事实上我们观察现实中稍微复杂一点儿的企业,无一例外都是多中心结构的。后面我们先深入理解S++的特性,然后再来详细探讨S++与各种架构的关系。另外,我相信很多朋友会困惑多中心架构如何解决淘宝级的访问压力,后面我会逐步的提出解决方案或解释。 架构是用来平衡资源的,它并不能改变资源的多少,想提高性能还是要在算法上下功夫。
李东,14岁开始学习计算机语言,作为课外兴趣自学了BASIC和汇编,利用放假期间编写了贪吃蛇、打飞碟等游戏。高中、大学期间继续自学软件编程,曾将C和汇编结合使得从高级语言中能够调用绘图功能,并模仿Borland C++开发了一套适合学校机器的图形化开发环境的原型。
93年大学毕业后在西门子合资公司作为交换机软件安装人员工作两年,然后来到JInfonet公司先后参与4GL的研发和JReport的研发。作为JReport的第一代主要研发人员,编写了从原型一直到3.0版本的核心引擎部分。2000年与合伙人一起创建了Bi-Soft公司,主营业务是商业智能软件Bi-Pilot,负责整个产品的研发及管理工作,从最基本的查询一直到多维分析模型和引擎都是产品的涵盖范围。
2007年Bi-Pilot被神州信息收购合并,李东开始在神州信息研发SmartESB产品,用SOA的方法论为客户提供底层产品服务。
感谢郭蕾对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们。