SAAS相关技术要点
这篇文章本来是我们开发组内部用的一个小文档。因为我们公司以前没有做SAAS的经验,就成立了一个小组做一做这方面的技术前探,我是成员之一。这篇文档想从宏观的层面把开发一个SAAS应用所要用到的技术点稍微梳理一下,便于指导后面的技术前探工作。之所以发在这里,是因为自己相关的研发经验太缺乏,可能有些技术盲点是自己根本没能考虑到的,希望园子里的各位大牛多多指导。
一.聚焦“三头怪”
在MS的官方文档中,把构建一个足够成熟的SAAS(MS简单列出了SAAS应用的4级成熟度)所面临的3个主要挑战:可配置性,可扩展性,多用户存储结构设计称为“three headed monster”。在MS给出的两个SAAS的demo(分别为LitwareHR和Crab)中,着重解决的也是这三个问题。所以,我们在进行技术前探的时候,也要扣准这三条主线。
1.概念
SAAS是一个典型的“单实例多处应用”的软件类型,这就要求实例本身在不同的应用环境下有很强的配置能力。具体说来,需要对以下4个方面提供配置能力:
(1)程序的外观。
(2)工作流程与业务规则。
(3)数据模型。
(4)用户及最终用户的存取权限。
这种自定义的能力应该在易配置性和配置能力两个方面做好权衡,最优的结果当然是通过最方便的配置手段来实现最复杂的自定义功能,但这并不容易做到,所以有可能我们会需要为一些比较高级的用户提供基于已有系统的二次开发能力(使用脚本等)。下面我们就具体来谈一下关于可配置性的各个方面。
2.配置的实现基础:元数据(MetaData)
系统通过配置数据展现不同的外观和行为,那么对整个系统来说,配置数据就是系统中的元数据。笔者自己也没有特别研究过元数据,仅仅是开发中用过一些xml文件或者数据库中的特定表来保存一些配置信息,但对于一个成熟的SAAS应用,这种简单的配置方式可能是不够的。如何设计出结构灵活、功能强大、兼容性好的元数据结构,如何在代码中提供最有效率的元数据服务(Metadata Service),如何定义元数据的元数据(Metadata of metadata),如何保证在元数据结构发生变化的时候不影响程序的运行,这一切都需要我们在对元数据本身的语义特性和可能的技术支持手段进行过调研之后才能得出。另外,笔者在写这篇文章的时候,很偶然在网上找到了几幅关于元数据服务层设计的图片,很有意思:
上面这幅图的上半部分给出了SAAS参考体系结构的一个概念模型,下半部分则给出了对应于体系结构的每一部分,现有的可能采取的技术手段。我们注意到,元数据服务和元数据数据结构定义是里面唯一的盲区。
下面这个图是Matias Woloski给出的对各主要配置模块(界面、业务规则、多用户数据结构、访问控制)提供的元数据服务的可能解决方案,也许可以做为我们进一步深入的一个线索。
3.配置的需求基础:业务共性提取与业务个性分析
为什么是所有tenant共享一套代码?因为所有这些用户在软件需求上有共同的需要,在业务流程上有很多共通的地方,他们所有的应用都是在一个比较确定的业务领域(Business Domain)内展开的。我们需要把这个业务领域内的业务需求梳理清楚,然后提供我们的软件为这个业务领域服务。既然他们都属于一个业务领域,那么我们提供一套可以运行的软件就行了,为什么还要提供那么强的配置能力呢?因为同属于一个业务领域内的客户,他们在业务规则的细节上其实有很多不同,业务流完全相同的两个企业其实是不存在的。另外,每一个企业都在不停的发展变化,业务结构也都在不断的调整、重整、升级过程中,我们的软件应该可以在一定的弹性范围内,支持企业的这种升级。
所以,研究我们的SAAS软件所要解决的业务领域特点,找出这个领域目前在横向范围内的企业业务间的差异性,以及在可以预见的将来的业务升级要求,其实是实现SAAS软件最开始的、也是最难的一步。但这一步骤本身和技术的关系可能并没有那么大,所涉及的最多也能也就是包含UML在内的众多领域建模技术。这一部分应该属于SAAS研究中业务和技术结合、同时业务占据的比重更大的一部分内容。
4.配置主要内容1:程序外观的配置
外观的配置其实包括的内容很多,但比较核心内容笔者认为是界面元素的多粒度模块化,只有实现了这一点,才有可能让用户在多个粒度级别上去定义自己想显示什么、以什么样的界面风格去显示。这一点上也一直是笔者认为.Net比较有优势的地方,因为MS的产品一直在构件化上面表现不俗。仅就Asp.net2.0中,已经有Custom Control,User Control,Web Parts,Theme, Skin, MasterPage等成熟界面技术可以使用;在.Net3.0的WPF(现已更名为SilverLight)中,相信更有很多优秀的模块化界面技术的出现,笔者尚未研究过。这些都需要我们去学习和发现。
另外,如果我们继续采用基于浏览器的软件系统,Web程序的“体验本地化”是必不可少的工作,在这方面AJAX技术已经越来越成熟,MS的AJAX 1.0正式版已经发布。
我们在学习这些界面技术的时候,不仅要学习它们的使用方式,还要明白它们底层的编译模型和运行模型,这样我们才能对每个显示模块对象实例如何以最小的运行成本来完成尽可能多的界面显示和交互响应功能有充分的把握。
5.配置主要内容2:业务流程的配置
所谓业务流程,不知笔者的理解是否正确,其实应该属于经典的工作流(workflow)问题。所以这一方面尽管非常重要与复杂,但研究起来重点却最为突出,无非就是两个:
(1)对工作流方法论的研究。笔者没作过关于工作流的开发项目,在这方面暂时没有发言权,但笔者认为在利用工作流相关的工具和类库进行开发之前,应当在方法论上对工作流有一个比较有度的把握。
(2)对各种现存的工作流工具的研究。工作流是企业开发的重点,相关的产品应该不少,笔者知道的主要工具如下:
a.WF(Microsoft Workflow Foundation), 这是.Net3.0新增的三大类库之一,专门用于对工作流技术的支持。
b.BPEL(Business Process Execution Language),这是由IBM牵头搞的一个利用XML来描述业务过程行为的标准,目前在业界也得到了广泛的支持和应用。当然,BPEL并不完全等同于工作流,它对人、角色、工作项目等并没有明确定义,重在刻画一个基于Web服务的业务流程。
6.配置手段的易用性
一个被广泛接受的观点是,易用性可能成为一个SAAS软件成败的关键。作为SAAS应用的使用者,肯定会关心是不是他的每一个员工都能很容易的使用这个系统,这其实是企业部署SAAS应用的主要成本之一。而在整个系统的操作中,对外观和业务流的自定义配置很有可能成为最复杂的部分,这部分操作的易用性也将直接影响整个软件的易用性。
想增强配置手段的易用性,需要我们多向salesforce这样的成熟SAAS应用学习取经。
三.可扩展性及相关技术
1.概念
应用的可扩展性包含两个方面的要求:(1)高效地利用应用资源,从而最大限度地提高并行性。(2)当原先的服务器资源确实无法满足不断增加的用户数量时候,可以很方面的通过向上扩展(提升硬件性能)或横向扩展(增加硬件数量)来提高整个系统的并发处理能力。可扩展性并不仅仅是SAAS面对的难题,所有基于Internate的大型网络应用队会面对这样的挑站,所以网络上相关的资料很多,大多谈及大规模企业应用的体系结构设计的主题,都会涉及到对可扩展性问题的讨论。笔者自己没有开发过大型的应用系统,更详细的知识点需要进一步的学习和了解之后才能给出,下面暂时只能简单列出一些笔者以前接触过的内容作为可能的技术研究点如下。
2.可扩展性支持技术1:应用的无状态模式
我们需要研究如何设计应用,使之运行在无状态模式下。也就是说,所有必需的用户和会话数据都存储在客户端或分布式存储设备上,任何应用实例都能访问。无状态是指每个事务处理都能由任何实例来完成,用户在一次会话中可用众多不同的实例进行事务处理,但用户本身并不知情。比如我们在做Asp.net开发的时候,如果用Session变量来存储状态信息,因为它需要占用服务器资源,当你想增加机器以扩展性能的时候,它们会起阻碍作用,因为Session是与特定机器相关连的。在这方面,也许我们可以参考EJB中的关于无状态会话Bean,以及其管理器无状态管理器的实现。其实,internet能发展到今天的规模,跟http这个无状态的协议应该有很大的关系,而internet的扩展性已经在现实世界中被印证了,所以如果我们能尝试着去理解整个因特网的结构特点,也许我们对如何建构一个高可扩展性的大型系统会有更深的了解。另外,从SOA的角度来讲,提倡的Service一般是Stateless的,给定什么样的输入,就会有对应的确定的输出。一旦服务有了状态,就无法方便的使用对象池来减少对象的数量,从而提高了负载。
3.可扩展性支持技术2:大型数据库的分解、重构技术
MySpace是一个过亿注册用户的超大型网站,在三年的发展过程中,它完成了从一个单服务器到及具扩展性的架构的变化,我想种变化其实对于我们研究如何建立一个可扩展的系统其实有很强的借鉴意义:
(1)最早。两台Web服务器,一台数据库服务器,和我们目前的结构是完全一样的。在初期的发展中,MySpace就是通过添加新的web服务器来提高性能的,直到其数据库服务器过载。
(2)50万用户。要增加数据库,这时候面临着保证数据一致性的问题。在第二代架构中,他们启用了3个SQL Server数据库服务器,一个为主,接受所有的数据提交,并将内容复制给另外两个,由它们全力向用户提供数据。在这个架构中,通过增加辅数据库服务器的方法,可以有效应对系统访问量的增加。
(3)100-200万用户。数据库服务器开始受制于I/O容量。这时候,把所有业务放到一个DB上看来已经不行了,于是他们对数据库的架构进行了垂直分割,不同的数据库服务器服务于不同类的功能,有的负责登录,有的负责博客等。另外,但用户达到200万的时候,他们启用了存储区域网络(SAN:Storage Area Network)。按MySpaces的说法,此举极大提升了系统的性能、正常运行时间和可靠性。
(4)300万。垂直分割不够用了,毕竟有些信息(如用户表)需要在所有DB中共享,维护数据一致性的开销很大。另外,有一些应用增长太快,其专用DB压力太大。这时候,需要进行向上扩展(Scale Up:升级服务器)和向外扩展(Scale Out:加强分布式能力,用大量便宜的服务器来分担压力)的抉择。为了尽量少改动以前的代码,他们先考虑了向上扩展,研究了如何使用32CPU的服务器的问题。但最终,他们还是走上了向外扩展的道路,开始提炼分布式计算架构(这是向外扩展架构必须面临的问题,大厂商如Google甚至开发了自己的分布式文件系统)。这时候,前面被拆分的应用在逻辑上又被整合了起来。并且,用户以百万为一组,被分别存储不同的DB。当然会有一个特殊的DB来控制所有的帐号和密码,但其功能单一,也就比较容易控制负荷。
(5)1000万。采用了新型的SAN,更改了SAN和数据库的绑定方式。在Web服务器和数据库服务器之间加上数据缓存层---他们说这是一开始就应该做的事情,但他们成长太快,以至于一直没有实现。
(6)2600万。采用SQl Server2005,因为支持64位的数据库可以使用更多内存。
从MySpace的变化可以看出,随着用户量的增加和用户数据量的积累,数据库服务器将日益成为瓶颈。在它成为瓶颈之前,充分做好各种相关的技术准备工作是必须的。
4.可扩展性支持技术3:线程和网络连接等汇集资源的共享(负载均衡)
将线程、网络连接和数据库连接等资源集中,这有助于使计算资源最大化,并提高我们预测资源使用的能力。当然,在这些方面,其实IIS和ADO.NET等基础的资源服务系统已经作了很多相关的考虑,我们做的资源调度应该是基于这些服务器之上的。我们可以参考.Net对线程池的管理,也可以参考ADO.NET对连接池的管理。另外在进行资源调度和管理的时候,要充分考虑整个网络的拓朴结构,并充分借鉴分布式系统在实现方式特别是资源调度算法上的一些考虑和特点。
所以,这里总的来说强调的是一种负载均衡的概念,而负载均衡除了上面提到的这些软件方面的手段,可能还包括对一些硬件设备的认识和选购,特别是对各种负载均衡服务器的性能和功能的掌握。
5.可扩展性支持技术4:其他
(1)多级缓存技术。缓存,说白了就是用空间换时间。越是并发的系统,越需要仔细考虑缓存的问题,我们每发现一处可以在多用户间反复重用的数据并将其加入缓存,都有可能使这部分数据的生成效率提高上千倍(如果这个数据可以在上千个用户间共享的话)。另外,如何提高缓存的命中率,也是当我们的网站逐渐变大之后,越来越重要的问题。还有,对于memcache这类的比较牛的缓存解决方案,也许我们也需要深入研究它与我们项目的结合点。
(2)仔细研究数据库的锁定方式,在对数据库操作的时候,尽可能锁定小范围的数据集合。采用既可以实现并发最大化,同时还能使排它锁定最小化的方式写入数据库操作。例如,在执行只读操作时,不要锁定记录。这些环节看似虽小,其实对整个系统的并发性都有显著的影响。
四.多用户存储结构设计及相关技术
一家公司的用户使用我们的SAAS应用服务存取客户信息时,该用户连接的应用实例同时可能还会为其他几十家,甚或是数百家公司的用户提供服务,各用户之间彼此互不知情。这就要求应用架构能够最大化不同用户间的资源共享,不过仍要区分属于不同客户的数据。所以,我们在设计存储结构的时候,一方面要考虑结构本身的可扩展性,一方面还要考虑数据访问的安全性。
1.数据访问控制
数据是不是安全,会不会被没有权限的人窃取或篡改,这是用户最关心的,因此也是我们最关心的。安全问题涉及的内容也确实是非常多,笔者这里试着从几个方面简单进行阐述:
(1)过滤:在用户和数据源之间加入中间层,给用户的感觉是数据库里只存了自己的数据。
在这方面,典型的手段是采用视图。
(2)权限:采用ACL来限制谁能访问什么数据,以及可以对数据作什么操作。
在这方面,有一个很关键的问题是如何建立一个受信任的连接。比较常见的方式有服务器模拟客户端用户的身份(impersonation)去访问数据;或者服务器始终以自己的进程身份来访问数据(受信任的子系统方式),额外的安全都放在应用的内部。前一种方式配置上比较复杂,但安全性较高;后一种方式不需要太多配置,但安全性较低,并且有些资源单靠服务器进程本身的访问级别是访问不到的。我们在开发的时候可能需要混合使用这两种连接方式。
另外,有些时候可能需要服务器以代理的方式来访问一些其他资源。
(3)认证(Authentication)
前面几点说的都是对于某个特定的用户,系统如何控制他的访问权限(也就是说,都属于授权/Authorization方面的问题),那么系统如何知道某个客户端请求确实是来自某个用户呢?这就是Authentication要做的工作。单就这一部分,包含的知识也相当多,以Asp.net2.0为例,就有Windows验证、基于表单的验证等;单就Windows验证,又有Kerberos,NTLM等不同的验证协议,这些验证协议在对代理服务器的支持、运行效率上都是有差别的,需要我们学习和掌握。另外,在.Net3.0中,MS在这一块儿好像又提出了一个新的概念和实现技术,CardSpace。这个技术里应该是凝结了MS对网络安全的最新思考,笔者觉得应当重点关注(此技术和Active Directory, WCF, Windows Live ID等技术都有很强的相关性)。
还有,从宏观上来看,认证的方式分为集中式认证(centralized authentication system)和非集中式认证(decentralized authentication system)两种,我们需要研究它们之间区别和联系,结合起来利用。
(4)加密
对用户的敏感数据进行加密,未授权方及时获得了这些数据也派不上用场。可以采用对称或非对称的加密算法。非对称算法的保密性好,但处理开销也大得多。实际操作中,一般是两种方式混用,即数据采用对称加密法,但用非对称加密法来加密对称密钥。
其实,和安全相关的问题还有很多,比如sql注入,代码安全等等,这里就不一一详述了。
2.可扩展的数据结构
关于这一部分,MS在其白皮书中的第二章《多用户数据体系结构》中已经有了比较详细的交待,本文中就不再重点介绍。可能采取的数据结构有:(1)独立数据库;(2)共享数据库,不同用户有不同架构;(3)共享数据库,共享架构。一共是三种方式,这三种方式的资源利用率越来越高,但在设计上也越来越复杂。所以,也并不是共享的程度越高越好,下面这幅图说明了如何在数据库的独立和共享性上面做以取舍:
对于三种模式中最复杂的“共享数据库,共享架构”,MS给了两种建议性的方案:预定义扩展字段以及名值表。一方面,我们可以参考这些方案实现,另一方面我们也可以思考自己的方案出来。另外,不管数据存储到底采用哪种方案,都要为数据表以后可能的横向或纵向切分留下余地。从数据库的横向扩展来看,主要的手段是复制和分组,具体如何去做都需要进一步的研究。
五.SAAS与SOA
SAAS指的是一种软件商业模式(特别是营销模式),而SOA指的是系统的实现(包括已有系统的整合)方式,两者本不在一个概念层上,但笔者在这里还是想强调一下两者之间的关系,特别是SOA的相关技术对SAAS的重要性。因为在SOA身上体现了业务整合、业务敏捷等众多特性,正是SAAS所需要的。特别是业务敏捷,虽然它强调的是一个企业业务在纵向时间轴上的变化和软件的应对,而SAAS更强调在同一时间点上同步厂商之间的业务区别,但两者在技术要求上并无本质区别。
另外,SOA已经渐渐成为企业应用开发的标准,我们的用户除了采用我们的SAAS软件,很可能还使用了很多其他的应用系统。为了能让我们的系统更开放,和其他的周边系统有更好的交互,一种SOA的思想和技术手段将在我们的开发中必不可少。
SOA本身也是一个技术集,涵盖的面非常广,本文在此就不展开了。
六.其他技术
1.单点登录
对现代网络应用易用性的基本要求之一,至少在我们系统内部,我们要做到用户一次登录,即可访问所有他有权访问的所有子系统。
2.对SAAS树状体系结构的进一步认识
SAAS本身是一个从服务提供商到各个企业,从企业到各个部门,从部门到每个最终用户的树状管理结构,这样的一个结构包含一些可以利用的技术特点:
(1)安全权限的继承性
系统的授权(Ahthorization)一般都是根据用户组/角色/Role来进行的,在对授权的管理上,MS提出了一个“配置域”的概念。存取控制由配置域管理。每个配置域根据应用的关系策略继承上级配置域的角色、许可和商务规则,并可在适当的时候对其进行修改、添加和删除。从概念上来说这是非常合理的,比如一个企业内的部门是一个配置域,它的上级配置域就是企业,而下级配置域可能会具体到每个最终用户(也可能是部门内的小组)。但具体实现的时候如何去做,还需要我们进一步研究并给出方案。
(2)用户的不同等级
按MS的文档,将用户区分为“用户”和“最终用户”。其实这里的“用户”指的就是一个单位或组织,不同“用户”之间的数据至少在逻辑上是互相隔离的。而“用户”可以为自己企业内部的多个“最终用户”授权,最终用户最终能在用户的控制之下访问到用户数据的一个子集。
这种把用户分成等级来处理的方式是很有意义的,比如在建立受信任连接的时候,就可以采用用户模拟和非用户模拟两种方式的结合。对用户采用模拟方式,对最终用户采用非模拟方式。比如在存储结构设计的时候,可以给用户单独建立数据库。
3.活动目录
如果我们所有的数据都取自关系数据库服务器,那么可能永远不需要活动目录。但有些资源是存储在文件系统中的,这就需要活动目录为我们提供存取服务了。我们需要研究原有的Active Directory技术,以及刚提出的ADAM(Active Directory Application Mode)等技术。