一套较完整的技术框架
1 引言
1.1 前言
本文将基于目前现有的软件开发架构(以下简称‘架构’)(Packer for Delphi),同时如何合理地引进新技术等问题,进行系统地分析和研究,以指导新架构的研发。
1.2 研发依据
1.2.1 公司发展
1.2.2 开发方式
1.2.3 技术升级
1.2.4 产品线
行业领域软件需要个性化的服务,如果对应以作坊式的开发方式,将会陷于项目越多,版本也越多,维护成本也随之上升的局面。
针对行业领域软件特点,在以产品线为设计思路的业务架构建设中,需要对应的技术架构来配合完成。
1.3 研发前提
1.3.1 公司产品开发的范围
1.3.2 软件开发架构在产品开发中所处的位置
软件开发架构,是一个承上启下、集成应用开发领域的通用的各种技术而形成的一整套的开发体系框架,它包括如下的几个方面:
1、可持续的框架体系:
一个用于明确管理界定各种功能及其关系的框架体系,每个功能点在架构中由于其特性必然有着明确的位置,各种相关技术也由架构来完成其相互的无缝接入。并且通过这种可持续化的特征,能将技术的、业务的工作管理起来,并持续的发展。
2、技术的集成和整合:
随着应用领域的拓宽,这些技术会不断的拓展,包括如:工作流技术,安全技术,消息服务技术,即时通信技术,门户技术,数据交换技术,全文检索技术等等。说到集成,就是指除了这些技术本身之外,架构提供对这些技术的整合,将这些技术本身放在整体框架的某个部分和层次。技术的整合不是简单的拼装,做得好坏,取决于长期的经验和技术的积累,否则再好的技术,整合起来往往得到的是最差的东西。
3、更为细节的规范:
为了程序的易于理解和维护,便于细化分工,架构将尽可能的减少异化,尽可能的标准化开发过程和代码格式。这些规范可能会细化到如:打开关闭连接的时机,命名空间的管理,文件名称的定义,代码缩进的长度,使用的开发和设计工具等等这样非常细节化的东西,从而保证一致性。
4、标准、简单,机械化的开发过程:
追求将开发过程1234化,避免思维的漏洞,将思维上的一种或者几种有效的开发套路固定为外在的规范,并且通过一系列的工具将其持久化。
5、最终的追求--软件生命周期的管理:
这样的一个架构,最终追求的是对一个完整的软件生命周期的管理,不仅仅是开发的过程,还包括规划,需求,设计,测试等一系列的过程。
总之,架构是为应用系统的开发,提供一套集成的、适合自身软件开发过程的技术规范、开发准则、通用组件、辅助工具等等,使得应用系统的开发更加高效、方便、统一,为软件大生产的开发提供物质保障。
1.3.3 技术平台的选型
开始架构研发之前,必须先对架构的基础-技术平台,进行选型,否则将是无本之木,一纸空谈。
纵观当前流行的技术平台,不外乎两大阵营:J2EE和.NET,以下是针对几个指标进行的一个评价:
|
J2EE |
.NET |
开放性 |
好 |
差 |
应用范围 |
Web应用 |
Web应用或者非web应用 |
开发工具成本 |
低廉(开源) |
一般(专用) |
开发资源成本 |
高 |
一般 |
开发效率 |
周期长 |
快速 |
运行性能 |
差 |
一般 |
运行资源成本 |
高(捆绑专用服务器) |
低(分布式PC服务器) |
部署效率 |
差 |
一般 |
界面丰富与灵活性 |
差 |
高 |
与服务商绑定 |
高(SUN、IBM) |
高(MS) |
关于J2EE和.NET之间的讨论已经持续很多年了,而且也将继续争论下去,孰优孰劣仍然很难下结论。
适用的才是好的,作为IT企业,从公司产品的受众、研发、推行、维护的成本与收入等等上来考虑,自然会得到一个明确的答案。
对于ERP等生产管理系统,系统性能、丰富的表现与交互界面是关键的技术要求之一,在非web应用的软件研发上将主要基于.NET开发平台。
同时,为了兼顾效率,可以结合Win32的开发工具(Delphi/C++)开发部分实时性要求很高的应用系统,对于这点,.NET自身可以很好的与Win32进行整合。
1.4 系统名称
1.5 中期计划
1.6 资源计划
2 参考文献
3 功能分析
通过分析归纳,技术架构的开发,只要针对如下几大项的功能点进行研发,基本上可以支持目前所遇到的大部分技术需求:
项目 |
内容 |
支持双语 |
双语是指开发出来的应用系统,应该在表现层上,只要根据用户的简单选择,就能提供中文、英文之一种语言显示效果。 提供对双语的技术支持,方便开发人员通过配置工具配置应用系统相关的属性(提示信息、按钮标签、数据标签等等),而在代码设计中只需对相关组件进行简单的定义,即可实现此功能。 |
数据字典 |
数据字典是对应用系统用到的所有数据项和结构的定义,以确保开发人员使用统一的数据定义。 本数据字典不仅包含数据库数据字典部分内容,而且进行了扩充,比如表字段的双语标签等的属性定义,再外延出去的话,还包括公共代码的统一管理等。 数据字典是技术架构与系统业务分析的基础,比如数据动态、持久层中的自动构建数据集、自动操作数据库等等功能,都要用到数据字典。 |
持久层 |
对象化存储就是将数据库中的数据在对象中实例化,当修改这个对象的属性时,数据库中的相应字段也会随之改变,通常叫做持久层。 持久层应该提供事务管理、锁机制、缓存机制。 |
数据动态 |
将应用系统中发生的数据变化,实时通知需要获知变更的组件中,使得数据在需要同步的组件中保持一致性。 |
安全管理 |
对应用系统的登陆用户进行校验与权限上的管理,包括菜单、按钮、记录的增删减等等。 支持工作流模式。 |
日志管理 |
对应用系统中敏感数据的更新,必须持久化,记录由何人、何时、何地(IP)和数据的新旧变更,以便跟踪。 应用系统中,由数据库、中间层、客户端所产生的陷阱信息都归到日志管理中。 日志按照日志类型、轻重程度、缓急程度等分级(可以由用户自定义),并设置日志发送的目的地:本地、数据库、监控中心、手机等等。 |
用户界面框架 |
总结表现层常用的界面模式,归整为统一的组件或模板,方便开发,统一应用系统的界面风格。 |
客户端组件框架 |
客户端的开发,关注于主程序、界面组件、工作间组件等。 主程序以EXE形式实现,而其余组件以DLL形式实现,主程序通过响应菜单来驱动组件运行。 必须规范主程序与组件间的接口。 |
服务端组件框架 |
服务端的开发,关注于主程序和业务组件。 主程序以EXE形式实现,而其余组件以DLL形式实现,主程序通过响应客户端来驱动组件运行。 必须规范主程序与组件间的接口。 |
通用报表 |
用户可以自定义报表,用户自定义的报表模板可按功能(树状层次)保存供以后或其他用户重复使用。 报表不仅要输出到打印机,而且应该能输出到Text、RTF、PDF、Excel、Word、HTML等等文档格式,并能够通过Email发送出去。 报表可以人为增加、删除列表项,人为将列表项重新排列、进一步搜索列表项等等。 |
工作流 |
工作流是针对工作中具有固定程序的常规活动而提出的一个概念。 通过将工作活动分解成定义良好的任务、角色、规则和过程来进行执行和监控,达到提高生产组织水平和工作效率的目的。工作流技术为企业更好地实现经营目标提供了先进的手段。 |
协同性 |
协同性在物流系统的管理上非常重要,很多作业需要多角色的配合来完成,因此在应用系统的实现上,需要考虑协同性问题,以方便用户工作。 各部门、各人员,以及企业和外部资源之间可以共享信息、实现即时沟通和协同运作,大大提升运作效率,减少企业管理和运营的成本。 |
应用系统发布策略 |
对应用系统的发布采取许可授权(license)的方法,可避免应用系统被盗用或者超范围使用,以保护公司的知识产权。 应用系统的升级,用户应该少受到影响,并且尽可能方便。 |
负载均衡 |
应用服务器应该具有可扩展性,即达到分布式。 在多个应用服务器提供服务的情况下,客户端连接服务器的策略,应该达到均衡连接,而一旦某台服务器当机时,客户端可以自动尝试连接其他服务器。 |
4 总体框架
4.1 分布式C/S/S框架
非web应用系统,将在基于分布式的C/S/S框架下进行开发。
分布式C/S/S框架和传统的C/S框架之不同点,在于客户端和数据库之间加入了应用服务器这一中间层。
4.1.1 优势
使用分布式C/S/S框架具有如下的优势:
1, 减轻处理器的负荷
主要是为了减轻数据库的负荷,由相对价廉的应用服务器来分摊其运算负荷。
2, 可伸缩性的要求
如果业务设计正确,业务逻辑就能够被复制和分布到几个负载均衡的应用服务器上,如果用户数量增加,则可以添加更多的服务器以满足需求。
3, 部署和可维护性的要求
分布式架构下的客户机,可以做到在启动时通过应用服务器进行自我更新;另外,添加功能模块也更容易些。
4, 稀有资源的共享
应用服务器将稀有资源(比如数据库连接)放在缓冲池中,这样可以在多个客户机上共享它们。
4.1.2 负载平衡
分布式计算最大的问题是如何做到负载平衡。基于计算中一个简单的事实:调用不同进程上对象的方法要比调用进程内对象的方法慢数百倍,如果将对象移到网络中的另一台机器上,这种方法调用又会慢数十倍。
所以,在应用系统的业务设计(技术架构与业务架构的关联)上须从以下几点考虑:
1, 客户机上不一定是绝对和业务逻辑无关,数据库也绝对不是不能处理业务逻辑,而应该遵循‘相关内容本地化’的原则,灵活处理;
2, 远程对象应该提供粗粒度的接口,以减少在网络中的信息交互量;
3, 优先选用无状态的对象,以提高系统可扩展性,为多应用服务器的负载平衡机制提供条件。
只有在应用系统的业务设计上,做到了上述几点要求,那么整个系统的性能就可以得到保障,否则用什么架构都是徒劳无益的。
另外,针对多应用服务器的负载平衡,本架构在客户端的登陆处理方式上,提供一套机制,使得客户端启动时,自动登陆到负载最轻的一个应用服务器上。
4.2 基于组件开发
基于组件的开发是个方法论框架,对于指导我们如何建设:开发体系结构、技术体系结构、应用体系结构和项目管理系统结构,都有很大的帮助意义。
采用这种方法,开发生命周期中的所有问题和阶段,包括需求分析、体系结构、设计、构建、测试、部署、支持技术基础设施和项目管理,都将是基于组件进行。
4.2.1 基于组件开发的益处
1, 控制开发复杂性
可以提供划分业务领域的极佳方法,开发过程是通过组件组装大规模系统而不是构建这些系统。
2, 改变应用系统的本质
按照用户的视点开发组件并组装系统,从而带来市场推销和购买软件解决方案的新方式。
3, 实现部件的自治开发
应用系统以一组准自治部署单元构成,从而支持新的和富有挑战性的高层并发开发、测试和部署。为此将改变开发模式和组织结构,由业务领域和专业领域来划分产生基于接口协同的自治开发小组(技术架构与组织架构的关联),而项目的运作则是依照订单来定购这些组件进行组装。
4, 控制部署复杂性
特别体现在系统的演化(变更)过程中,因为系统的修改和更正只会影响一个组件。
5, 缩短产品投放市场所需的时间
成熟的基于组件的开发会大大缩短软件的开发周期,基于组件的开发很容易通过现有的组件组装新的系统。
4.2.2 基于组件开发的层次
1,分布式组件
从粒度角度看,分布式组件是最小的组件,具有可通过网络寻址的接口,通常采用商品化的组件实现技术(例如CORBA、EJB、.NET Remoting或DCOM等)实现。
这种设计模式的目标是支持大规模分布式系统的高生产率开发。
定义分布式组件的方式,使概念设计人员和开发人员只需要关注描述接口、编写业务逻辑、定义到持久存储的映射以及调用其他分布式组件的服务,从而降低功能开发人员的工作复杂度。
2,业务组件
业务组件是自治业务概念(实体或过程)的软件实现。业务组件包含把给定业务概念表示、实现和部署为更大分布式信息系统的自治、可重用要素所需的全部软件工件。
具有各种体系结构原则和概念的业务组件可以用任何语言实现,虽然当前的商品化的建模工具和组件实现技术并不直接支持业务组件概念,但业务组件是一种极为有力的逻辑概念,可以用来降低大规模开发的复杂性,独立于下层开发环境的支持级别。我们可以在不同程度上采用业务组件概念,都会带来可观的开发效益。
业务组件开始是需求阶段的一种单个结构,到了部署、配置和维护阶段,仍然是同一个单元。从这个意义上说,业务组件概念涵盖了整个开发生命周期。
3,业务组件系统
描述业务组件之间的协同关系,是对业务组件的组装,提供了针对某个业务问题的解决方案。
业务组件组装作为开发、测试、部署和发布单元是很有用的。不仅如此,业务组件组装还可以看作是一种进化或维护单元,即通过一个单一操作,就可以用新版本替换整个业务组件组装。
4.2.3 基于组件开发的开发过程
基于组件的开发过程有以下10个黄金特征:
1, 以组件为核心
在整个开发过程,以及所有的体系结构考虑和业务组件方法的所有其他问题,都围绕不同级别粒度的组件展开。
2, 以体系结构为中心
在整个开发生命周期都采用系统结构视点推动系统的进化。
3, 关注自治
在每个开发生命周期阶段,都必须在适当的层次上采取关注自治性的步骤。
4, 向协同发展
在关注自治的同时,实现高水平的协同。一方面,要对单个业务组件进行自治的分析、设计、实现和测试,另一方面又需要保持系统作为一个整体的完整性,保持这种不同自治单元之间的各种潜在协同的完整性。
5, 迭代特性
开发过程通过自治地实现和进化单个组件,支持具有明显迭代和渐进特征的过程。为了支持这种过程具有成本效益,开发环境理念必须支持整个生命周期内的快速迭代。
6, 高水平的并发开发
前面的特征支持独立团队彼此互相独立和并发地设计、开发和测试系统部件,同时仍然保持整个系统的完整性。这是快速开发的一个基本要素,并直接支持经济地完成软件制造的目标。
7, 持续集成
功能开发人员应该能够持续地开发系统部件,并立即得到有关系统功能和行为的系统级反馈,同时又要把注意力集中在构建系统的功能上,而不是技术细节上。
8, 支持风险管理驱动的开发
倡导对项目状况进行立即反馈,以便不断验证和确认各种设计和实现决策;倡导小型、快速迭代,采用合适的工具和过程管理。
9, 突出强调重用
重用要运用于生命周期从需求开始的所有阶段。
10, 把组件开发作为产品开发
业务组件是在尽可能多的地方重用的产品,好的产品开发的突出特征,是十分关注质量、文档和支持。交付的产品应该具有“活的文档”的特征,即总是保持最新状态的文档。
4.3 基于组件开发的分层框架
在分布式C/S/S框架下,可以实现基于组件的分层设计。
4.3.1 分层
层(layer):层是对架构的横向划分,对模型中同一抽象层次上的包进行分组的一种特定方式。通过分层,使系统以更松散的方式耦合,从而更易于维护。分层是对系统逻辑上的分层,在实际应用中将根据系统效率、负载平衡等等实际情况,变通、权衡地实现具体的应用。
我们将应用系统的设计划分为:表现层、业务层、持久层等,在这些层上分别构建相应的组件框架,以利于方便和规范应用系统实现分层框架。
表现层包含‘客户端界面组件框架’,业务层包含‘客户端业务组件框架’、‘服务端业务组件框架’,持久层包含‘数据集持久化引擎’;而‘工作流引擎’、‘数据动态引擎’、‘消息引擎’、‘安全引擎’等是横跨表现层、业务层和持久层。
以下将按照分层和引擎分别表述。
4.3.1.1 表现层
表现层是用户和应用系统进行交互的接口。它辅助用户输入,提供各种提示和帮助、响应用户操作所触发的各种事件、限制用户的输入、处理一些特殊的操作等等。
在表现层上,需要提供一整套的支撑模块和组件框架,以统一界面风格、设计模式。
4.3.1.1.1 分类描述
1, 窗体模版
通过项目和产品实践中不断的积累,逐步归纳整理出一套具有自身特色的标准模版:主窗体、多窗体、对话框窗体、数据处理窗体、查询打印窗体等等。
2, 客户化定制
用户可以自定义界面风格、自定义操作风格、自定义数据显示与输出模式。比如:报表可以由用户自定义,而且可以将自定义模板持久化到本地或配置库中供其他用户使用等等。
这些定制化的功能,需要第三方界面控件的配合来完成,必要得话,要对这些控件进行二次开发。
3, 导向型界面框架
有些界面之间存在明确的处理顺序,用户可以选择‘上一步’、‘下一步’或者‘结束’,界面之间的跳转是由用户触发的,用户的操作流程可以用一张流程(导航)图来描述,导航图上每一个节点就是一个用户界面。为此,可以通过这样一个流程控制器,以隔离界面与业务逻辑,对流程中的界面进行管理,提供状态保存和传递的机制。
本框架是工作流引擎在客户端上一个独立的外延子项,核心组件为通用的流程控制器和状态机,状态信息的持久化在本地,以便恢复导航图中每个节点的当时状态。另外,利用这个组件,也可以在系统正常退出时保存界面状态,以便重启客户端时,将界面恢复到当初退出时的状态。
导向型界面是解决单个用户的多步操作行为,如果每步的界面是由不同的用户来操作的话,就得靠消息驱动来提供作业的导航了。
4, 消息驱动型界面框架
一个任务可以由多位用户协作完成,当前一个用户完成自身的工作后,可以将此任务传递到下道工序的用户,任务通过流程控制器进行流转。消息驱动型的界面,使得用户的操作是由消息来推动,任务是分派来的而不是主动去找的。为隔离界面与业务逻辑,通过流程控制器对消息驱动型界面进行管理,提供状态保存和传递的机制。
本框架是工作流引擎在客户端上的一个关键子项,核心组件为通用的流程控制器和状态机,状态信息的持久化在配置库,以便恢复导航图中每个节点的当时状态。
本框架的具体实际机制,将由最终选用的工作流引擎来定,将在下面的专题章节中单独讨论。
5, 整合第三方表单控件
第三方表单控件,是相对图形化控件而言,分普通窗体控件和数据感知控件。
第三方表单控件的引进,必须遵照少而精的策略,如果开发工具本身自带的控件已能满足开发需求,那么就不要再使用相同功能的第三方控件,花哨实无必要。
目前可以尝试引进的第三方界面控件,大致如下:
ComponentOne Studio for .NET;
Developer Express Component for .NET;
6, 整合第三方图形控件
我们所开发的产品,80%的界面将是图形化交互模式,不仅仅要画出无数各种形状和颜色的小图形,而且这些图形也是一个个对象,需要随时根据动态刷新数据变换颜色、形状、位置等等,另外,它又是可以与用户进行交互的,可接受鼠标的点击、选择、聚焦、拖放、获取属性等等。
在现有产品中,我们已经成功地使用了第三方的控件: TATUK GIS for VCL,积累了不少的开发经验。在.NET开发平台上,也有该产品线:TATUK GIS for .NET,所以,相信目前的产品可以平滑地迁移到新的技术平台上。
7, 整合第三方报表控件
用户可以自定义报表,人为增加、删除列表项,人为将列表项重新排列、进一步搜索列表项等等,用户自定义的报表模板可按功能(树状层次)保存供以后或其他用户重复使用。
报表不仅要输出到打印机,而且应该能输出到Text、RTF、PDF、Excel、Word、HTML等等格式文件,并能够通过Email发送出去。
一些第三方的表单控件,可以将数据列表输出到打印机和各种格式的文件中,此处专门讨论专业报表控件,除了VS2005自带的Crystal Reports(水晶报表)外,目前可以尝试引进的第三方报表控件有:
ActiveReports for .NET;
Grid++Report(COM组件);
8, 动态菜单
沿袭Packer for Delphi中的模式,应用系统的菜单可以通过配置工具定义的内容进行动态构建。
当菜单项与客户端业务组件进行关联后,业务组件就可以被自动调用(通过客户端业务组件框架);当业务组件与安全引擎进行关联后,菜单项的Enabled和Visible属性都能被自动设置。
动态菜单的设计,将继承自VS2005自带的菜单控件,分标准菜单和树状菜单两种。
4.3.1.1.2 智能客户端
智能客户端(Smart Client)是微软为开发表现层而提供的一套‘集成式桌面框架’,声称将淘汰掉基于浏览器的开发模式,虽说是针对web应用,但将客户端开发回归到桌面,保持丰富的表现性和互操作性,是我们所需要的。
智能客户端包含了一些基本服务:上下文服务、部署服务、安全服务、集成服务等等。
4.3.1.2 业务层
业务逻辑层,有人把这一层叫做业务基础平台,或者叫做领域框架层。这一层是针对某一行业或特定类型应用的通用的软件实现,具有业务的通用性。它可以更高程度地实现软件的复用,同时又支持用户的个性化需求的实现,能够快速地开发用户所需要的应用系统。而基于组件的开发方式是为达到此目的的唯一实现过程。
如何构建业务层,必须从服务、组件、对象三个层次分析问题,服务包含了组件、组件包含了对象,对象在组件中被复用,组件在服务中被复用,而对象、组件、服务的关系必须是松耦合的。为做到这点,按照面向对象的方法,核心功能一般被实现为一组以特定方式交互的抽象的类,在导出具体的应用时,这些抽象的类由特定的具体子类替换。而从组件和服务的观点来说,这些抽象类就是接口。总之,接口是构建业务层的关键点。
为了实现业务层,我们抽象出一层来通过接口协调其中的对象、组件、服务,这就是业务组件容器,它是组件运行时所处的空间,负责组件的生命周期管理以及组件运行需要的上下文管理。当用户希望执行一个业务的时候,我们可以要求容器创建这个业务对象,业务容器可以交给我们一个业务对象的代理,隐藏真实的对象的位置。实际的执行过程可能是分布式的,容器为我们管理业务对象的事务性,保存业务执行的进度,必要的时候暂停业务,条件成熟后再重新开始,业务完成以后将对象销毁……这些我们都不必关心,由容器为我们做。
按照分布式系统的物理实现,将业务层中的组件分为:客户端业务组件、服务端业务组件,它们都由业务组件容器统一管理和调配。客户端业务组件框架是客户端业务组件的容器,提供与客户端界面组件和服务端业务组件的标准接口;服务端业务组件框架是服务端业务组件的容器,提供与客户端业务组件和持久层引擎的标准接口。
4.3.1.2.1 客户端业务组件框架
沿袭Packer for Delphi中的模式,基于DLL的插件框架将被迁移到基于程序集的插件框架。它们没有本质的区别,只是.NET的程序集为组件开发提供了更方便的开发环境和调试环境,同样也方便了组件的部署。
组件框架为应用系统开发提供标准的接口,当应用系统需要创建某个业务对象时,组件框架利用.NET的反射机制,通过接口动态加载相关的程序集并启动这个业务对象。缺省情况下,组件框架会传递给这个组件当前应用系统的用户权限等等信息;同样,调用方和被调的组件之间,也可以通过接口传递消息、数据、对象等。
程序集可以实现动态插拔,只需更改配置信息(事先被持久化到本地或配置库中)和XCOPY相应的组件,就可以无须编译直接定制出一个特定的应用系统。
客户端业务组件与服务端业务组件之间的联系,是采取请求服务和提供服务的方式处理的。
4.3.1.2.2 服务端业务组件框架
服务端业务组件通过远程组件容器供客户端调用。.NET框架有两种组件容器供远程调用:XMLWeb服务和.NET Remoting。
.NET Remoting 和JAVA的RMI一样,允许开发人员将网络中独立机器上的组件(程序集)连接起来构成应用程序,前提是假设是在一个同构环境中,假定.NET应用位于通信通道的两端。
XMLWeb服务可以使Web站点和应用程序之间象组件(程序集)那样互相作用,跟所有的组件(程序集)一样,Web服务也是通过一些方法来提供它的功能。与.NET Remoting不同的是,Web服务被设计为可以在异构环境中工作。
XMLWeb服务和.NET Remoting有许多相似之处,它们共享许多诸如SOAP和WSDL等组件(程序集),而且ASP.NET可以驻留远程对象,并通过HTTP通道使用SOAP串行化技术来提供这些对象,使得远程对象看起来就象是个Web服务。但是,它们是根本不同的技术,.NET Remoting使用串行化机制来保持CTS(Common Type System,即.NET通用类型系统)类型的可靠性,而Web服务使用串行化机制来保持XML Schema(XML文档类型系统)类型的可靠性。正因为如此,当知道客户端仅是.NET客户端时,使用.NET Remoting比较合适,而如果还需要支撑很多类型的客户端平台时,Web服务会更适合这项工作。
一般而言,信息系统对外的接口,或者信息系统内的子系统之间接口,可以采取XMLWeb服务的方式(即SOA架构);而子系统内则采取.NET Remoting方式。
1,效率分析策略
从系统效率考虑,.NET Remoting提供了HTTP和TCP两种通道、SOAP和二进制两种传输格式,可互相组合使用,而且还可以在一个服务器上同时注册一个HTTP通道和一个TCP通道,以满足不同的需要。
TCP通道利用TCP/IP网络协议提供了连接性,默认情况下,信息被转换成二进制格式,二进制有效负荷相对而言比较小,因此TCP通道与HTTP通道相比执行起来更容易。不过,TCP通道需要在服务器上建立唯一的网络端口,这点以及他专门的二进制格式,在传送方法调用时,要通过防火墙会比较困难。不过,在一个封闭的网络环境(也就是说在防火墙后面)中,要获得性能更好的连接性,首选TCP通道。
HTTP通道利用HTTP网络协议提供连接性,在Web服务器和Web浏览器间也使用HTTP协议。默认情况下,信息被转换成SOAP格式,由于SOAP基于XML语言,有效负荷会更大一些,因此HTTP通道比TCP通道执行起来要慢一些。但从另一个角度来说,也更要灵活一些。例如,IIS可以作为远程对象的主机,并在HTTP通道中提供这些远程对象。因为IIS是在端口80(所有Web服务器的默认端口号)进行监听,不需要再打开一个新的端口来提供对远程对象的连接。而且,防火墙的通常配置容许80端口的请求,因此如果要更顺利地通过防火墙,首选HTTP通道。
为了将TCP通道的速度和HTTP通道的灵活性进行折中,可以使用带有二进制格式化的HTTTP通道。这样可以为IIS驻留远程对象提供灵活性,还可以使之很容易地通过防火墙。不过,TCP通道本身比HTTP通道更有效,因此,TCP通道/二进制格式化的组合还是要比HTTP通道/二进制格式化的组合更快一些。
另外,.NET Remoting的调用机制有同步和异步之分,当客户端需要及时响应用户操作的情况下,可以选用异步方式(委托)调用远程对象。
2,驻留远程对象策略
上述提到的IIS驻留远程对象方式是一种,另外还可以驻留在Windows服务中。
Windows服务可以在机器重启时自动启动,并且可以使用一个特定的用户帐号执行,也不会干扰本机上的其他用户,这些特点都使得Windows服务非常适合于驻留远程对象。
3,编组远程对象策略
.NET以两种不同的方式编组对象:通过值编组(MBV)和通过引用编组(MBR),从概念上讲,这些编组技术与通过值和通过引用传送参数的表示法是类似的。
利用MBR可以进行分布式处理,它使得远程调用对象(通过代理)时,该对象可以运行在不同的应用程序域、进程或机器上。此方式适合于调用次数少,而被调用对象运行负荷大,需要负载平衡的情况下,是分布式处理常规模式。
而MBV可以串行化远程对象并将其反串行化到客户端,在客户端的应用程序域中创建一个远程对象的副本,这样就可以象访问和修改本地对象一样使用该对象。此方法适用于用来封装数据,或者对象调用次数多的情况下(因为会造成网络负荷)。
4,激活远程对象策略
Singleton模式:Singleton对象可为所有客户端请求共享状态或资源,但多个客户端访问Singleton对象实例时,虽说每个请求都会以一个独立的工作线程进行工作,但在这些线程访问和修改对象的实例域时就要考虑线程同步的问题(lock)。
SingleCall模式:运行库为每个客户端请求建立一个新对象来响应,并在完成请求后就释放对象,在客户端之间没有任何可共享的状态和资源,甚至是被调用的方法间也是如此。也就是说,该对象是无状态的。在处理很多服务器端的平衡负载请求时,本模式非常有效。
客户端激活对象:类似于SingleCall对象,每个客户端都可以激活这个远程类型的唯一实例,不过不同的是,客户端激活对象可以持续于多个方法。也就是说,该对象是有状态的。
5,远程对象租赁策略
一般来说,消耗资源大、特别是占用稀有资源的对象,最好采用SingleCall模式,以尽快回收和释放,此模式不需要关心远程对象的租赁期。
而Singleton对象和客户端激活对象为了保存客户端的状态和资源,需要在设计时延续远程对象租赁的生存期直到断开关联为止(构建和注册发起者(sponsor))。
6,元数据部署策略
远程对象的调用是通过代理加远程通道的工作方式来完成的。当对象通过一个方法调用从服务器返回时,事实上服务器传递了一个对象引用(ObjRef),ObjRef保存了构建客户端代理所需的全部信息,包括类型名、URI、类型层次结构和支持接口(在这些信息当中,类型名起了决定作用,因为它包含了程序集名),然后客户端运行库会反射这个程序集来构建代理。
通过上述原理的分析,知道只有为客户端提供服务器的元数据,才能运转起来。优雅的解决方法是,将每个远程对象都分成一个接口和一个实现,然后只将接口分布在客户机,而将实现放在服务器上。从技术上讲,根据需要,在接口程序集中也可以包含抽象基类。另外,可以采用配置文件(事先被持久化到本地或配置库中)的方法,为客户端和服务器定义各自的远程设置。
如此,服务端业务组件框架作为一个容器,可动态加载程序集,加载的触发条件是配置文件是否发生更新,一旦发生更新事件,就重新读取,根据变化的内容重新构建程序集。从而做到动态部署、即插即用、热插拔。
4.3.1.2.3 组件框架的实现方法
不管是客户端还是服务端的业务对象,都是基于组件的方式进行开发。
沿袭Packer for Delphi中的模式,架构提供统一的组件容器,利用.NET的程序集技术、反射机制、Remoting技术等等,实现动态的加载、释放本地或远程的业务组件。
组件容器与业务组件、业务组件与业务组件之间,架构都提供标准的接口,利用接口技术来传递传递消息、对象、数据等;应用系统也可以在这些标准接口基础之上,扩展成为自己的接口,以方便开发。
4.3.1.3 持久层
持久层是对关系数据库持久化操作的数据访问中间件。
4.3.1.3.1 为什么需要持久层
如果直接用SQL来传递数据的话,存在许多问题,比如:
¨ 业务改变容易破坏结构化数据的结构
¨ 业务逻辑与数据存储代码混在了一起
¨ 随着应用的增长问题更加明显
而使用持久层,可以将业务逻辑和数据存储逻辑隔离开来,业务逻辑操作的是数据的映射而不是实体,在完全消除SQL语句的情况下,支持多记录的条件查询、更新、删除。如此可解决上述问题。
4.3.1.3.2 如何实现持久层
单纯地追求绝对的松耦合,会带来性能上的急剧退化。因此,必须权衡利弊,在参考当前流行的持久化模式下,构建适合自己的持久层。
主导思想是,不在运行期动态映射数据库,而是提供工具由开发者配置和映射数据库,在运行期通过这些配置信息来构建映射关系,为业务层提供数据持久化接口。这样做,虽然少了些灵活性,但性能可以得到保障。
通过工具配置和映射数据库。方法是自业务到数据,是业务驱动,不是数据驱动。也就是说,通过构建业务对象,来生成虚拟表(数据集)对象,由工具将数据集对象与物理表之间构建出一层映射关系。如此,数据集和物理表的构建可以在规范(结合数据字典)下完成,而业务对象对数据集的操作(查询、更新、删除等),也可以通过引擎自动持久化到对映的物理表中。
另外需要提到的是,对于存储过程的使用将有所限制,即只是在为优化系统性能的前提下而使用,原则上,它用来做数据的一些操作,比如大批量的数据更新、数据分析等等,而不存放业务逻辑。
目前,基于上述前提条件,有两种方案可供选择:
1,将Packer for Delphi中的持久层服务迁移到.NET平台上
迁移既有的持久层框架,最大的好处是,一套配置工具和配置库可以同时支持到基于Delphi和.NET的两种开发平台,原有的成果可以继续发挥作用。
这种框架的迁移,碰到的主要技术问题是,如何将MIDAS+DCOM技术转换成ADO.NET+.NET Remoting/Web Service技术。
ADO.NET结构示意图如下:
从上图可知,ADO.NET框架是非常适合分布式组件开发的:
u 在应用程序中将数据缓存在本地,以便可以对数据进行处理
u 在层间或从 XML Web 服务对数据进行远程处理
u 与数据进行动态交互,例如绑定到 Windows 窗体控件或组合并关联来自多个源的数据
u 对数据执行大量的处理,而不需要与数据源保持打开的连接,从而将该连接释放给其他客户端使用
ADO.NET框架与MIDAS框架也有很多相似的地方,比如DataAdapter和TDataSetProvider、DataSet和TClientDataSet,在框架中所在的位置、所起的作用都差不多;服务端和客户端所传输的同样是数据包,只是格式不同而已,等等。所以说,从MIDAS框架下的持久层迁移到ADO.NET下的持久层,是可行的。
2,开源持久层框架IBatisNet
另外的办法,就是直接使用第三方开源的持久层框架。经过对当前流行的持久层框架分析和比较下来看,当中比较适合于公司产品的持久层框架,应该是IBatisNet。
IbatisNet算是一个半ORM的框架,或者说Data Map。IBatisNet实际是一个PO与SQL之间的关系映射框架。也就是说,IBatisNet并不会为开发者在运行期自动生成SQL执行。具体的SQL需要开发者编写,然后通过映射配置文件,程序将SQL所需的参数传入,框架将映射好的结果返回。这些与Packer持久层的开发思路较为相似。
优点:
u 简单易学
易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
u 灵活
开发人员可以充分利用SQL的强大功能。
u 对数据库开发的要求低
只要原先通过SQL可以实现的功能,通过IBatisNet几乎都能够实现。
u 功能强大
提供了连接管理,缓存支持,线程支持,(分布式)事物管理,通过配置作关系对象映射等数据访问层需要解决的问题。提供了DAO支持,并在DAO框架中封装了ADO.NET,NHibernate和DataMapper。
u 增强系统的可维护性
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。SQL和代码的分离,提高了可维护性。
缺点:
u 半ORM,需要开发人员写SQL,自动代码生成工具不完善
u 需要一些XML配置
u 还不是很成熟
u 工程实践较少,在实际项目中的使用较少。
结论:
从理论上说,由于IBatisNet是一个轻量级的非侵入的框架,使用它的风险会相对低点。他的那些缺点并不是致命的,而且也是有一些解决方案的。由于理念相同,从Packer持久层迁移到IBatisNet相对比迁移到NHibernate要容易得多。所以,在.NET上要选一个第三方开源的持久层框架的话,IBatisNet是一个比较不错的选择。
4.3.2 引擎
4.3.2.1 数据集持久化引擎
见上节。
4.3.2.2 工作流引擎
工作流是针对工作中具有固定程序的常规活动而提出的一个概念。通过将工作活动分解成定义良好的任务、角色、规则和过程来进行执行和监控,达到提高生产组织水平和工作效率的目的。工作流技术为企业更好地实现经营目标提供了先进的手段。
一般说起工作流,其实包含了两种类型:一种是与行政办公有关的工作流,以文档/文件流转为主,另一种就是商业(业务)流程,英文中的 Process 更能表达此意思。实现前者目的的平台产品相对较丰富,如 Lotus Notes、Exchange 等,而实现后者的平台产品似乎相对较少,且功能也不完备。
Microsoft Windows Workflow Foundation(WWF)是一个可扩展框架,用于在.NET平台上开发工作流解决方案。WWF同时提供了 API 和一些工具,用于开发和执行基于工作流的应用程序。WWF提供单个统一的模型,以便创建跨越多个类别应用程序的端到端解决方案,包括人力工作流和系统工作流。
WWF可构建有状态的、持久化的、不间断运行的应用程序。WWF运行时引擎管理工作流的运行,为工作流的长期运行提供保障,并能抵抗机器的重启。
WWF为开发人员提供了一个工作流模型,来描述应用程序所需要的处理过程。通过使用工作流模型所提供的流程控件、状态管理、事务和同步器,开发人员可以分离应用程序逻辑和业务逻辑,构造一个高层次的抽象,达到提高开发者效率的目的。
WWF可以帮助开发者重用组件。WWF为开发者提供了一系列的活动——活动是一种包含了工作单元的可配置逻辑结构。这种结构封装了开发者可能经常性用到的一些部件,这样就节省了开发者的时间。通过将工作流引擎载入进程,WWF可以使任何应用程序和服务容器运行工作流。运行时服务组件被设计成可插件形式的,这个可使应用程序以最合适的方式来提供它们的服务。
如何将WWF融入到本架构,需要投入资源进行研究,比如:在客户端如何整合消息驱动型界面、在业务层如何利用数据字典整合数据包、并且如何与消息引擎(消息流)、安全引擎(用户和权限)进行整合等等。
4.3.2.3 数据动态引擎
数据动态引擎,是将数据库发生的数据变化,实时表现在客户端界面上。它在物理布局上分为动态刷新服务器、客户端动态刷新组件、配置工具等三部分,动态刷新服务器提供分布式负载均衡机制。
4.3.2.3.1 实现机制
4.3.2.3.2 配置工具
配置工具是为开发者配置数据动态引擎所维护数据集的SQL语句等信息,持久化到配置库中的,动态刷新服务器依照配置信息来维持其数据集。
4.3.2.3.3 对业务架构设计的建议
经过以往应用系统的开发经验,建议:数据集的SQL尽可能简洁、客户端的表现层和业务层彻底解耦,如此,就能够使得相关表触发器的编写更加简单、准确,客户端的代码编写也更加容易和面向对象化;最好是,数据库结构的设计也要考虑到是否适合数据动态引擎运行等等;总之,希望能够更好的满足性能、准确率、刷新量等等功能外的需求。
4.3.2.4 消息引擎
应用系统软总线包括技术实现上的、也包括设计规范上的。应用系统设计可面向总线进行,设计者只需识别总线,根据总线的规定去设计,将各组件按照总线接口的标准与总线连接而无需单独为各组件设计连线。这就简化了系统的设计,也简化了系统的结构,使系统易于扩充和更新。
消息引擎是应用系统软总线的一个关键技术,是各组件联系的纽带,在接口技术中扮演着重要的角色。倚靠目前可以利用的技术,我们可以从以下几处着手来实现它。
4.3.2.4.1 数据包
在总线上传输的数据需要统一的标准进行包装,用以将参数传递给框架中的任意对象,即将彼此无关的参数打包成单一和高效的数据封装包,以简化系统的设计,这点可以与物流领域中的集箱和散货做比方,是一个道理。
当交互的对象被某种形式的边界隔开,数据传输的代价就会很高。边界可以有多种形式:网络边界、进程边界、域边界(.NET)和存储边界(I/O)等等。当开发人员来回设置和获取数据时,数据传输可能带来性能上的问题。
为了避免在对象交互期间的多次往返,一种选择就是在方法中立即传递所有参数。数据包就是这样一些参数的容器,它是一个通用的容器,将按需容纳许多参数来满足任何业务对象。
数据包另一个好处是,可以应对参数集合频繁改变的情形,只要往返双方知道怎么打包和解析即可。
使用ADO.NET的DataSet对象来作为数据包的容器是可行的方法之一。数据包利用DataSet可以包含任何数据,并传递到框架内的每一层。同时,与数据包交互的业务对象不直接和DataSet打交道,而是调用数据包的标准方法(比如GetData()),为业务对象提供统一的交互界面。
4.3.2.4.2 数据字典
此处的数据字典不仅仅是指数据库概念(就数据库概念将在持久层中专门讨论),而是囊括了信息系统内交互的所有信息的元数据。
架构提供专门的配置工具来构建信息系统的数据字典,并持久化到配置库中供相关标准组件调用。
数据字典的使用,可以规范开发过程,使得系统设计简单化。首先是参数的规范,开发人员不必自创参数的命名,少了沟通的障碍,也减少了信息的二义性。其次是值的规范,定义了一套公共的代码表,为信息系统提供统一的代码支持。
数据字典的构建,使得表现层、业务层和持久层间的信息交互可以通过数据字典自动匹配,为自动化处理(工作流等)等应用提供了基础平台。
4.3.2.4.3 Message Queue
利用 Microsoft Windows“消息队列”,可以通过发送和接收消息方便地与应用系统进行快速可靠的通信。消息处理和消息为基于服务器的应用程序组件之间的进程间通信提供了强大灵活的机制。同组件间的直接调用相比,它们具有若干优点,其中包括:
1,稳定性
组件失败对消息的影响程度远远小于组件间的直接调用,因为消息存储在队列中并一直留在那里,直到被适当地处理。消息处理同事务处理相似,因为消息处理是有保证的。
2,消息优先级
更紧急或更重要的消息可在相对不重要的消息之前接收,因此可以为关键的应用程序保证足够的响应时间。
3,脱机能力
发送消息时,它们可被发送到临时队列中并一直留在那里,直到被成功地传递。当因任何原因对所需队列的访问不可用时,用户可以继续执行操作。同时,其他操作可以继续进行,如同消息已经得到了处理一样,这是因为网络连接恢复时消息传递是有保证的。
4,事务性消息处理
将多个相关消息耦合为单个事务,确保消息按顺序传递、只传递一次并且可以从它们的目标队列中被成功地检索。如果出现任何错误,将取消整个事务。
5,安全性
MessageQueue 组件基于的消息队列技术使用 Windows 安全来保护访问控制、提供审核并对组件发送和接收的消息进行加密和验证。
4.3.2.4.4 应用范围
如何合理地使用MQ技术,是构建可编写、可部署的应用系统所必须考虑的问题。通过对MQ技术的了解,它不是特别适合于数据交互量大、或者不需维持历史消息的系统,而适合于用户间的消息通知(必达消息)、协同工作模式下的应用系统。
4.3.2.5 安全引擎
计算机技术安全管理的范围很广,可以包括网络安全性、数据安全性、操作系统安全性以及应用程序安全性等。很多方面的安全性管理大都已经有成熟的产品了,我们只需根据自己需要有选择性的使用就可达到自己的目的了。本章中有关关涉及‘安全管理’一词均只针对应用系统中有关对象与数据而言的范围。
4.3.2.5.1 名称解释
主体:即可以向应用系统发出应用请求的任何实体,包括各种用户、其它与本系统有接口的应用程序、非法入侵者。系统必须具有识别主体的能力,接口实际上也是由用户登记的,故主要问题是校验用户身份的合法性,系统应建立用户鉴别机构以验证用户身份。
用户:用户就是一个可以独立访问计算机系统中的数据或者用数据表示的其它资源的主体,用户在一般情况下是指人。
权限:权限是对计算机系统中的数据或者用数据表示的其它资源进行访问的许可。可分为对象访问控制和数据访问控制两种。
对象访问控制:用一个二元组来表示:(控制对象,访问类型)。其中的控制对象表示系统中一切需要进行访问控制的资源,访问类型是指对于相应的受控对象的访问控制,如:读取、修改、删除等等。
数据访问控制:如果不对数据访问加以控制,系统的安全性是得不到保证的,容易发生数据泄密事件。所以在权限中必须对对象可访问的数据进行按不同的等级给予加密保护。我们同样用一个二元组来表示:(控制对象,谓词)。权限最终可以组合成如下形式:(控制对象,访问类型,谓词)。
角色:角色是指一个组织或任务中的工作或位置,它代表了一种资格、权利和责任。
用户委派:用户委派是用户与角色之间的一个二元关系。
权限配置:权限配置是角色与权限之间的一个二元关系。
4.3.2.5.2 总体构思
架构应该能够做到对对象控制、菜单控制、数据集的控制,将应用系统的安全管理单独的分离出来,并制定一些整个系统通用的安全准则。应用系统开发者在业务设计时不要过多的考虑程序安全性的问题,而只需遵循系统的安全准则即可,把主要精力花费在系统的业务功能上。
1,基于角色对用户组进行访问控制
对一组用户比对单个用户进行访问控制更加合理,用户组代表了具有相近工作性质的一组用户的集合,可以委派完成用户组工作的角色以控制用户组的权限范围(当然我们也可以把角色看成是我们系统中一个特定用户组)。同时支持角色的继承和多继承。通过改变用户的当前角色集就可以改变用户的权限,而改变某种角色所含的权限时又可以改变一组用户的权限,基于这种访问控制方式有3个方面的作用:(1)简化了权限管理,避免直接在用户和数据之间进行授权和取消。研究表明,用户所具有的权限易于发生改变,而某种角色所对应的权限更加稳定;(2)有利于合理划分职责,用户只有其所应具有权限,这样可以避免越权行为,有关用户组的关系描述正是对此的支持;(c)防止权力滥用,敏感的工作分配给若干个不同的用户完成,需要合作的操作序列(工作流)不能由单个用户完成。
2,支持动态地改变用户的权限
安全管理考虑了访问权限不是静态,而是动态的情况。当应用系统使用工作流时,可通过工作流引擎与安全管理控制核心的接口,动态分配用户完成当前工作流环节所需的权限。
3,权限的相互关联
各种权限不是互相独立而是相互关联的,而且权限可以感知到其它用户操作,这可以描述有关协同权限。例如在给数据编辑控件授权只读权限时,收回用户对数据插入和删除权限,该权限允许感知其它用户的操作,诸如某用户改变了数据等等。
4,提供方便的授权/取消机制和检查机制:
只要进行简单的赋值操作即可完成授权,同时由角色分配规则和主体访问规则控制这种授权机制的应用。
5,用户之间的授权关系:
依据角色指派关系,运行系统中的用户自身可以对角色进行管理,这提供了又一种动态改变用户权限的手段。通常,角色指派的权力都在系统中具有管理责任的用户手中。
用户通过专用客户端的登陆窗口进入应用系统,专用客户端依此管理用户的权限等信息,并根据用户权限动态生成菜单项和其他的加载项,如工具栏、列表框等等。用户通过专用客户端调用具体的组件,而组件(程序集)在用户的操作过程中动态加载、缓存和管理,即插件的方式。专用客户端还负责构件(程序集)的下载升级,做到一次安装永久使用。
4.4 License版权
为保护应用系统产品的版权,需要在架构中提供版权限制功能,以限制用户同时登陆数量。
可提供公钥予客户对系统进行版权升级,而公钥是通过开放用户数、客户公司名等等信息计算而来。
5 架构层次
如上图,软件开发架构开发层次,上层的开发基本将基于下层提供的功能进行开发。
6 设计规范
遵照《.NET设计规范》进行代码编写。
7 风险控制
从前文分析,公司将来的产品主要以图形化交互界面为主,那么图形对象在.NET上的应用,是否能够支持大批量数据的动态刷新、界面的响应周期等等指标,都需要经过测试才能下结论,这甚至是整个框架是否能够基于.NET开发平台之上构建的前提条件。如果拿轻量级的TATUK GIS在压力测试下也未能达到上述要求的话,那是否中止以.NET开发平台为主的框架设计,而转向以win32(Delphi/C++)开发平台为主的框架设计,就应该重新考量的了。
8 技术准备与技术培训
9 实施方案
技术架构的研发是个迭代、逐步完善的过程,不可能是一蹴而就的工作,同时必须实时响应它所支撑的产品线开发的需求。所以组建专职的技术架构研发组织,可以保障技术架构的研发持续稳固的进行下去,并能切实发挥其效用。
架构的实施,必须得到全体开发人员的配合和理解。因为应用系统的业务分析、逻辑分层、数据库设计等等,都是能够脱离本架构限制,随意发挥的。在应用系统的设计开发中,哪些可行、哪些不可行,都需要对本架构、.NET平台技术、分布式组件开发等技术和方法论,需要有一系列的领悟和使用经验,并能够融入到自己的开发当中,才能使业务架构与技术架构完美结合,设计出好的产品。但这些又不是本架构能够做到的,需要公司相关制度、组织结构、开发团队的配合。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2064428