全世界有成百上千万的程序开发人员,无论是科班出身、还是半路出家的,每个开发人员大致的成长之路都是从计算机硬件及软件的基础理论开始、包括学习算法和数据结构,然后挑选一至几个被最广泛使用的计算机语言,比如通用的Java、C++、.NET、以及工作中遇到的特殊用途的某种计算机语言等等,就这些种语言本身的句法和功能进行学习和训练;同时了解和熟悉一些数据库的设计和开发知识。全世界确实有大量的应用比较简单,最多也就是三层的“网页-Web服务器-数据库”这类的“模型-视图-控制器”(Model-View-Controller)架构。事实上多年以前Sun Microsystems 就发布过关于J2EE的架构模式目录,来指导Enterprise Java的企业架构师们设计出优美的、灵活应变的架构。
现在,你作为一个IT咨询公司的IT总监或解决方案架构师、或者你就是公司里的企业架构师,而你面对的是成百上千个现有的小系统和应用:有的是Java、有的是.NET、而另外一些是数据库里的存储过程;再加上大型的ERP系统、客户管理系统、业务流管理系统等等,你要怎么做才能把这些看似杂乱无章的系统和应用连接起来了呢?
首先来看看我们是怎么走到今天这一步的:
- 20世纪70年代,商务运行中占绝对优势的是Mainframe系统,其特点是运行过程和数据都高度集中在一台机器上、专注于实现商务功能的自动化。
- 20世纪80年代,随着个人电脑和局域网的普及,企业里各个部门的用户使用个人电脑进行文字和图表的处理、而不再过多的依赖于IT部门的大型机。
- 20世纪90年代,随着广域网的普遍使用并成为企业标准,企业的信息和资源进一步地分散到企业的各个部分,造成了资源共享、集中监控和企业学习等方面的困难。这时的企业高管们已经开始意识到需要对系统和数据进行集成和整合。这个时候,已经很难找到与外界没有任何联系的、孤立的系统了。
- 21世纪初,随着广域网和互联网出现,企业变得更加大型化和全球化。企业和合作伙伴、供应商、分销商、以及企业内部员工之间的互动愈加频繁。在这个阶段,企业高管们关心的是数据共享和如何基于数据做出相应的战略决策。
- 2010年后,企业高管们依然关心数据共享和基于数据的战略决策,但这一次企业资源和服务的标准化成为具体实施的主题,具体措施包括软件技术和方法论、以及企业里相应的组织机构方面的调整。结合方兴未艾的云平台、物联网和大数据技术,渐渐明确了IT部门的作用是为了推动企业的快速创新。
只要你做过几年的企业IT设计和开发、或者参与过客户公司的IT咨询项目,你一定会发现,没有一个项目是从一张白纸开始写起的。恰恰相反,每一个项目都需要保留和利用数个、甚至数百个现有的应用和系统、将其中的数据分享给其它的应用和系统。每个现有的应用和系统都已运行多年,它们都已存有多年的商务数据、有很多的用户依赖这些系统和应用来完成他们每天的工作,它们具有宝贵的价值。另外在这些系统和应用之上还常常二次开发出了更多的工具和应用。所以,将它们全部推倒重来是不可能的。但另一方面,这些系统和应用盘根错节、相互依赖,给系统维护和升级、新功能开发带来了不小的挑战。
我们先来看看如果A程序要跟B程序分享数据,都有那些方法可以实现呢?直观地,可以相信以下几种方式:
- 如果A程序跟B程序运行在同一个内存空间里,A程序将数据处理的结果放在B程序可以访问的内存地址上。可惜,实际应用中遇到的集成问题都不是这种情形。
- A程序将数据处理的结果存入某种格式(比如固定数据单元长度或特定字符分隔的csv)的文件。对于大量、批处理的情形,这样的数据分享/集成方式依然很普遍。然而,关于如何处理这样的文件的具体逻辑需要数据源和数据目标系统另外单独沟通,从而严重影响了数据的通用型;另外,以文件的形式传送数据(本地或映射的文件夹、各种FTP服务器等)在强调实时的应用中有着许多明显的缺陷 – 最显著的是I/O速度比存储器的调用速度要慢得多。
- A程序将数据处理的结果存进某个数据库、再由B程序从数据库中将该处理结果取出。这种方式与文件方式相比更容易安排、且数据库的transaction管理使得数据的传送更为可靠,但在文件方式中存在的I/O速度问题依然存在,而且数据库本身的软件版权和支持费用也要考虑。
在最近的15年里,计算机内存的价格下降的速度远远大于硬盘价格的下降。而基于内存、不涉及I/O的系统之间的信息交换渐渐成为主流。这包括同步调用和异步调用,即调用者等待和完全不等待调用结果的两种情形。基于SOAP/XML的Webservices调用和JMS的消息发布即是具体的两个例子。
我们来看一个最简单的例子,如何将S系统(比如Salesforce)的数据导入T1系统(比如MySQL数据库)。绝大多数人立即想到的、最自然的办法是定义好哪些数据是需要从S系统导入T1系统的(比如顾客的姓名、电话和电邮);找到从S系统取出这些数据的方法(比如调用Salesforce SOAP API)、并取得数据;最后看怎么将数据存入T1系统中(比如JDBC调用)。大功告成!
且慢!这种“最自然的”方式存在着以下诸多问题。顺便提一句,凡是涉及到某种技能的培养,最正确有效的做法往往和“最自然的、最本能的”方式恰恰相反,比如滑冰时正确的方式是将重心放在前脚上,恰恰与人走路时最自然的重心放在后脚上的本能相反。
- 从头到尾都是封闭的、点对点式的调用。如果同样的S系统的信息还需要导入T2系统(比如Oracle数据库)和T3系统(比如SAP),从S系统中导出数据的工作要重复三次。如果分在不同的项目中完成,同样工作的实施可能重复进行、并互不一致。当总的系统数目超过5个时,系统的复杂程度就会失去控制,会变成这样:
2. 每次导出的信息只是只言片语 – 只看“姓名、电话和电邮”这几个指标,你知道在谈什么吗?导出的数据完全无法重复利用。
3. 设计和实施的人员必须十分了解如何对S系统和所有的T系统进行调用。而通常熟悉多个企业级系统的人员很难找到。
4. 每个企业级系统的安全措施都不一样,这样的集成方案要妥善保存和管理多个企业关键系统的保密信息。而诸如调用限制的针对调用者的具体安全策略(policy)更是很难实施。
系统集成、避免点对点实施的害处
为了解决上面的第一个问题,系统集成引进了BUS的概念,每个数据源系统都不再直接与任何数据目标系统直接点对点地进行连接,而是全都连到BUS上。这有点儿像一个组织内部需要开会、而不是个别谈话来有效地解决问题。由此,点对点、一对一的通信变成了一对多,系统的复杂性从O(n2)变成了O(n)。
每个系统在连接到BUS上时需要通过一个特定的机制(见下图橙色部分),叫做联接器(Connector)或者适配器(Adapter),其功能是将每个系统不同的数据形式转换成BUS上通用的数据格式(WireFormat)。这类转换共有四种不同的模式:
- 同步、从系统到BUS:系统将数据送到BUS上,并等待一个回复。系统会等到一个期待的答复(正常结果或错误信息),或者等待超时。
- 同步、从BUS到系统:与(1)相同但方向相反,这次是从BUS到系统。
- 异步、从系统到BUS:系统将数据送到BUS上,然后立即转去做下一步的任务而不期待任何回复。
- 异步、从BUS到系统:与(3)相同但方向相反,这次是从BUS到系统。
有了上面这样的结构,是否就可以进行集成了呢?回到我们上面的开会的例子,很明显,大家都坐在会议桌旁还不够、会议还必须在一位主持人的主持下才能对具体问题进行讨论和处理。从这个角度上看,ESB更像是一条高速公路:高速公路上有不同的出口和入口(就像ESB上连接着不同的数据源和数据目标系统),而行驶的车辆就像是不同系统之间被传送的数据。在看似杂乱无章的车辆行驶的鸟瞰图中,每一辆车的运行其实都在完成一个特定的、有意义的任务, 是某个商业交易的一个组成部分。
与此类似,ESB的作用就是会议桌加会议主持,或者高速公路加交通指挥。有人将ESB的这一作用称之为“协同”(Orchestration),具体来讲可以大致分成以下四种类型的关于数据的具体工作(可以记成“VEST”):
- 验证 (Validation):对数据的正确性进行验证。很多时候数据验证的逻辑是对应与特定的系统的,还有一些验证是在ESB的协同过程中进行的。数据验证的具体项目可以是关于商业逻辑、处理过程和数据格式的,大体对应于“模型-视图-控制器”(Model-View-Controller)。验证的过程可以尽早的发现问题、并妥善处理。
- 丰富(Enhancement):对数据源系统来的数据进行某些处理和添加,比如从生日推算出现在的年龄;将原系统Salesforce中客户张先生的ID转换成目标系统SAP中对应的户张先生的ID;从(第三方)订货系统中调出张先生的购买历史后与源数据一并送到(目标)SAP系统,等等。丰富的过程可以将相关的信息和逻辑与源数据一同送给目标系统, 以方便目标系统的处理。
- 标准化(Standardization):在ESB上飞来飞去的数据从内容和形式上都是应该是统一的。在内容上,使用独立于IT之外的商业数据模型,比如Customer、Order、Payment等等,我们称之为“通用数据模型”(CommonData Model),简称CDM。我们在下一节“集成使用的数据格式”中对此会进行详细的讨论。在形式上,应该尽量采用标准通用的格式,如XML,JSON等,并尽量将数据本身及其元数据安排在一起,让数据的意义不言自明、让即使不懂IT的商务用户也能读得懂数据,而不是像固定数据单元长度或特定字符分隔的csv文件;这些文件需要程序以外的逻辑才能处理。
- 转换(Transformation):由于源系统和目标系统的数据形式千差万别,系统集成的协同过程需要将源系统的数据形式先转换成CDM、并在集成协同的过程中进行处理,即验证-丰富-标准化-转换(VEST),然后在发往目标系统时将CDM再转换成目标系统的数据形式。
集成使用的数据格式
现在我们来看看为了本文开始时“最自然的”集成方式的第二个问题:只言片语的信息。不完整的数据只在特定系统之间的特定流程中有意义,而脱离了这样的上下文数据就无法解释、没有意义。从另一方面看,这一类数据不仅仅是“做什么”的原始要求、也是“怎么做”的解决方案的结果。“做什么”一般而言十分清楚,而“怎么做”却因人而异、千差万别。换言之,前者稳定,而后者不稳定。将“怎么做”有意无意地掺入进“做什么”,必然会造成整个系统的不稳定,应为前者变化的可能性和变化的频率会大大高于后者。
举个例子,如果我们将Customer这个商务概念用JSON来定义,我们会得到如下的结构:
{ "customer": {
"name": "Allen Chen",
"birthdate": "1989-08-28",
"phones" : [
"138-2345-6789",
"130-9876-5432"
]
}}
这样定义的好处是,即使不懂IT的业务人员也能看懂,并告诉你这样的数据模型是否存在问题。而且由于是依照业务模式设计的、完全没有考虑IT技术因素,这样的CDM会非常稳定。如果ESB是将消息传递的模式由“多对多”转换成“多对一 + 一对多”,CDM就是对消息内容的格式做了同样的事情。总的结果是让各个系统之间的耦合大大降低、减少一个系统中的更改对其它系统的影响,将任何更改的影响范围降至最低。
总结
在这篇文章里,我们概要地介绍了对系统集成的需求和历史由来、最初直接的集成方式及其不足之处。我们相应地介绍了BUS的概念、以及BUS是如何在数据传输和数据本身模型结构这两个方面将各个系统之间的紧密耦合解除、使得针对某个系统的更改被局限在有限的范围内,而不至于使其影响范围扩大化。我们还初步介绍了ESB协同操作的具体内容、以及如何设计和使用集成用“通用数据模型”(CDM)。
在下一篇“系列博客(02)– 系统集成的系统化及进一步发展”中,博主将继续介绍关于“服务”的概念、面向服务架构(SOA)的基本概念和企业中SOA实施的具体做法和组织结构,以及实施过程中经常出现的错误,以回答本篇开始时的第三、第四个问题。