《SaaS RES营销管理系统架构设计.doc》由会员分享,可在线阅读,更多相关《SaaS RES营销管理系统架构设计.doc(66页珍藏版)》请在三一办公上搜索。
1、 SaaS RES营销管理系统SaaS RES 系统架构设计目 录1项目背景12关键需求12.1关键功能需求12.2关键非功能性需求22.3关键商业需求32.4关键约束32.5名词解释33参考资料44系统功能分析44.1SaaS模式下功能分析44.2业务功能划分64.3子系统划分65架构设计65.1架构分析65.1.1业务实体的增、删、改及一些复杂的业务处理功能75.1.2对象的查询业务、报表业务125.1.3创建订单典型的高并发资源争用业务155.1.4数据权限控制165.1.5支持多租户的数据结构195.1.6基于单域名的租户访问方式195.1.7租户带宽上的限制205.1.8租户存储数据
2、分离和受限动态路由235.1.9租户敏感数据加密235.1.10可配置性产品模块可配置245.1.11BOSS运营系统与RES业务系统的消息交互255.1.12整合第三方系统企业级服务总线(ESB)285.1.13动静分离285.1.14伸缩性295.1.15安全性应用安全345.1.16安全性数据安全355.1.17安全性网络安全355.1.18监控服务器监控365.1.19监控网络监控365.1.20监控数据库监控365.1.21数据存储365.1.22物理空间扩展375.1.23系统升级375.2逻辑架构385.2.1制作平台和试用平台385.2.2总体架构图395.2.3最小架构图43
3、5.2.4技术架构445.2.5功能模块455.2.6模块架构详解495.3物理架构505.3.1总体架构网络拓扑图(使用存储设备)505.3.2最小架构网络拓扑图(不使用存储设备)505.3.3各层次对硬件的要求525.3.4虚拟化545.3.5模块部署图545.3.6硬件设备555.4数据架构555.5开发架构565.5.1Bundle划分规则565.5.2项目工程划分规则及项目目录结构575.5.3部署目录结构585.5.4开发技术框架使用规则595.6运行架构595.6.1登录和访问流程595.6.2与BOSS运营系统有关帐户信息的交互流程625.6.3与BOSS运营系统有关产品模块信
4、息的交互流程625.6.4与BOSS运营系统有关系统消息的交互流程626架构验证626.1.1性能626.1.2安全性626.1.3可扩展性636.1.4可运维性637风险评估647.1数据库无法支撑大量租户风险(IO瓶颈)647.2高峰期的访问风险641 项目背景SaaS源于一种简单的思想:软件即服务!随着一大批的公司,如国外的Salesforce在这个领域取得的辉煌成绩,SaaS已经彻底改变了人们对软件的观念,使用软件的人从产品消费者转换成服务消费者,而开发软件的人从产品提供者转变为服务提供者。为了顺应当今IT企业级应用的发展趋势和满足公司战略发展的需要,本架构文档旨在描述在SaaS这种商
5、业模式下,如何搭建适合目前公司现状的企业信息化系统。对于SaaS商业模式,简要描述如下: SaaS模式无论是对于用户,还是对于软件开发商都有着巨大的优势。从用户方面来看:用户可以只花少量的资金就可以使用一款软件了,并可以很直观的评估软件是否满足要求或者是否适合公司的管理模式,大大降低了软件产品的资金投入以及风险。另外,用户不需要维护软件、以及硬件本身,可以按照自己的需要定制,按需使用。大大降低了成本。最后,由于软件是托管在运营商,往往有更好的服务保障和防毒措施,用户可以放心的把这一部分的开支节省下来,去投入到更重要的地方。从软件商来看:SaaS模式大大节省了销售的成本,软件商可以把重点资源放在
6、市场推广方面,销售反而是顺理成章的事情。另外SaaS也为软件商节省了维护成本,以往的维护都是一对一的,甚至要到客户现场。这种模式势必导致成本剧增,而SaaS却能保证软件对客户的服务响应快捷和高效。最重要的是SaaS给软件商提供了稳健的经营模式,有利于企业不为销售和各种售后服务疲于奔命,而可以将更多精力放到产品的研发和推广上去,不断提高客户服务质量和系统维护水平。SaaS RES就是SaaS商业模式下的房地产营销管理系统。主要为各个房地产商提供低成本的、按需购买功能的营销解决方案。2 关键需求2.1 关键功能需求 l 与SaaS BOSS运营支撑系统进行交互:SaaS BOSS系统主要对整个RE
7、S业务系统的正常运营起到管理和支撑作用。比如创建租户第一人,配置租户可使用的产品模块,各种系统通知消息,状态查询等等。l 业务实体的的增、删、改及一些复杂的业务处理功能:对于SAAS RES系统来说,业务实体的增、删、改是最常见的操作,它们属于业务实体的维护操作,在系统的产品管理、客户管理、销售管理、服务管理和财务管理模块都普遍存在,这些操作都包括一些数据校验,业务约束等处理逻辑,除了业务实体的增、删、改等数据维护操作外,一些复杂的业务处理功能也具有相当的典型性,这些复杂的业务处理通常涉及多个业务实体的状态变化以及它们之间的业务约束,而且这些业务逻辑很大机会随着业务的发展而变化,因此,如何通过
8、合理的设计来保证以一个清晰的结构来表达这种业务模型,并能够让模型有足够的灵活性来应付将来可能发生的业务变化显得非常的关键,在架构分析中,将会以“客户下订单(即创建订单)”作为用例进行分析。l 业务数据的查询业务、报表业务:对业务数据的查询操作是贯穿整个系统所有模块的业务,而报表业务也是数据查询的一种特殊例子,它们都属于系统中非常典型的功能需求。l 创建订单典型的高并发资源争用业务:这种业务对数据在处理过程中的排他性有非常严格的要求,即业务数据在某个事务处理过程中,绝对不能受到其他事务处理的干扰,“创建订单”用例就是这一关键功能需求的典型用例,在架构分析中将会对如何保证这种事务排他性进行详细分析
9、。l 数据权限控制:数据权限控制是系统的一个典型的功能,客户管理、销售管理、服务管理、财务管理和报表等模块中都有数据权限控制的需求,数据权限控制的意思是:不同角色可以拥有同一个系统功能的使用权限,但不同角色对于同一系统功能,其可操作的数据是有可能不同的,目前系统定义了三个数据权限级别:1)全部:对应功能权限能操作所有相关数据;2)本人管辖的员工负责的数据:对应功能权限只能操作当前用户拥有的数据,以及当前用户所在部门(包括下级部门)的所有员工所拥有的数据;3)本人负责的数据:对应功能权限只能操作当前用户拥有的数据。l 需要整合第三方系统提供附加值,包括用“在线客服”为租户在线的、及时的支持服务;
10、用“SMS”为租户提供短信服务;用“EMail” 为租户提供发送业务邮件和邮件提醒服务。2.2 关键非功能性需求l 租户及用户数量:最大租户数为500。每个租户最大的用户数100,所有租户平均用户数50。平均在线人数约为:12500人。l 并发数:5% * 平均在线人数 = 625次每秒l 性能:系统及时提供相应服务的能力。包括较高的吞吐量、快速的平均响应时间、持续高速的系统处理能力。大部分操作的响应时间控制在3秒以内。l 安全性:系统为合法的租户及用户提供服务,阻止非授权租户及用户使用系统。如用户验证安全性,用户数据安全性等。l 持续可用性:系统长时间无故障运行能力,一年内无故障率达到99.
11、9%(年累计停止服务时间不超过8小时45分钟)l 易用性:系统必须易于使用。系统在升级过程中,降低或避免老客户的适应难度。l 可伸缩性:当用户数和数据量增加时,系统维持高服务质量的能力。如当业务量增大时(比如用户操作频繁或者增加了租户),可以通过增加服务器来提高性能,无需对系统进行编程级修改,也不会对最终用户的使用产生影响。l 健壮性(容错性):系统发生以下情况仍然能够正常运行:用户进行了非法操作;部分软硬件系统发生了故障;其它非正常情况。l 隔离性:减少租户与租户之间的相互影响,租户之间的数据必须良好隔离。l 可扩展性:根据SaaS产品发展需要,系统要较容易的适应新需求或需求变化。l 可移植
12、性:根据租户数量或服务水平,可容易的从一个运行环境转移到另一个不同的运行环境。(数据库的迁移需要暂时服务,其他的升级基本上对用户是透明的)l 可维护性:SaaS系统是由多角色人员一起来运营的。系统的安装、部署、扩展、升级、新租户的加入必须容易,减少出差错。系统运行的监控必须准确、及时。对故障的处理必须简单快速。l 租户端带宽有限:一个租户通常有多个用户使用系统,而访问系统时通常是共享带宽,比如ADSL(处于成本考虑,可能采用上行512K,下行2M)。2.3 关键商业需求l 系统1.0版本的规划最大租户数是500l 系统必须在2009年11初月交付l 该产品能方便IDC运营管理l 系统支持多租户
13、,按租户合同,进行灵活的模块配置,不同租户可以购买不同的业务模块2.4 关键约束l 使用Apache作Web Http Serverl 使用OSGi作应用所在环境(容器选用jetty或者tomcat,待测)l 使用MySQL5.1.3作为数据库2.5 名词解释“租户”:指购买SaaS应用的客户,比如某个开发商购买了RES,那么这个开发商就是“租户”。“租户管理员”:由SaaS服务提供商的运营人员使用。指SaaS服务提供商内部,负责管理“租户”的管理员,该管理员的职责一般是根据合同来添加租户,添加租户的“租户第一人”,修改租户信息,修改租户各种配置信息等。该角色的工作,在运营中一般由“实施工程师
14、”来完成。“租户第一人”:由租户自己使用。这个“租户第一人”是由“租户管理员”分配的,租户可以使用这个“租户第一人”给自己的系统添加用户。“用户”和“账户”在本文的描述中都是只用户用来登陆系统的用户名。3 参考资料SaaS模式系统参考架构设计.doc作者:陈操MSYQL数据库备份与恢复及SaaS下的备份策略.doc作者:莫荣广4 系统功能分析4.1 SaaS模式下功能分析从系统使用者的角度,整个系统的功能模块划分如下:图表 5.1.11 SaaS RES 1.0功能模块划分图l 系统1.0版本的产品只有普通房源,还不包括车位、花园、学籍等房地产附带产品的管理l 销售管理模块和财务管理模块是系统
15、的核心业务模块l 系统支持多租户共同使用,但租户的管理、租期管理等不属于本系统的职责,由BOSS系统负责,系统与BOSS系统进行交互,获取BOSS系统提供的租户相关信息和租户启用、停用通知等信息4.2 业务功能划分4.3 子系统划分下面站在系统构建者的角度出发,按业务处理、报表统计和基础支持三个类别把系统进行子系统划分:图表 5.1.11 SaaS RES 1.0子系统划分图l 租户信息管理子系统主要包括BOSS系统发送过来的租户相关信息,如租期到期提醒信息,租户通知信息的管理l 用户管理子系统包括了用户的身份认证,用户管理和员工、组织架构的管理。5 架构设计SaaS模式的架构设计和普通系统的
16、架构设计有所不同,SaaS除了要满足用户各种个性化要求以外,应用服务器和数据库服务器要满足成千上万的请求,因此,对系统可用性、伸缩性、扩展性以及性能提出了更高的要求。本次参考架构设计的总体原则就是:分割和缓存。5.1 架构分析下面主要综合之前的功能性和非功能性的要求,来对系统的整个架构进行分析。5.1.1 业务实体的增、删、改及一些复杂的业务处理功能分析:对于SaaS房地产营销管理系统1.0(后面统一简称为SaaS RES 1.0)来说,对业务实体的增、删、改、操作是最常见的基础功能,这些操作都有一个共同的特征改变系统中的业务实体的状态(或数据),因此,这里选择基础房间的增、删、改这一典型的功
17、能需求进行分析,以阐述对于这类对业务实体状态产生改变的操作的设计决策。决策:系统使用最常见的层式架构进行设计,按逻辑被划分为:展示层、应用服务层、领域层和数据访问层,下图展示了系统各逻辑层之间的关系:图表 5.1.11 增、删、改操作设计决策图(充血模型)l 展示层:负责为用户提供用户界面,接收用户的输入参数,提交给应用服务层执行相应业务操作,并接收应用服务层的返回结果展示给用户,其直接依赖于应用服务层。l 应用服务层:向外提供业务功能服务,它只负责系统应用级别的逻辑如事务控制、权限控制、日志处理等,以及少量的跨领域对象的业务逻辑,它通过领域层的领域对象仓库获取相关的领域对象,然后调用领域对象
18、的方法完成相应的业务,再把业务结果封装到数据传输对象(DTO)中返回给展示层,这里的DTO是作为展示层与应用服务层的数据载体,它负有装载请求数据和结果数据的职责。l 领域层:包含业务领域内的一系列相关领域对象及其仓库接口,领域对象封装其领域内的业务逻辑,领域对象通过其仓库获取和持久化。l 数据访问层(ORM):提供领域对象的持久化实现,它的作用是把领域对象的具体持久化实现细节封装起来,并利用ORM工具把数据库中的数据转换为领域对象。该层只提供持久化实现,持久化操作的接口由领域层定义,因此,该层依赖于领域层提供相关领域对象的数据结构和持久化操作接口。下面分别以系统中四个典型的功能用例来分别对业务
19、实体的增、删、改以及涉及复杂业务规则的业务操作进行详细分析:用例1:创建个人客户信息业务实体的创建操作创建个人客户信息有如下的业务约束:l 客户的姓名、性别、联系电话、客户类型、是否重点客户的标识这些属性都不能为空;l 客户的姓名和联系电话组成了客户身份的唯一标识。领域驱动设计,或者说面向对象设计的最重要规则是:把不同的职责合理的划分到不同的对象中,根据这一规则,我们对上述的业务约束进行分析:客户属性是否必填,属于客户实体自身的业务完整性约束,因此,这部分职责应该交给客户实体本身负责;客户的姓名和联系电话是客户身份的唯一标识,这意味着系统不能存在两个具有相同姓名和联系电话的客户,这就需要在创建
20、客户的时候进行检查,而这部分工作,对于客户实体来说,它并不了解其他客户实体的信息,因此,应该交由其上层,客户管理应用服务负责。根据上面的分析,我们已经可以清晰的划分职责,然后得出如下的创建个人客户的时序图:5.1.12 创建个人客户信息时序图用例2:修改个人客户信息业务实体的修改操作修改个人客户信息有如下业务约束:l 修改个人客户信息用例包含了创建个人客户信息的所有业务约束;l 当系统设置了需要开启客户信息修改审核功能时,如果修改了个人客户信息中的核心信息,并且修改个人客户信息的系统用户不具有审核功能权限,则修改后的个人客户信息不能直接更新,而是要把修改信息提交审核,审核通过后,才能更新对应的
21、个人客户信息。根据上述的业务约束进行分析,系统是否开启客户信息修改审核功能,很明显不属于个人客户实体的职责,因此它应该由应用服务层负责,同时,由于客户管理应用服务的职责是对客户信息进行管理,而客户信息修改审核功能的设置是由系统参数设置模块负责,所以,这项职责应该由系统参数设置应用服务提供,而判断是否修改了客户核心信息,很明显属于个人客户的职责。最后,根据当前系统用户是否具有审核功能权限,这部分职责应该由客户管理应用服务负责,由于权限判断是由通用权限组件提供的功能权限判断器来提供,前者会把任务委托给后者。经过上述分析,得出下述的时序图:5.1.13 修改领域对象时序图用例3:把个人客户信息放入回
22、收站业务实体的删除操作把个人客户信息放入回收站有如下的业务约束:l 参加过认筹登记的客户不能放入回收站;l 交过钱(存在财务付款记录)的客户不能放入回收站;l 下过订单的客户不能放入回收站l 正在提交审核(被修改或合并后未审核通过)的客户不能放入回收站。分析业务约束,认筹登记、财务记录、订单都属于客户实体的从属信息,即客户实体与上述实体形成聚合关系,按照领域驱动设计的理念,客户实体是上述实体的聚合根,所以,判断客户是否有过认筹登记、财务记录和订单都应该是客户实体的职责,然而我们再进一步分析,实体的职责是相对的,在不同的业务上下文,业务实体所具有的业务职责是不同的,把个人客户信息放入回收站这一个
23、用例,其业务上下文局限于客户管理,因此,在这一范围内,客户实体并没有认筹登记、财务记录和订单等概念,客户实体是一个职责单一的实体,而上述概念分别来源于销售管理服务(包括认筹登记、订单)和财务管理服务(财务记录),对于客户管理应用服务来说,其业务上下文同样与销售管理服务、财务管理服务无关,所以,判断客户是否参加过认筹登记,是否有财务记录,是否下过订单的职责既不应该由客户实体负责,也不应该由客户管理应用服务负责(由于销售和财务是客户的下游业务销售和财务都是基于客户的,所以依赖关系是前两者依赖于后者,如果由客户管理应用服务负责,则客户管理应用服务必须委托销售管理应用服务和财务管理应用服务提供判断结果
24、,这就形成客户管理与销售管理、财务管理形成循环依赖关系,这违背了模块化设计原则)。进一步分析,上述判断逻辑都只是一种查询服务,并不会对任何业务实体产生状态影响,因此,可以通过在客户领域对象仓库中提供一个特殊的查询服务来获取。我们再分析最后一个业务约束,由于客户是否需要审核是由系统设置决定的,因此该判断逻辑同样不属于客户实体的职责范围,应该由客户管理应用服务委托系统参数设置服务完成,综上所述,得出如下时序图:5.1.14把个人客户放入回收站时序图注:该用例表达的是逻辑删除的场景,物理删除的场景与此基本一致,唯一的不同是需要在业务处理的最后通过实体对应的仓库从持久层中把对象删除。用例4:客户下订单
25、(即创建订单)典型的复杂业务处理功能客户下订单有如下的业务约束(注:由于该用例业务功能非常复杂,而且在结构设计阶段,销售模块的需求分析还没完全完成,因此该用例的业务约束将忽略一些不是很重要的细节,该用例的最终模型和时序图以销售管理模块的详细设计为准):l 下订单时可以根据系统参数的设置同时修改客户信息;l 只有状态为“可售”的且有定价的房间可以进行下订单;l 当系统参数设置组合房间可以拆开销售时,组合房间和基础房间都可以下订单,否则,被组合的基础房间不可售;l 根据系统参数设置判断是否可以使用历史价格;l 如果有客户有进行认筹登记,需要对认筹登记进行解筹,并把认筹金额转换为定金;l 需要根据各
26、种优惠及款项信息计算订单的总折扣率和折后总房价;分析业务约束,第一个业务约束很明显不属于订单实体及其他相关实体的职责,由销售管理应用服务委托系统参数设置应用服务进行判断,当可对客户信息进行修改时,还需要委托客户管理应用服务提供修改服务;房间是否可售需要根据房间状态决定,这职责明显是由房间实体负责;已组合的基础房间是否可售,由系统参数设置决定,所以应该由销售管理应用服务委托系统参数设置应用服务进行判断,至于房间是否已经被组合,这是房间实体本身的职责;可否使用房间历史价格,由销售管理应用服务委托系统参数设置应用服务进行判断;对于解筹操作,订单实体包含认筹登记记录,因此应该由订单负责;订单的总折扣率
27、和折后总房价是由订单的各种优惠及款项信息决定的,因此属于订单的职责,但进一步分析,总折扣率和折后总房价可能由不同的计算方式,因此,应该设计一个订单总折扣率和折后总房价计算器实体,并由订单委托其进行计算,综上所述,得出如下时序图:5.1.15 客户下订单时序图这个时序图的设计并不是最终的客户下订单用例的时序图,它主要表达了一个复杂的业务,需要通过合理的抽象以及对业务变化的预见性,建立好合理的模型,并把职责合理的划分到不同的服务或领域对象中,从而得到更好的灵活性或扩展性,这也是领域驱动设计的核心思想。5.1.2 对象的查询业务、报表业务分析:对象的查询业务、报表业务同样也是系统的典型操作,与对象的
28、增、删、改不同,对象的查询业务、报表业务的共同特征是:1)这些操作不会改变业务实体的状态和数据;2)这些操作返回的数据量可能比较大;3)这些操作查询的结果很多时候是跨领域对象的数据视图;4)这些操作通常比较频繁;5)这些操作不需要调用领域对象的具有业务意义的方法。基于这些特征,如果使用“充血模型”设计方法,就会出现一系列问题,下面以基础房间的查询作为例子来说明问题:基础房间查询只需要返回一个符合查询条件的基础房间视图列表,它包括的数据除了基础房间的基本信息外,还包括基础房间的楼栋名、分期名、楼盘名、朝向、景观、开发商名等关联信息,如果直接获取领域对象再转换成数据传输对象,由于领域对象仓库实现使
29、用了ORM框架,返回的都是对象,那么,每个房间领域对象必须要返回其相关联的所有对象:图表 5.1.21 基础房间关联对象类图而事实上,对于该查询业务来说,它只需要这些关联对象中的某一个或几个属性(如:分期对象的分期名称),可以看到,使用加载领域对象的方式有下面的问题:l 加载了大量不必要的数据,严重浪费磁盘IO资源,可能会导致磁盘IO瓶颈;l 创建大量的关联对象,并且需要进行对象关系转换,浪费CPU资源;l 大量对象会导致内存开销大增,在高并发时可能会导致内存溢出;l 加载的对象是领域对象,但查询业务并不需要调用领域对象的任何业务方法;l 应用服务层需要把领域对象转化为DTO返回,这同时浪费C
30、PU和内存资源。这一系列的问题说明,对象查询业务、报表业务并不适合使用“充血模型”进行设计。决策:由于对象的查询业务、报表业务没有对业务实体的状态产生影响,因此严格来说,它们并不属于“业务”,我们可以以一种“查询通道”的方式来实现,查询通道的意思是:不加载领域对象,也不使用ORM,而是直接使用结构化查询语言SQL(对于不同的持久化实现机制,有不同的结构化查询语言,如XML的XQuery、XQL等),通过组合查询直接返回数据视图所需要的数据,并组装成一个DTO返回(注:这只是其中一种实现方案,还有一种比较可行的实现方案是:为需要查询的数据在数据库建立数据视图,然后通过ORM工具把视图映射为一个D
31、TO,这种方式就不需要直接编写SQL语句,但返回的对象并不是DO,而是没有任何业务含义的DTO),下图展示了查询通过的逻辑层关系图:图表 5.1.22 查询业务、报表业务设计决策图(查询通道、贫血模型)与“充血模型”不同,应用服务层绕过了领域层,直接通过查询通道查询数据,并把查询结果直接以DTO的形式返回,下面是使用查询通道查询数据的时序图:5.1.23 查询通道时序图这种方式,免去了加载无用数据、对象关系映射、领域对象与DTO的转换逻辑,从而大大的减轻了磁盘IO、CPU开销和内存开销。注:上图只是为了表达清晰,省略了领域层,实际上,“查询通道”只是一个概念,在实际设计中,会把查询方法都封装在
32、领域对象仓库接口中,实现放在领域对象仓库实现中,所以,应用服务层还是通过调用领域层的领域对象仓库查询接口完成查询业务的。补充说明:DTO即数据传输对象,它只包含数据,没有任何行为,同时,DTO把DO的对象关联关系辗平,成为一个独立的数据视图对象,以房间DTO为例,它不会关联到楼层、分期等DTO,而是把楼层名、分期名作为房间DTO的一个属性,这种设计方式通常称为“贫血模式”,也相当于Martin Fowler在企业应用架构模式一书中所说的“事务脚本(Transaction Script)”模式。另外,对于一些变化频率很低或者不会发生变化的数据,如很多页面的下拉菜单数据等,为了减轻数据库服务的IO
33、压力,还需要采取缓存策略。5.1.3 创建订单典型的高并发资源争用业务分析:创建订单是整个系统一个非常重要的业务功能,它在一些特定的时间,如五一、十一等开发商促销的时间并发性比较高,由于同一个房间在同一时间只能下一张订单,这里就涉及一个在下订高峰期房间争订的情况,系统要保证不要出现同一房间被不同两个客户下订的情况。根据创建订单的业务规则,订单只能预订状态为“可售”的房间,当下订成功后,房间状态被改变为“已售”,要保证不出现上述争订的情况,事实上就是要保证在整个订单创建过程房间状态数据变化的排它性。决策:由于系统使用Hibernate作为持久化框架,我们可以利用Hibernate提供的为数据库相
34、关数据上“锁”的功能来保证数据变化的排它性。Hibernate提供了两种数据锁定机制:悲观锁和乐观锁。悲观锁对数据的处理采取一种保守的策略,即在整个数据处理过程(完整的事务)中,对目标数据上锁,以保证事务以外的其他操作都无法在此事务提交前对目标数据进行修改,悲观锁的实现通常依赖于数据库提供的锁机制。乐观锁采取比悲观锁相对宽松的策略,它的原理是,为数据增加一个用于记录“版本”的字段,当事务读取数据时,会把数据的版本号也一并读取,当事务修改了数据后,Hibernate会自动把该数据的版本号加1,然后在提交事务前,把该版本号与数据库中的对应数据的版本号进行对比,如果该版本号高于数据库记录的版本号,证
35、明在事务过程中没有其他事务修改并提交过对应数据,事务被提交;如果该版本号不高于数据库记录的版本号,则说明事务过程中已经有其他事务修改了该数据并提交,事务提交被拒绝。对比两种策略,我们发现,两种策略达到的效果是一致的,但悲观锁更加严谨,保证先开启的事务对数据有主动权,但同时,它却带来了数据库性能的大量开销,因为在整个事务过程中,所有其他事务都无法修改被锁定的数据,尤其对于长事务,这种开销更加明显。乐观锁不能保证先开启的事务对数据占有主动权,实际上是先提交的事务才会被成功提交,但乐观锁基本不会浪费数据库的性能开销,而且不依赖于数据库的锁机制实现。创建订单是一种高并发的操作,每个房间在整个下订过程只
36、被一个客户占有,这显然是客户不能接受的,而事务孰先孰后,对于客户来讲却是透明的,很明显,我们应该采用Hibernate的乐观锁策略来避免房间争订的情况。创建订单只不过是整个系统的其中一个典型的功能点,对于其他类似的功能,如财务收退款这些敏感操作,我们都需要采用相同的策略对数据进行锁定处理。5.1.4 数据权限控制SaaS RES 1.0在客户管理、销售管理、服务管理、财务管理和报表等模块中都有数据权限控制的需求,数据权限控制的意思是:不同角色可以拥有同一个系统功能的使用权限,但不同角色对于同一系统功能,其操作的数据是有可能不同的。目前系统定义了三个级别的数据权限:l 全部:对应功能权限能操作所
37、有相关数据;l 本人管辖的员工负责的数据:对应功能权限只能操作当前用户拥有的数据,以及当前用户所在部门(包括下级部门)的所有员工所拥有的数据;l 本人负责的数据:对应功能权限只能操作当前用户拥有的数据。分析:SaaS RES 1.0对于功能权限和数据权限都有需求,对于功能权限控制,系统采用公司开发的通用权限组件2.0实现,同时,由于系统的数据权限是根据组织架构进行划分的,数据权限控制的组织架构还会采用公司开发的通用组织架构组件实现,通用权限组件2.0以一种事件拦截的机制来实现基于RBAC的功能权限控制,其原理如下图:图表 5.1.41 通用权限组件2.0原理图当用户试图访问系统的功能服务时,功
38、能权限拦截器会首先把用户的请求拦截下来,然后把用户信息和请求信息发送给功能权限控制器,功能权限控制器会根据用户信息从权限数据库中获取该用户的授权信息,即角色集合,然后再获取这些角色的功能权限集合,最后判断出该用户是否拥有其请求的功能服务的访问权,如果有,则请求被传递给相应功能服务,如果没有,请求被拒绝,并重定向到拒绝访问的错误页面。使用权限组件这种拦截机制的好处是:把基于角色的访问控制逻辑彻底的从业务逻辑中分离,业务开发人员只需要关注业务,无需编写任何权限判断的逻辑,这大大减轻了业务开发人员的工作量,也提高了系统的灵活性。如果说基于角色的访问控制权限与业务无关,那么数据权限却与业务有比较紧密的
39、联系,比如:销售团队A的普通销售员只能跟踪自己的客户,但其团队主管却可以跟踪团队内所有成员的客户。这些可以看作是系统业务的一部分,但对于SaaS RES 1.0来说,这种数据级别的权限控制是相对稳定和单一的,如上所述,它只有三个级别的数据权限。对于数据权限控制,权限组件2.0只提供了扩展的机制,并没有提供具体的实现。决策:根据上面的分析,我们可以有两种方式实现数据权限控制:l 直接在业务代码中编写数据权限控制的逻辑,把它视作业务逻辑的一部分;l 通过权限组件2.0提供的框架进行扩展。上面提到,SaaS RES 1.0的数据权限控制是相对稳定和单一的,这就意味着,数据权限控制的逻辑有很高的重用可
40、能性,如果采取第一种方式,业务开发人员就不得不关注数据权限控制逻辑了,而且把数据权限控制逻辑交由业务开发人员实现,代码就很容易失控。权限组件2.0虽然没有提供数据权限控制的实现,但它却提供了一个良好的框架,让业务系统可以在框架的基础上进行扩展,实现数据权限控制。可以看到,两种方案都需要编写等量的数据权限控制代码,但后者可以让系统的结构更加清晰、合理和容易维护,因此,后者是一种更合适的选择。其原理如下图:图表 5.1.42 权限组件2.0中数据权限扩展原理图用户的请求还是先要进行RBAC的功能权限判断(见上述说明),当通过了功能权限判断后,用户请求会进一步被传递给访问前权限处理器,这里的“访问前
41、权限处理器”就是权限组件的框架提供的一个扩展点,SaaS RES 1.0需要实现此处理器,它的作用是进行数据权限处理,判断当前用户对目标数据是否有操作权,如果没有,则直接拒绝访问,如果有,则可以对用户的请求进行加工,最常见的做法是,为请求添加上数据筛选过滤条件,如:用户发起了一个获取客户列表的功能请求,该用户是销售团队A的普通销售员,访问前权限处理器发现普通销售员这个角色的数据权限级别是“本人负责的数据”,则对该请求进行加工,为其添加上“数据拥有者标识”作为筛选条件,然后再把请求发送给业务系统的对应功能服务。当服务处理完后,返回结果又会被进一步传递给访问后权限处理器,“访问后权限处理器”同样是
42、权限组件框架提高的扩展点,可以通过实现此处理器,对返回的结果进行加工,比如屏蔽某些敏感数据等。通过这样的设计,利用权限组件框架提供的扩展点,既能很好的实现系统对于数据权限控制的要求,也让数据权限控制的逻辑和功能权限控制逻辑一样,从业务系统的业务逻辑中抽离,使系统的结构更加合理和灵活。5.1.5 支持多租户的数据结构由于目前已经确定使用MySQL作为数据库的约束,要支持多租户,我们有以下三种方式可以选择:1.每个租户都有独立的数据库2.租户共享同一个数据库,但独立数据结构(即一个租户对应一个schema)3.租户共享同一个数据库,且共享相同的数据结构。(即一个schema被多个租户共享)对于以上
43、三种方式的比较,可以从下表看出:隔离性安全性成本独立数据库高高高一个租户一个schema中中中多个租户共享schema低低低图表 5.1.51 三种支持多租户数据结构方式比较图第一种方式,似乎和传统的软件没什么区别,只适合高端用户和隔离性要求很强的用户,比如医院、银行等等,对于普通的租户情况不适用,因为成本太高。第三种方式,隔离性差,且难以迁移、备份和恢复数据。因此,我们目前选用第二种方式,即一个租户一个schema的方式作为目前支持多租户的数据结构。5.1.6 基于单域名的租户访问方式由于用户访问方式是单域名的,比如举个例子来说,登陆流程是这样的:1.用户usera想进入系统,由于未登录,会
44、被应用引导至登陆页面进行登陆,比如2.用户usera提交用户名和密码3.系统验证账户的有效性,如果账户有效,那么系统会查找出usera是属于租户A的,接下来构建租户A的有效路径返回给usera,类似 (注:在存在租户个性化页面定制和按租户分区访问情况下,url需要包含租户标识,如4.用户usera进入正确的访问地址了,如同样的,如果userb属于租户B,想要登陆系统,同上面的步骤相同。考虑到可能要同多个系统做整合,因此,我们需要在多个系统之间做到单点登陆。Web环境下的单点登陆,业内已经有了很多解决方案,比如著名的CAS和OpenID等等。在这里,我们使用公司的单点登陆组件(基于CAS)。就目
45、前而言,单点登陆的账号和密码等信息是存放在数据库中的(MySQL)。在将来,也可能会将这些数据移植到LDAP中去。5.1.6.1 用户账号规则按照目前的规划,用户账号的命名规则由租户自己决定。举个例子来说:租户A新增了usera,userb这两个账户,那么租户B就不可以新增同名账户了。5.1.7 租户带宽上的限制SaaS模式下,应用都是基于互联网的,因此最终用户也是通过互联网来使用SaaS应用的。而目前的信息化程度,对于大多数最终用户来说,都是在共享带宽的环境下使用互联网,比如ADSL(上行512K,下行2M)。这就可能会出现多个用户在共享的带宽下同时访问我们的SaaS应用的情形,要使得这些用
46、户获得良好的响应速度和体验,就要求我们的SaaS应用不应该占用过多的带宽资源。因此,这对我们的设计提出了更高要求,要尽量的减少网络带宽的占用,减少不必要的网络传输,提升web的性能等等。下面列举影响Web性能的主要因素:5.1.7.1 影响web性能的因素1. 页面过大:页面在500k以上2. 图片和iframe过多:会导致增加请求数3. Cookie内容过大:会导致发起请求变慢5.1.7.2 三十四条黄金守则著名的雅虎为我们提供了网站性能上的三十四条守则,这些守则可以约束我们的设计,总结列举如下:5.1.7.2.1 内容类 减少http请求 减少DNS查找 避免跳转 缓存ajax 延迟加载 提前加载 减少DOM元素