【转】浅谈改进数据库应用系统性能的常用策略

注本文版权由文章原作者所有,如果作者认为本转载侵犯了原作者的权利,请与管理员联系 [email protected]

浅谈改进数据库应用系统性能的常用策略
陆兆洁  南宁经济信息中心

摘要:本文主要简述了改进数据库应用系统性能的常用策略,并从系统层次架构角度分别介绍了在不同领域所采用的方法,本文的侧重点放在解决问题的方法论上,期待能够达到抛砖引玉之效。

1  引言

数据交互复杂度与频度的提升,导致了数据库在运维、迁移和规模扩展进程中的性能问题。作为一项确保企业IT基础部件健康运营的关键技术,数据库性能优化的实现路径和IT系统管理架构越来越密不可分。

在数据库成熟应用的时代,数据库的性能优化已经演变为一项相当严密的系统工程。作为企业IT基础设施的核心部件之一,数据库并不是孤立的系统,它与网络、操作系统、存储等硬件系统紧密相连,这种与其他IT部件的多重连接特性决定了数据库性能优化是一门综合技术。

2  数据库应用系统性能的优化

完整的数据库性能优化周期可以分为两个阶段,一是设计与开发阶段,主要负责对数据库逻辑和物理结构的优化设计,使其在满足具体业务需求的前提下,系统性能达到最佳,同时系统开销最小;二是数据库的运行阶段,其优化手段以数据库级、操作系统级、网络级为主。

2.1  数据库的设计和开发阶段

数据库性能下降很大一部分的风险是能够在数据库的设计阶段予以规避的。因此,设计优化也就成为了数据库性能优化技术的源头和方向。由于数据库逻辑结构的不合理、索引设计不合理,开发阶段的技术冲突无法调适,多种因素的累积作用导致了许多数据库系统上线后不久即出现性能故障的案例不在少数。比较生命周期的调优成本与调优收益曲线,性能调优的成本随软件生命周期进程而增加,但调优收益却随软件生命周期进程而减少。在该阶段的具体实现上一般表现为某一类数据库,其性能的改进主要体现在逻辑设计和物理设计上。

2.1.1  数据库的逻辑设计

数据库的逻辑结构是由一些数据库对象组成,如数据库表空间、表、索引、段、视图、存储过程、触发器等。数据库的逻辑存储结构(表空间等)决定了数据库的物理空间是如何被使用的,数据库对象如表、索引等分布在各个表空间中。

数据库的逻辑配置对数据库性能有很大的影响,因此首先要对数据库中的逻辑对象根据他们的使用方式和物理结构对数据库的影响来进行分类,这种分类包括将系统数据和用户数据分开、一般数据和索引数据分开、低活动表和高活动表分开等等。

数据库逻辑设计的结果应当符合下面的准则摘要:

(1)把以同样方式使用的段类型存储在一起;

(2)按照标准使用来设计系统;

(3)存在用于例外的分离区域;

(4)最小化表空间冲突;

(5)将数据字典分离。

逻辑结构优化用通俗的话来说就是通过增加、减少或调整逻辑结构来提高应用的效率,可以从以下几个方面来精练数据库的逻辑设计:

1、基本表扩展

数据库性能包括存储空间需求量的大小和查询响应时间的长短两个方面。为了优化数据库性能,需要对数据库中的表进行规范化。一般来说,逻辑数据库设计满足第三范式的表结构轻易维护且基本满足实际应用的要求。所以,实际应用中一般都按照第三范式的标准进行规范化,从而保证了数据库的一致性和完整性,设计人员往往会设计过多的表间关联,以尽可能地降低数据冗余。但在实际应用中这种做法有时不利于系统运行性能的优化:如过程从多表获取数据时引发大量的连接操作,在需要部分数据时要扫描整个表等,这都消耗了磁盘的I/O和CPU时间。

为解决这一问题,在设计表时应同时考虑对某些表进行反规范化,方法有以下几种:一是分割表。分割表可分为水平分割表和垂直分割表两种:水平分割是按照行将一个表分割为多个表,这可以提高每个表的查询速度,但查询、更新时要选择不同的表,统计时要汇总多个表,因此应用程序会更复杂。垂直分割是对于一个列很多的表,若某些列的访问频率远远高于其它列,就可以将主键和这些列作为一个表,将主键和其它列作为另外一个表。通过减少列的宽度,增加了每个数据页的行数,一次I/O就可以扫描更多的行,从而提高了访问每一个表的速度。但是由于造成了多表连接,所以应该在同时查询或更新不同分割表中的列的情况比较少的情况下使用。二是保留冗余列。当两个或多个表在查询中经常需要连接时,可以在其中一个表上增加若干冗余的列,以避免表之间的连接过于频繁,一般在冗余列的数据不经常变动的情况下使用。三是增加派生列。派生列是由表中的其它多个列的计算所得,增加派生列可以减少统计运算,在数据汇总时可以大大缩短运算时间。

因此,在数据库的设计中,数据应当按两种类别进行组织:频繁访问的数据和频繁修改的数据。对于频繁访问但是不频繁修改的数据,内部设计应当物理不规范化。对于频繁修改但并不频繁访问的数据,内部设计应当物理规范化。有时还需将规范化的表作为逻辑数据库设计的基础,然后再根据整个应用系统的需要,物理地非规范化数据。规范与反规范都是建立在实际的操作基础之上的约束,脱离了实际两者都没有意义。只有把两者合理地结合在一起,才能相互补充,发挥各自的优点。

2、索引的建立

创建索引是提高检索效率最有效的方法之一,索引把表中的逻辑值映射到安全的RowID,能快速定位数据的物理地址,可以大大加快数据库的查询速度,一个建有合理索引的数据库应用系统可能比一个没有建立索引的数据库应用系统效率高几十倍,但并不是索引越多越好,在那些经常需要修改的数据列上建立索引,将导致索引B*树的不断重组,造成系统性能的下降和存储空间的浪费。对于一个大型表建立的索引,有时并不能改善数据查询速度,反而会影响整个数据库的性能。这主要是和SGA的数据治理方式有关,Oracle在进行数据块高速缓存治理时,索引数据比普通数据具有更高的驻留权限,在进行空间竞争时,Oracle会先移出普通数据,对建有索引的大型表进行数据查询时,索引数据可能会用完所有的数据块缓存空间,Oracle不得不频繁地进行磁盘读写来获取数据,所以,在对一个大型表进行分区之后,可以根据相应的分区建立分区索引。

2.1.2  数据库的物理设计

数据库物理设计需要对时间效率、空间效率、维护代价和各种用户要求进行权衡,结果会产生多种方案,必须对此进行细致评价,选择一个较优的方案作为数据库的物理结构。

数据库的数据最终是存储在物理磁盘上的,对数据进行访问就是对这些物理磁盘进行读写,因此对于这些物理存储的优化是系统优化的一个重要部分。对于物理存储结构优化,主要是合理地分配逻辑结构的物理存储地址,这样虽不能减少对物理存储的读写次数,但却可以使这些读写尽量并行,减少磁盘读写竞争,从而提高效率,也可以通过对物理存储进行精密的计算减少不必要的物理存储结构扩充,从而提高系统利用率。

为了避免数据库文件之间的竞争,在物理设计时,文件应该被放到不同的I/O通道,跨越驱动器的文件分离,避免磁盘争用成为一个“瓶颈”。主要应该注意以下几点技巧:把关键数据文件分布在各个可用的磁盘上,这些文件包括表空间、回滚段或UNDO段、联机重做日志文件、操作系统盘、经常访问的表的数据文件以及经常访问的索引的数据文件;把数据和索引文件分开放置;对于经常连接的表,把它们的数据和索引表空间分开,这样每个表上的信息就不会放在相同的磁盘上;把控制文件的多个备份存储到不同的磁盘和控制器上,以最终实现操作并行化。

同时,还应将表数据和索引数据分开表空间存储,分别使用独立的表空间。因为假如将表数据和索引数据放在一起,表数据的I/O操作和索引的I/O操作将产生影响系统性能的I/O竞争,降低系统的响应效率。将表数据和索引数据存放在不同的表空间中,并在物理层面将这两个表空间的数据文件放在不同的物理磁盘上,就可以避免这种竞争了。

2.2  数据库的运行阶段

数据库的运行管理主要通过对数据库运行环境进行调整来达到改进性能的目的。在决定进行系统性能调优级时,首先应制定一个完善的调优级方案,先监控系统并分析问题所在,然后根据分析结果每次调整一个参数,再进一步监控系统查看系统性能有无变化,然后做进一步调节。其中有一个重要的原则:每次最好只调节一个参数。

2.2.1  数据库级参数性能调优

一般来说,数据库管理系统(DBMS)中与性能相关的参数都与对系统物理内存的设置有关,换言之,数据库级参数性能优化即是DBMS对系统内存的配置。通常,只要将这些主要参数设置好就会显著改善数据库系统的性能,因此,配置好数据库系统参数,是优化数据库系统运行环境的关键。

数据库管理系统对系统内存的配置应尽可能实现如下目标:

一是减少分页:当系统执行分页时,会将当前没有使用的信息从内存移到硬盘上。这样就可以为当前需要内存的程序分配内存。如果频繁地发生分页,系统性能就会严重降低,从而导致很多程序的执行时间变长。

二是减少内存交换:当系统执行内存交换时,会将活动进程临时地从内存移到硬盘上,这样另一个活动进程就可以得到所需要的内存。内存交换基于系统循环时间。如果内存交换过于频繁,就会产生大量的磁盘I/O,应用的性能可能会急剧恶化。

三是扩大高速数据存储内存缓冲区容量:用户的进程对这个内存区发送事务,并且以这里作为高速缓存读取命中的数据,以实现加速的目的。主要包括数据块缓冲、数据字典缓冲、恢复回滚日志缓冲以及SQL共享池等这几个部分摘要。对这些内存缓冲区的合理设置,可以大大加快数据查询速度,提高内存区的命中率。

2.2.2  操作系统级参数性能调优

(1)进行定期的磁盘检查和磁盘空间清理,当系统运行一段时间后,会出现一定的文件错误和磁盘碎片,此时就需要进行磁盘整理。

(2)自动关闭停止响应的程序,无须进行手工干预。

(3)调整应用程序优先级,让常用程序拥有较高的优先权,自然运行速度就会快些。

(4)配置操作系统核心使用更少的内存。

(5)配置操作系统与DBMS相关的内核参数以便将更多的系统内存留给DBMS使用。

2.2.3  网络级参数性能调优

网络带宽会影响系统性能,减少网络负载,可以改善系统的性能。

负载均衡将是大型应用高负荷访问和大量并发请求采用的终极解决办法,它提供了一种有效的方法来扩充服务器带宽,增加吞吐量,提高网络的灵活性和可用性。

对负载均衡的应用,可以从网络的不同层次入手,具体情况要看瓶颈所在,不外乎从传输链路聚合、采用更高层网络交换技术和设置服务器集群策略三个角度实现,一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建集群,这样的架构成本低、性能高还有很强的扩张性,随时往架构里面增减节点都非常容易。

3  结束语

在应用丛生、高度分布式的环境中,要总结出一套“放之四海皆准”的数据库性能优化方法论并不容易。但结合企业自身特色的性能优化流程却是有据可循的。同时,数据库性能优化方法还具有浓重的行业色彩。

在对数据库应用系统改进所采取的策略中,前面提到的每个方法可能都会被用到,本文介绍得比较粗浅,具体实现过程中很多细节还需要慢慢熟悉和体会,有时一个很小的参数设置,对于系统性能的影响就会很大,在此仅概而述之,以期达到抛砖引玉之效

Continue reading 【转】浅谈改进数据库应用系统性能的常用策略

【转】Web前端在移动

            Web前端在移动                    

Web前端的起源

Web应用诞生:随着GMail、 Google Map等优秀Web应用出现,Ajax在2004年之后一度成为热门话题。经过几年的发展,一批以Prototype、Dojo、Ext为首的 Ajax+UI的浏览器兼容框架不断出现。UI和Web中间新增了一层以Javascript为核心,专门处理数据传输、Web交互等内容的开发 层,Web前端。Web前端伴随Web应用而诞生,并逐步走来。

Web宿主之争:随着RESTful Web Service潮流的发展,后台服务也迅速实现了数据云端化,接口API化。但受IE垄断和发展缓慢的影响,Web前端始终走不出浏览器能力不足和兼容性 问题突出的困局。开发维护浏览器插件、Flash控件等更是无奈的选择。Web前端往往因为需要兼容IE6、IE7、FF、有无插件、有无Flash等情 况付出巨大开发代价。2006年,John Resig的jQuery框架从某个意义上解决了这个问题。我认为最大的突破在于让老旧浏览器适配新的Web标准,满足了开发者开发高效而兼容老旧浏览器 的需要。

Web标准化之路:Google 在 2008年推出了Webkit核心的浏览器Chrome(后来也发布了ChromeOS)。随着FireFox,Chrome,Safari,Opera 等浏览器开始对HTML5和CSS3的深入支持以及性能的不断优化,IE市场占有率的持续下滑。Web标准化终于等到了一个发展机遇。2010 年,HTML5和CSS3被Webkit核心的Chrome、Safari绚丽地实现后,IE9也表示全面支持HTML5后。Web标准进入一个高速发展 阶段。随后,浏览器GPU加速也浏览器厂商们所接受。在Web标准化、离线化、硬件化的浪潮中,Web应用逐渐具备了替代桌面应用条件和能力。Web前端 开发也在逐步取代桌面应用客户端开发。

移动Web应用背景

非智能机时代:Java和WAP是取代短信SP后的第一种移动互联网实现方式。这个年代虽然荒蛮,但很纯真。

前智能机时代:HP 把一台WinPPC 的PAD增加电话功能,做成第一台智能手机时。Windows Mobile和S60是这个时代的主角。基于手机系统的客户端应用就是移动互联网应用的最好形式。但是随着系统版本的不断升级,设备的差异不断增大。手机 客户端应用开发同样面临着与Web前端开发一样的兼容性开发效率和维护成本问题。

后智能机时代:随着iPhone和 Android(HTC、摩托罗拉、三星等)手机等的热卖,两个电子市场生态链逐步形成。再加上最近诺基亚和微软和合作,电子市场生态链之争拉开帷幕。客 户端应用成为了电子市场生态链的主角。不过随着三方系统的竞争升级,也伴随浏览器的不断优化。先不论WP7,iPhone和Android阵营的浏览器都 是webkit核心的,差异只在于硬件加速能力和设备资源的差异。这恰好也是移动Web应用的发展机遇。

移动Web应用开发

需求

互联网是个产品线丰富的产业,但不可能对所有产品都投入巨大开发成本。WAP能满足基本使用需求,而客户端应用满足主线产品的高端需求。还有一大片中高端需求无法很好满足。遗憾的是,限于开发成本,用户没有与其高端设备相匹配的非主线产品客户端可用。

开发成本无法避免,但可以择优。我们可以通过移动Web应用的方式来次优替代非主线产品客户端。这也是廉价的移动应用实现方式。

现状

目前iOS和Android系统的浏览器都是webkit核心的,我们可以开发移动Web应用来满足这块需求。iOS支持硬件加 速,Android系统也能满足基本Webkit的API功能,适宜通过区分iOS来提供差异化服务。iOS的Mobile Safari有足够能力提供webkitTransForm(图形变换,3D变换支持硬件加速)、webkitTransition(CSS3动画)、 SQLite、LocalStorage(离线存储)、 WebSocket(iOS 4.2+)服务。至于Android,因为需要兼容参差的低端设备,还是不建议使用复杂图形变换和CSS3动画,其它能力可以通过判断能否支持来选择使 用。另外多点触摸、重力感应、地理位置还是根据能否支持和需要来使用,主要用于优化用户体验,不影响基本交互方式。

未来

移动Web应用的起点比PC Web应用的高,但适用范围较窄。但移动Web应用将成为Web应用的一种延伸,从开发角度来看,应该是殊途同归的。

小结

Javascript的角色从诞生起的页面粘合剂转变成今天的Web应用开发语言,一路走来经过很多波折。有人喜欢他,有人讨厌他,在崇拜和谩 骂中成长过来。将来的路还很长,但迷雾已散去,前途是光明的。当中有无数人的付出汗水,也成就了少数应用的辉煌。不过他仍然是一个工具,为开发者服务,需 要人们一起来优化他,使用他。

Continue reading 【转】Web前端在移动

架构蓝图--软件架构 "4+1" 视图模型

见维基百科

http://en.wikipedia.org/wiki/Software_architecture

2005 年 1 月 01 日

本文基于多个并 发视图的使用情况来说明描述软件密集型系统架构的模型。使用多重视图允许独立地处理各"风险承担人":最终用户、开发人员、系统工程师、项目经理等所关注 的问题,并且能够独立地处理功能性和非功能性需求。本文分别对五种视图进行了描述,并同时给出了捕获每种视图的表示方法。这些视图使用以架构为中心的、场 景驱动以及迭代开发过程来进行设计。

引言

我们已经看到在许多文章和书籍中,作者欲使用单张视图来捕捉所有的系统架构要点。通过仔细地观察这些图例中的方框和箭头, 不难发现作者努力地在单一视图中表达超过其表达限度的蓝图。方框是代表运行的程序吗?或者是代表源代码的程序块吗?或是物理计算机吗?或仅仅是逻辑功能的 分组吗?箭头是表示编译时的依赖关系吗?或者是控制流吗?或是数据流吗?通常它代表了许多事物。是否架构只需要单个的架构样式?有时软件架构的缺陷源于过 早地划分软件或过分的强调软件开发的单个方面:数据工程、运行效率、开发策略和团队组织等。有时架构并不能解决所有"客户"(或者说"风险承担 人",USC 的命名)所关注的问题。许多作者都提及了这个问题:Garlan & Shaw 1、CMU 的 Abowd & Allen、SEI 的 Clements。作为补充,我们建议使用多个并发的视图来组织软件架构的描述,每个视图仅用来描述一个特定的所关注的方面的集合。



回页首

架构模型

软件架构用来处理软件高层次结构的设计和实施。它以精心选择的形式将若干结构元素进行装配,从而满足系统主要功能和性能需 求,并满足其他非功能性需求,如可靠性、可伸缩性、可移植性和可用性。Perry 和 Wolfe 使用一个精确的公式来表达,该公式由 Boehm 做了进一步修改:

软件架构 = {元素,形式,关系/约束}

软件架构涉及到抽象、分解和组合、风格和美学。我们用由多个视图或视角组成的模型来描述它。为了最终处理大型的、富有挑战 性的架构,该模型包含五个主要的视图(请对照图 1):

  • 逻辑视图(Logical View),设计的对象模型(使用面向对象的设计方法时)。
  • 过程视图(Process View),捕捉设计的并发和同步特征。
  • 物理视图(Physical View),描述了软件到硬件的映射,反映了分布式特性。
  • 开发视图(Development View),描述了在开发环境中软件的静态组织结构。

架构的描述,即所做的各种决定,可以围绕着这四个视图来组织,然后由一些用例 (use cases)或场景(scenarios)来说明,从而形成了第五个视图。正如将看到的,实际上软件架构部分从这些场景演进而来,将在下文中讨论。

图 1 - "4+1"视图模型
图 1 - "4+1"视图模型

我们在每个视图上均独立地应用 Perry & Wolf 的公式,即定义一个所使用的元素集合(组件、容器、连接符),捕获工作形式和模式,并且捕获关系及约束,将架构与某些需求连接起来。每种视图使用自身所特 有的表示法-蓝图(blueprint)来描述,并且架构师可以对每种视图选用特定的架构风格(architectural style),从而允许系统中多种风格并存。

我们将轮流的观察这五种视图,展现各个视图的目标:即视图的所关注的问题,相应的架构蓝图的标记方式,描述和管理蓝图的工 具。并以非常简单的形式从 PABX 的设计中,从我们在Alcatel 商业系统(Alcatel Business System)上所做的工作中,以及从航空运输控制系统(Air Traffic Control system)中引出一些例子―旨在描述一下视图的特定及其标记的方式,而不是定义这些系统的架构。

"4+1"视图模型具有相当的"普遍性",因此可以使用其他的标注方法和工具,也可以采用其他的设计方法,特别是对于逻辑 和过程的分解。但文中指出的这些方法都已经成功的在实践中运用过。

逻辑结构

面向对象的分解

逻辑架构主要支持功能性需求――即在为用户提供服务方面系统所应该提供的功能。系统分解为一系列的关键抽象,(大多数)来 自于问题域,表现为对象或对象类的形式。它们采用抽象、封装和继承的原理。分解并不仅仅是为了功能分析,而且用来识别遍布系统各个部分的通用机制和设计元 素。我们使用 Rational/Booch 方法来表示逻辑架构,借助于类图和类模板的手段 4。 类图用来显示一个类的集合和它们的逻辑关系:关联、使用、组合、继承等等。相似的类可以划分成类集合。类模板关注于单个类,它们强调主要的类操作,并且识 别关键的对象特征。如果需要定义对象的内部行为,则使用状态转换图或状态图来完成。公共机制或服务可以在类功能 (class utilities)中定义。对于数据驱动程度高的应用程序,可以使用其他形式的逻辑视图,例如 E-R 图,来代替面向对象的方法(OO approach)。

逻辑视图的表示法

逻辑视图的标记方法来自 Booch 标记法4。当仅考虑具有架构意义的条目时,这种表示法相当简单。特别是在这种设计级别上,大量的修饰作用不大。我们使用 Rational Rose? 来支持逻辑架构的设计。

图 2 - 逻辑蓝图的表示法
图 2 - 逻辑蓝图的表示法

逻辑视图的风格

逻辑视图的风格采用面向对象的风格,其主要的设计准则是试图在整个系统中保持单一的、一致的对象模型,避免就每个场合或过 程产生草率的类和机制的技术说明。

逻辑结构蓝图的样例

图 3 显示了 Télic PABX 架构中主要的类。

图 3 - a. Télic PABX 的逻辑蓝图 b.空中交通系统的蓝图
图 3 - a. Télic PABX 的逻辑蓝图 b.空中交通系统的蓝图

PABX 建立终端间的通信连接。终端可以是电话设备、中继线(例如,连接到中央办公室)、连接线(PABX 专线到 PABX 线)、电话专线、数据线、ISDN 等等。不同的线路由不同的接口卡提供支持。线路 controller 对象的职责是在接口卡上对所有的信号进行解码和注入,在特定于接口卡的信号与一致性的小型事件集合之间进行相互转换:开始、停止、数字化等。 controller 对象同时承载所有的实时约束。该类派生出许多子类以满足不同的接口类型。terminal 对象的责任是维持终端的状态,代表线路协调各项服务。例如,它使用 numbering plan 服务来解释拨号。conversation 代表了会话中的一系列终端 。conversation 使用了Translation Service(目录、逻辑物理映射、路由),以及建立终端之间语音路径的Connection Service 。

对于一个包含了大量的具有架构重要意义的类的、更大的系统来说,图 3 b 描述了空中交通管理系统的顶层类图,包含 8 个类的种类(例如,类的分组)。

进程架构

过程分解

进程架构考虑一些非功能性的需求,如性能和可用性。它解决并发性、分布性、系统完整性、容错性的问题,以及逻辑视图的主要 抽象如何与进程结构相配合在一起-即在哪个控制线程上,对象的操作被实际执行。

进程架构可以在几种层次的抽象上进行描述,每个层次针对不同的问题。在最高的层次上,进程架构可以视为一组独立执行的通信 程序(叫作"processes")的逻辑网络,它们分布在整个一组硬件资源上,这些资源通过 LAN 或者 WAN 连接起来。多个逻辑网络可能同时并存,共享相同的物理资源。例如,独立的逻辑网络可能用于支持离线系统与在线系统的分离,或者支持软件的模拟版本和测试版 本的共存。

进程是构成可执行单元任务的分组。进程代表了可以进行策略控制过程架构的层次(即:开始、恢复、重新配置及关闭)。另外, 进程可以就处理负载的分布式增强或可用性的提高而不断地被重复。

软件被划分为一系列单独的任务。任务是独立的控制线程,可以在处理节点上单独地被调度。

接着,我们可以区别主要任务、次要任务。主要任务是可以唯一处理的架构元素;次要任务是由于实施原因而引入的局部附加任务 (周期性活动、缓冲、暂停等等)。它们可以作为 Ada Task 或轻量线程来实施。 主要任务的通讯途径是良好定义的交互任务通信机制:基于消息的同步或异步通信服务、远程过程调用、事件广播等。次要任务则以会见或共享内存来通信。在同一 过程或处理节点上,主要任务不应对它们的分配做出任何假定。

消息流、过程负载可以基于过程蓝图来进行评估,同样可以使用哑负载来实现"中空"的进程架构,并测量在目标系统上的性能。 正如 Filarey et al. 在他的 Eurocontrol 实验中描述的那样。

进程视图的表示法

我们所使用的进程视图的表示方法是从Booch最初为 Ada 任务推荐的表示方法扩展而来。同样,用来所使用的表示法关注在架构上具有重要意义的元素。(图 4)

图 4 - 过程蓝图表示法
图 4 - 过程蓝图表示法

我们曾使用来自 TRW 的 Universal Network Architechure Services(UNAS0) 产品来构建并实施过程和任务集合(包扩它们的冗余),使它们融入过程的网络中。UNAS 包含 Software Architect Lifecycle Environment(SALE)工具,它支持上述表示方法。SALE 允许以图形的形式来描述进程架构,包括对可能的交互任务通信路径的规格说明,正是从这些路径中自动生成对应的 Ada 或 C++ 源代码。使用该方法来指定和实施进程架构的优点是易于进行修改而不会对应用软件造成太多的影响。

进程视图的风格

许多风格可以适用于进程视图。例如采用 Garlan 和 Shaw 的分类法1,我们可以得到管道和过滤器(Pipes and filters),或客户端/服务器,以及各种多个客户端/单个服务器和多个客户端/多个服务器的变体。对于更加复杂的系统,可以采用类似于 K.Birman 所描述的ISIS系统中进程组方法以及其它的标注方法和工具。

进程蓝图的例子

图 5 - Télic PABX 的过程蓝图(部分)
图 5 - Télic PABX 的过程蓝图(部分)

所有的终端由单个的 Termal process 处理,其中 Termal process 由输入队列中的消息进行驱动。Controller 对象在组成控制过程三个任务之中的一项任务上执行:Low cycle rate task 扫描所有的非活动终端(200 ms),将 High cycle rate task(10 ms)扫描清单中的终端激活,其中 High cycle rate task 检测任何重要的状态变化,将它们传递给 Main controller task,由它来对状态的变更进行解释,并通过向对应的终端发送消息来通信。这里 Controller 过程中的通信通过共享内存来实现。

开发架构

子系统分解

开发架构关注软件开发环境下实际模块的组织。软件打包成小的程序块(程序库或子系统),它们可以由一位或几位开发人员来开 发。子系统可以组织成分层结构,每个层为上一层提供良好定义的接口。

系统的开发架构用模块和子系统图来表达,显示了"输出"和"输入"关系。完整的开发架构只有当所有软件元素被识别后才能加 以描述。但是,可以列出控制开发架构的规则:分块、分组和可见性。

大部分情况下,开发架构考虑的内部需求与以下几项因素有关:开发难度、软件管理、重用性和通用性及由工具集、编程语言所带 来的限制。开发架构视图是各种活动的基础,如:需求分配、团队工作的分配(或团队机构)、成本评估和计划、项目进度的监控、软件重用性、移植性和安全性。 它是建立产品线的基础。

开发蓝图的表示方法

同样,使用 Booch 方法的变形,仅考虑具有架构意义的项。

图 5 - 开发蓝图表示方法
图 5 - 开发蓝图表示方法

来自 Rational 的 Apex 开发环境支持开发架构的定义和实现、和前文描述的分层策略,以及设计规则的实施。Rational Rose 可以在模块和子系统层次上绘制开发蓝图,并支持开发源代码(Ada、C++)进程的正向和反向工程。

开发视图的风格

我们推荐使用分层(layered)的风格,定义 4 到 6 个子系统层。每层均具有良好定义的职责。设计规则是某层子系统依赖同一层或低一层的子系统,从而最大程度地减少了具有复杂模块依赖关系的网络的开发量,得 到层次式的简单策略。

图 6 - Hughes 空中交通系统(HATS)的 5 个层
图 6 - Hughes 空中交通系统(HATS)的 5 个层

开发架构的例子

图 6 代表了加拿大的 Hughes Aircraft 开发的空中交通控制系统(Air Traffic Control system)产品线的 5 个分层开发组织结构。这是和图 3 b 描述的逻辑架构相对应的开发架构。

第一层 和第二层组成了独立于域的覆盖整个产品线的分布式基础设施,并保护其免受不同硬件平台、操作系统或市售产品(如数据库管理系统)的影响。第三层为该基础设 施增加了 ATC 框架,形成一个特定领域的软件架构(domain-specific software architecture)。使用该框架,可以在第四层上构建一个功能选择板。层次 5 则非常依赖于客户和产品,包含了大多数用户接口和外部系统接口。72 个子系统分布于 5 个层次上,每层包含了 10 至 50 个模块,并可以在其他蓝图上表示。

物理架构

软件至硬件的映射

物理架构主要关注系统非功能性的需求,如可用性、可靠性(容错性),性能(吞吐量)和可伸缩性。软件在计算机网络或处理节 点上运行,被识别的各种元素(网络、过程、任务和对象),需要被映射至不同的节点;我们希望使用不同的物理配置:一些用于开发和测试,另外一些则用于不同 地点和不同客户的部署。因此软件至节点的映射需要高度的灵活性及对源代码产生最小的影响。

物理蓝图的表示法

大型系统中的物理蓝图会变得非常混乱,所以它们可以采用多种形式,有或者没有来自进程视图的映射均可。

图 7 - 物理蓝图的表示法
图 7 - 物理蓝图的表示法

TRW 的 UNAS 提供了数据驱动方法将过程架构映射至物理架构,该方法允许大量的映射 的变更而无需修改源代码。

物理蓝图的示例

图 8 - PABX 的物理蓝图
图 8 - PABX 的物理蓝图

图 8 显示了大型 PABX 可能的硬件配置,而图 9 和图 10 显示了两种不同物理架构上的进程映射,分别对应一个小型和一个大型 PABX。C、F 和 K 是三种不同容量的计算机,支持三种不同的运行要求。

图 9 - 带有过程分配的小型 PABX 物理架构
图 9 - 带有过程分配的小型 PABX 物理架构
图10-显示了过程分配的大型PABX物理蓝图
图10-显示了过程分配的大型PABX物理蓝图

场景

综合所有的视图

四种视图的元素通过数量比较少的一组重要场景(更常见的是用例)进行无缝协同工作,我们为场景描述相应的脚本(对象之间和 过程之间的交互序列)。正如 Rubin 和 Goldberg 所描述的那样6。

在某种意义上场景是最重要的需求抽象,它们的设计使用对象场景图和对象交互图来表示4。

该视图是其他视图的冗余(因此"+1"),但它起到了两个作用:

  • 作为一项驱动因素来发现架构设计过程中的架构元素,这一点将在下文中讨论。
  • 作为架构设计结束后的一项验证和说明功能,既以视图的角度来说明又作为架构原型测试的出发点。

场景的表示法

场景表示法与组件逻辑视图非常相似(请对照图 2),但它使用过程视图的连接符来表示对象之间的交互(请对照图 4),注意对象实例使用实线来表达。至于逻辑蓝图,我们使用 Rational Rose 来捕获并管理对象场景。

场景的例子

图 11 显示了小型 PABX 的场景片段。相应的脚本是:

1. Joe的电话控制器检测和校验摘机状态的变换,并发送消息唤醒相应的终端对象。

2. 终端分配一些资源,并要求控制器发出拨号音。

3. 控制器接受拨号并传递给终端。

4. 终端使用拨号方案来分析数字流。

5. 有效的数字序列被键入,终端开始会话。

图 11 - 本地呼叫的初期场景――阶段选择
图 11 - 本地呼叫的初期场景――阶段选择

视图之间的对应性

各种视图并不是完全是正交的或独立的。视图的元素根据某种设计规则和启发式方法与其他视图中的元素相关联。

从逻辑视图到过程视图

我们发现逻辑视架构有几项重要特性:

  • 自主性:对象是主动的、被动的还是被保护的?
    • 主动对象享有调用其他对象或其自身操作的主动权,并且当其他对象对其进行调用时,具有对其自身 操作的完全控制权。
    • 被动对象不能主动调用任何操作,对其他对象调用自身的操作没有控制。
    • 被保护对象不能主动调用任何操作。但对自身的操作有一定的控制功能。
  • 持久化:对象是暂时的还是持久化的?它们是否会导致过程或处理器的终止?
  • 依赖性:对象的存在或持久化是否依赖于另一个对象?
  • 分布性:对象的状态或操作是否能被物理架构中的许多节点所访问?或是被进程架构中的几个进程所访问?

在逻辑视图中,我们认为每个对象均是主动的,具有潜在的"并发性",即与其他对象具有"平行的"行为,我们并不考虑所要达 到的确切并发程度。因此,逻辑结构所考虑的仅是需求的功能性方面。

然而,当我们定义进程架构时,由于巨大的开销,为每个对象实施各自的控制线程(例如,Unix 进程或 Ada 任务),在目前的技术状况下是不现实的。此外,如果对象是并发的,那么必须以某种抽象形式来调用它们的操作。

另一方面,由于以下几种原因需要多个控制线程。

  • 为了快速响应某类外部触发,包括与时间相关的事件。
  • 为了在一个节点中利用多个 CPU,或者在一个分布式系统中利用多个节点。
  • 为了提高 CPU 的利用率,在某些控制线程被挂起,等待其他活动结束的时候(例如,访问外部对象其他活动对象时),为其他的活动分配 CPU。
  • 为了划分活动的优先级(提高潜在的响应能力)。
  • 为了支持系统的可伸缩性(借助于共享负载的其他过程)。
  • 为了在软件的不同领域分离关注点。
  • 为了提高系统的可用性(通过 Backup 过程)。

我们同时使用两种策略来决定并发的程度和定义所需的过程集合。考虑一系列潜在的物理目标架构。以下两种形式我们可以任选其 一:

  • 从内至外:
    由逻辑架构开始:定义代理任务,该任务将控制一个类的多个活动对象的单个线程进行多元化处理;同一代理任务还执行持久化处理那些依赖于一个主动对象的对 象;需要相互进行操作的几个类或仅需要少量处理的类共享单个代理。这种聚合会一直进行,直到我们将过程减少到合理的较少数量,而仍允许分布性和对物理资源 的使用。
  • 由外至内:
    从物理结构开始:识别系统的外部触发;定义处理触发的客户过程和仅提供服务(而非初始化它们)的服务器进程;使用数据完整性和问题的串行化 (serialization)约束来定义正确的服务器设置,并且为客户机与服务器代理分配对象;识别出必须分布哪些对象。

其结果是将类(和它们的对象)映射至一个任务集合和进程架构中的进程。通常,活动类具有代理任务,也存在一些变形:对于给 定的类,使用多个代理以提高吞吐量,或者多个类映射至单个代理,因为它们的操作并不是频繁地被调用,或者是为了保证执行序列。

注意这并不是产生最佳过程架构的线性的、决定性的进程;它需要若干个迭代来得到可接受的折衷。还存在许多其他方法,例如 Birman 等人5 或 Witt 等人7提出的方法。 确切的实施映射的方法不在本文的讨论范围,但我们以一个小的例子来说明一下。

图 12 显示了一个小的类集合如何从假想的空中交通控制系统映射至进程。

flight 类映射至一个 flight 代理集合:有许多航班等待处理,外部触发的频率很高,响应时间很关键,负载必须分布于多个 CPU。并且,航班处理的持久化和分布性方面都取决于 flight server,为了满足可用性,还是使用 flight server 的一台备份服务器。

航班的 profile 和 clearance 总是从属于某个航班,尽管它们是复杂的类,但它们共享 flight 类的进程。航班分布于若干其他进程,特别是对于显示和外部接口。

sectorization 类,为 controller 的权限分配建立了空域划分。由于完整性约束,仅能被一个代理处理,但可以与 flight 类共享服务器过程:更新得并不频繁。

location 和 arispace 及其他的静态航空信息是受到保护的对象,在几个类中共享,很少被更新;它们被映射至各自的服务器,分布于其他过程。

图 12 - 从逻辑视图到过程视图的映射
图 12 - 从逻辑视图到过程视图的映射

从逻辑视图到开发视图

类通常作为一个模块来实现,例如 Ada 包中可视部分的一个类型。密切相关的类(类的种类)的集合组合到子系统中。子系统的定义必须考虑额外的约束,如团队组织、期望的代码规模(通常每个子系统 为 5 K 或 20 K SLOC)、可重用性和通用性的程度以及严格的分层依据(可视性问题),发布策略和配置管理。所以,通常最后得到的不是与逻辑视图逐一对应的视图。

逻辑视图和开发视图非常接近,但具有不同的关注点。我们发现项目规模越大,视图间的差距也越大。例如,如果比较图 3 b 和图 6,则会发现并不存在逐一对应的类的不同种类到层的映射。而如果我们考虑类的种类的"外部接口"-网关种类时,它的实现遍布若干层:通讯协议在第 1 层或以下的层,通用网关机制在第 2 层,而特定的网关在第 5 层子系统。

从进程视图到物理视图

进程和进程组以不同的测试和部署配置映射至可用的物理硬件。Birman 在 ISIS 项目中描述了详细的映射模式5。

场景主要以所使用类的形式与逻辑视图相关联;而与进程视图的关联则是考虑了一个或多个控制线程的、对象间的交互形式。

模型的剪裁

并不是所有的软件架构都需要"4+1"视图。无用的视图可以从架构描述中省略,比如: 只有一个处理器,则可以省略物理视图;而如果仅有一个进程或程序,则可以省略过程视图。 对于非常小型的系统,甚至可能逻辑视图与开发视图非常相似,而不需要分开的描述。场景对于所有的情况均适用。

迭代过程

Witt 等人为设计和架构指出了 4 个阶段:勾画草图、组织、具体化和优化,分成了 12 个 步骤7。他们还指出需要某种程度的反向工程。而我们认为对于大型的项目,该方法太"线性 化"了。在 4 个阶段的末尾,可用于验证架构的内容太少。我们提倡一种更具有迭代性质的方法,即架构先被原形化、测试、估量、分析,然后在一系列的迭代过程中被细化。该 方法除了减少与架构相关的风险之外,对于项目而言还有其他优点:团队合作、培训,加深对架构的理解,深入程序和工具等等(此处提及的是演进的原形,逐渐发 展成为系统,而不是一次性的试验性的原形)。这种迭代方法还能够使需求被细化、成熟化并能够被更好地理解。

场景驱动(scenario-driven)的方法

系统大多数关键的功能以场景(或 use cases)的形式被捕获。关键意味着:最重要的功能,系统存在的理由,或使用频率最高的功能,或体现了必须减轻的一些重要的技术风险。

开始阶段:

  • 基于风险和重要性为某次迭代选择一些场景。场景可能被归纳为对若干用户需求的抽象。
  • 形成"稻草人式的架构"。然后对场景进行"描述",以识别主要的抽象(类、机制、过程、子系统),如 Rubin 与 Goldberg6 所指出的 ―― 分解成为序列对(对象、操作)。
  • 所发现的架构元素被分布到 4 个蓝图中:逻辑蓝图、进程蓝图、开发蓝图和物理蓝图。
  • 然后实施、测试、度量该架构,这项分析可能检测到一些缺点或潜在的增强要求。
  • 捕获经验教训。

循环阶段:

下一个迭代过程开始进行:

  • 重新评估风险,
  • 扩展考虑的场景选择板。
  • 选择能减轻风险或提高结构覆盖的额外的少量场景,

然后:

  • 试着在原先的架构中描述这些场景。
  • 发现额外的架构元素,或有时还需要找出适应这些场景所需的重要架构变更。
  • 更新4个主要视图:逻辑视图、进程视图、开发视图和物理视图。
  • 根据变更修订现有的场景。
  • 升级实现工具(架构原型)来支持新的、扩展了的场景集合。
  • 测试。如果可能的话,在实际的目标环境和负载下进行测试。
  • 然后评审这五个视图来检测简洁性、可重用性和通用性的潜在问题。
  • 更新设计准则和基本原理。
  • 捕获经验教训。

终止循环

为了实际的系统,初始的架构原型需要进行演进 。较好的情况是在经过 2 次或 3 次迭代之后,结构变得稳定:主要的抽象都已被找到。子系统和过程都已经完成,以及所有的接口都已经实现。接下来则是软件设计的范畴,这个阶段可能也会用到 相似的方法和过程。

这些迭代过程的持续时间参差不齐,原因在于:所实施项目的规模,参与项目人员的数量、他们对本领域和方法的熟悉程度,以及 该系统和开发组织的熟悉程度等等。因而较小的项目迭代过程可能持续 2-3 周(例如,10 K SLOC),而大型的项目可能为 6-9 个月(例如,700 K SLOC)。

架构的文档化

架构设计中产生的文档可以归结为两种:

  • 软件架构文档,其结构遵循"4+1"视图(请对照图 13,一个典型的提纲)
  • 软件设计准则,捕获了最重要的设计决策。这些决策必须被遵守,以保持系统架构的完整性。
    图 13 - 软件架构文档提纲
    图 13 - 软件架构文档提纲



回页首

结束语

无论是否经过一次本地定制的和技术上的调整,"4+1"视图都能在许多大型项目中成功运用。事实上,它允许不同的"风险承 担人"找出他们就软件架构所关心的问题。系统工程师首先接触物理视图,然后转向进程视图;最终用户、顾客、数据分析专家从逻辑视图入手;项目经理、软件配 置人员则从开发视图来看待"4+1"视图。 在 Rational 和其他地方,提出并讨论了其他系列视图,例如 Meszaros(BNR)、Hofmeister。Nord 和 Soni(Siemenms)、Emery 和 Hilliard(Mitre),但我们发现其他视图通常可以归入我们所描述的 4 个视图中的一个。例如 Cost&Schedule 视图可以归入开发视图,将一个数据视图归入一个逻辑视图,以及将一个执行视图归入进程视图和物理视图的组合。

表 1 - "4+1"视图模型一览表
表 1 - "4+1"视图模型一览表

Continue reading 架构蓝图--软件架构 "4+1" 视图模型

【转】Comet is Always Better Than Polling

Comet is Always Better Than Polling

by Greg WilkinsNovember 6th, 2007            

               

Comet techniques are advocated when your application needs low latency events to be delivered from the server to the browser. Comet can deliver sub-second latency for messages making possible web applications like chat, games and real-time monitoring of prices and states.

It is often asserted that for applications that don’t need low latency (e.g. email readers), traditional polling is a better alternative. However, some rudimentary analysis shows this assertion to be wrong, and that Comet techniques can be applied to all required latencies and event rates to provide improved data rates and average latencies.

For this analysis, I have considered polling vs. the long-polling technique where a server may hold a poll request for a period of time while waiting for events/messages to be delivered to the browser. In order to ensure that we are comparing apples with apples and oranges with oranges, I have compared configurations that provide the same maximum latency. For example, for a maximum latency of 10s, the polling technique must issue a poll every 10s and the average latency is half that. For the Comet technique long polling, a long poll needs to be issued 10s after the last long poll completes, but the server may hold the long poll for up to 300s while waiting for an event.

The attached spreadsheet contains the calculations, which I have graphed for 1s, 10s and 100s maximum latency for message rates of 1, 10, 100 and 1000 messages per second for 1000 users. The results show that the Comet long polling technique uses less bandwidth than polling in all situations, and uses significantly less bandwidth when the average period between messages is longer than the maximum latency:

Not only does Comet long-polling provide superior data rates, it also provides superior average latency. The Comet technique allows the average latency to be lower than the maximum latency because once the pause between polls is complete, the long poll is ready to respond immediately to events.

This analysis shows that for the worst case, when the message rate is high, load and latency for Comet long-polling are identical to traditional polling, and for most cases the load and latency are significantly better than traditional polling.
The calculations for these graphs are in this Comet vs Polling spreadsheet. The assumptions made are that all messages are equal in size (150Bytes) and that the message arrival times are randomly but uniformly distributed. A maximum long poll timeout of 240s is assumed. The Y axis of the graphs is logarithmic so larger differences appear smaller.

Continue reading 【转】Comet is Always Better Than Polling

voice srgs语法相关

grxml:使用xml书写srgs的方式
abnf:rfc5234规范,
现在,几乎每一位新编程语言书籍的作者都使用巴科斯范式来定义编程语言的语法规则。
例如sql语法帮助也是用这个来描述的。
然而srgs中的abnf是混合bnf和abnf的语法,例如或|是bnf写法,/被改做为权重, =又是abnf写法,bnf写法是:=

-------------------------------------------abnf双模式示例
#ABNF 1.0 UTF-8;

language en;
mode voice;
root $basicCmd;

public $basicCmd = (dtmf-1 | yes) {y} | (dtmf-2 | no) {n};


------------------------------------------------------------------------

在voice中既然后台具备自然语言处理的能力,就不应该使用tag而应该直接返回所有匹配项。

$object = [the | a] (window | file | menu);
这样的写法用户说了the就会返回the,没说就不会返回the,所以都用[]比较好。
$object = [the | a] [window | file | menu];

--------------------------------------------------------------------------

grxml

item下面可以有ruleref但不能是rule

<rule id="r_3">
        <one-of>
            <item>
                <tag><![CDATA[Yes]]></tag>    //可以
                <ruleref uri="#r_4" />
            </item>
            <item>
                <tag><![CDATA[No]]></tag>
                <ruleref uri="#r_5" />
            </item>
        </one-of>
    </rule>

item在下面放one-of是可以的
<rule id="r_0">
        <one-of>
            <item>
                <tag><![CDATA[__QUERY__]]></tag>
                <item repeat="1-">
                    <one-of>
                        <item>what</item>
                        <item>who</item>
                        <item>where</item>
                        <item>how</item>
                        <item>why</item>
                        <item>whom</item>
                    </one-of>
                </item>
                <item repeat="0-">
                    <one-of>
                        <item>is</item>
                        <item>are</item>
                        <item>were</item>
                        <item>does</item>
                        <item>do</item>
                        <item>did</item>
                        <item>will</item>
                        <item>would</item>
                        <item>shall</item>
                        <item>should</item>
                        <item>may</item>
                        <item>might</item>
                    </one-of>
                </item>
                <item>
                    <ruleref special="GARBAGE" />
                </item>
            </item>
        </one-of>
    </rule>

Continue reading voice srgs语法相关

applet沙箱权限问题

官方解释:

http://download.oracle.com/javase/6/docs/technotes/guides/plugin/developer_guide/security.html

  • All unsigned applets are run under the standard applet security model.
  • If usePolicy is not defined in the java.policy file, then a signed applet has the AllPermission permission only if Java Plug-in can verify the signers, and the user agrees to granting the AllPermission permission when prompted.
  • If usePolicy is defined, then a signed applet has only the permissions defined in java.policy and no prompting occurs.

对于第二点,就是说签了名的一般都是有所有权限的。

但是还需要如下的处理[这个是必要的]
对于签名的applet,

  1. AccessController.doPrivileged(new PrivilegedExceptionAction() { 
  2.    public Object run() throws Exception { 
  3.    //you unsafe code                                          
  4.        return null; 
  5.    } 
  6. }); 


我们知道Java applet在浏览器中运行时默认情况下是不能访问本地资源的,比如读写客户端电脑上的文件。这是Java的安全沙箱机制,简单说就是有一组安全检查规 则,要通过检查之后才能访问特定资源。不过在企业应用中这种安全机制有时候并不是十分必要,这里我们就讨论一下在企业应用中突破沙箱检查的方案。
    当然,很多朋友会说,这太简单了,只需要改一下java.policy就可以了,授予程序对所有权限就可以了,就像下面这样:
     grant {
          permission java.security.AllPermission;
     };
没错,这样确实可以使客户端applet有权限访问任何资源,但是这个方案有个很实际的问题:java.policy是位于每个客户端电脑的jre 目录下的,如果要修改,那么就需要通知每一个使用该系统的用户,并指导他们做相应操作。这对于搞IT的用户来说是小菜一碟,但对一般业务人员来说却是个额 外的工作,这样的发布方式很难被人认可。

    另一个方案——对applet进行签名,用户访问时系统会弹出安全提示框,用户如果信任该程序,点击确认就相当于赋予了这个客户端小程序访问本地资源的权限。这是个很典雅的方案,体现了系统安全和对用户权利的尊重!具体做法大致如下:
    1、编写applet,编译并打成jar包
    2、对jar包签名
        这一步首先要产生证书,利用jdk提供的工具,执行类似下面的命令:
       keytool -genkey -keystore d:\mykeys.store -alias test -validity 300
       根据系统提示执行完这个命令后会生成一个证书库,上例是:mykeys.store,-validity 300是证书有效期为300天的意思,接下来用这个证书库中的证书给jar包签名,仍然是jdk的工具,命令类似下面:
       jarsigner -keystore d:\mykeys.store d:\applet.jar test
    3、把applet.jar发布到应用服务器

    这个看似完美的方案实际也有一点问题,很多时候我们并不希望把客户端程序都打到一个jar包里,那么多个jar包就需要分别签名,每次修改完客户端程序, 都要重新打包和签名,不然就只有applet能访问本地资源。我们不想这么麻烦,甚至我们有时都不希望对客户端代码打包,这时候签名就不好实现了。那么如 何解决这个问题呢,看下面这招。
    既然applet已经被用户授权,那么是否可以在applet里改变安全管理器(SecurityManager)?实验证明是可以的!只需要继承 SecurityManager类,创建自己的安全管理器类,然后覆盖checkPermission方法,允许访问任何资源。在applet的init 方法中调用System.setSecurityManager把安全管理器设置为我们自己的就一切OK了!

    至此,我们彻底突破了沙箱检查,而且客户体验很好,完美的方案!

代码很简单,类似于下面这样即可:[这种解决方法我也加了,没有测试是否必须--好像不起作用,没签名的引用包还是报错]
public class MainApplet extends JApplet {

private class DefaultSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission perm, Object context) {
}

@Override
public void checkPermission(Permission perm) {
}
}

@Override
public void init() {
super.init();
System.setSecurityManager(new DefaultSecurityManager());
  }
}

总结:
如果有是默认权限之外的代码:
1:需要签名
2:需要在applet中

  1. AccessController.doPrivileged(new PrivilegedExceptionAction() { 
  2.    public Object run() throws Exception { 
  3.    //you unsafe code                                          
  4.        return null; 
  5.    } 
  6. }); 

3:需要用户接受证书

在写skype4java applet时遇到的问题都是关于将包内资源dll加载的问题,winp,skype4java的实现都在applet环境下工作不好,我的解决方法是将其复制到tmp目录下再加载即可。

Continue reading applet沙箱权限问题

html5资源

[标准]
http://dev.w3.org/html5/postmsg/
http://dev.w3.org/html5/websockets/
http://dev.w3.org/html5/eventsource/
[当前实现]
http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28HTML_5%29#Related_specifications
[game教程]
http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx
[中文教程]
http://kb.operachina.com/node/190
[cake框架教程]
http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/08/24/cake-programming-tutrorials.aspx
gif动画转图片
http://share.wglm.net:81/ts/Ulead_GIF_Animator5.0.rar
游戏
https://github.com/oldj/html5-tower-defense
websocket的缺陷
http://blogs.webtide.com/gregw/entry/websocket_chat
1:经常断线
2:不知道是否发送成功
3:keepalive
4:消息重发导致死循环[消息体过大]
替代物

Comet is Always Better Than Polling

-----------------------------------------------------------------------------------------------------------------------------

 

推荐10款非常优秀的HTML5开发工具

2011-10-09 09:37 | 2649次阅读 | 来源:梦想天空的博客 【已有0条评论】发表评论

关键词:HTML5 | 作者:梦想天空 | 收藏这篇资讯

HTML5发展如火如荼,随着各大浏览器对HTML5技术支持的不断完善以及HTML5技术的不断成熟,未来HTML5必将改变我们创建Web应用程序的方式。今天这篇文章向大家推荐10款优秀的HTML5开发工具,帮助你更高效的编写HTML5应用。

1.Initializr

推荐10款非常优秀的 HTML5 开发工具

Initializr是制作HTML5网站最好的入门辅助工具,你可以使用提供的特色模板快速生成网站,也可以自定义,Initializr会为你生成代码简洁的可定制的网页模板。

2.HTML5demos

推荐10款非常优秀的 HTML5 开发工具

想知道你的浏览器是否支持HTML5 Canvas吗?想知道Safari是否可以运行简单的HTML5聊天客户端吗?HTML5demos会告诉你每一个HTML5特性在哪些浏览器中支持。

3.HTML5 Tracker

推荐10款非常优秀的 HTML5 开发工具

想了解HTML5的最新动向吗?使用HTML5 Tracker吧,它可以跟踪HTML5最新修订信息。

4.HTML5 visual cheat sheet

推荐10款非常优秀的 HTML5 开发工具

想要快速超找一个标签或者属性吗?看看这个非常酷的速查手册吧,每个Web开发人员的必备。

5.Switch To HTML5

推荐10款非常优秀的 HTML5 开发工具

Switch To HTML5是一个基础而有效模板生成工具。如果你开始一个新项目,可以到这里获取免费的HTML5网站模板。

6.Cross browser HTML5 forms

推荐10款非常优秀的 HTML5 开发工具

HTML5中的日历,取色板,滑块部件等都是非常棒工具,但是有些浏览器不支持。这个页面将帮助你构建完美的HTML5表单兼容方案。

7.HTML5 Test

推荐10款非常优秀的 HTML5 开发工具

你浏览器准备好迎接HTML5革命了吗?HTML5 Test将告诉你。这个网站会为你当前使用的浏览器生成一份对video、audio、canvas等等特性的支持情况的完整报告。

8.HTML Cheat Sheat

Canvas元素是HTML5最重要的元素之一,它可以在网页中绘制图形,非常强大。这是一个Canvas元素的详细速查手册。

9.Lime JS

推荐10款非常优秀的 HTML5 开发工具

LimeJS是一个HTML5游戏开发框架,用于快速构建运行于触屏设备和桌面浏览器的游戏。非常棒,一定要用用试试。

10.HTML5 Reset

推荐10款非常优秀的 HTML5 开发工具

HTML5 Reset是一组文件,包括HTML、CSS等,用于在开始新项目的时候帮助你节省时间,提供HTML5的空白WordPress模板。

Continue reading html5资源

[转]WebTest比拼Selenium:模拟和真实浏览器上的测试

 

作者 Geoffrey Wiseman 译者 乔梁 发布于 2007年11月5日 上午1时24

Web应用软件的功能测试工具有很多种,但它们最根本的差异在于:某些工具可以驱动一个或多个真正的浏览器以便得到完全真实的环境,比如Selenium,而另一些工具只是模拟Web浏览器的操作,比如Canoo WebTest。Marc Guillemot这两种工具进行了对比,根据他的观点,WebTest以13:5的比分获胜。
Marc就以下方面内容对这两种工具进行了对比和评分:

Canoo WebTest

Selenium

Tied

Reports

Browser Fidelity

Testing Ajax

Speed

Beginner Friendly

Integration into Development Process

Support for Badly Formatted HTML Code

Scalability

Multi-Language Support

Capture JS Errors

Documentation

Predictable Behaviour

XPath Support

Extensibility

Data-Driven Tests

Internationalization Support

Support for Non-HTML Content

Marc认为,这些测试不够快,但“WetTest 的工作不多,所有测试都运行在JVM上”。他也提到Selenium无法捕获Javascript错误导致的测试失败:
只要你的单元测试通过了,你就不在意编辑错误了吗?肯定不是!但事实上,Selenium就是这样的,因为它不能检测到你的应用程序中的javascript错误(除非这些测试直接导致测试失败)。
另外,他也提到Ajax 测试(一般来说,大家都认为这是浏览器模拟器的弱点)是一种纽带:
与一般的想法相反,你并不需要在浏览器中运行你的JavaScript测试来测试AJAX功能。HtmlUnit和WebTest可以完成这样的工作,甚至可以称为完全胜任这样的工作,因为它允许更好地测试页内请求,使不可预知的浏览器行为成为可预知的(参见我前一个帖子)。
另一方面,他相信Selenium可以支持多种语言,“Selenium RC可以与不同的开发语言(Java、Ruby、PHP等等)结合,而WebTest只能与Ant结合使用”,还支持不规范的Html以及真实的浏览器:
HtmlUnit对JavaScript支持已经大幅改善,但还不能(且永远不可能)与真正的浏览器行为一模一样。尽管Selenium也更改了一些Web应用的JavaScript正常执行,但它使用真正的浏览器工作,所以已经和浏览器的标准行为相当接近啦。
作为Canoo WebTest和HtmlUnit的首席开发人员,Marc明显倾向于他所接纳的这种形式的工具,在与他讨论之前,请一定要先读一下他的分析报告:
显然,作为WebTest(和HtmlUnit)的负责人,我的确是有倾向性的。但是,我也有多年开发和维护庞大的功能测试套件的经验。客观一点儿说,我可能在其它方向上过分担心了,应该相信Selenium。当然,我将不断地修正我在Selenium理解上的错误。但请您在开始批评我之前,一定要读一下这篇文章。
已经总结了这些反馈。Vitaly认为,WebTest和Selenium的关系可以看作是苹果和桔子的关系。“Selenium,WebTest(HttpUnit),DBUnit,JUnit和其它测试工具是互补的。有些事用这个工具可能完成,用另外一个工具却不成。”还有些人讨论了录制回放和脚本测试各自的优点,以及测试可维护性。Murali推荐使用PragmaticQA Element
Christian反驳了WebTest对Ajax支持的说法,并提及在他的应用中,“由于HtmlUnit不能解析Dojo的import子句,即使最简单的页面也会抛出异常。”
而Simon认为,对浏览器保真度最重要的一点就是:
象 WebTest这样的工具有点太理论化了,它想证明代码完全正常工作,但是只能在理想环境下,与生产环境相去甚远。真正的用户使用的是IE或 Firefox,而Selenium可以让我们在“真实的”条件下做测试,例如有内存泄漏问题的脆弱的浏览器,和不符合标准的代码。
没有客户使用WebTest使用的引擎,这意味着尽管我们知道它在某种环境上运行得很好,但并不意味着真的没有麻烦。相反,我们的Selenium测试运行在Firefox之上,也运行在IE之上,所以它会捕获跨平台使用中发生的很多问题。
最后,Kent Tong设想了结合两种方法的途径
是否可以开发这样一种中间层,即大家只写一套测试,即可以运行在WebTest上,又可以运行在Selenium之上?这样,大家就可以得到WebTest和Selenium各自带来的好处了。
你用过这些工具吗,或者其它功能测试工具?这会吸引你参与讨论下一代功能测试工具吗?更多的信息,请阅读Canoo WebTestSeleniumTesting下一代功能测试工具
英文原文链接:WebTest vs. Selenium: Real and Simulated Browser Testing

相关厂商内容

Web App应用开发者大会火热报名中(4月27日 北京 免费)!
2011年5月11日-13日第十届中国系统与软件过程改进年会
Adobe Flash Builder 4简体中文正式版高速下载

2 条回复

关注此讨论 回复
真实的环境下测试 发表人 胡 凯 发表于 2007年11月5日 上午8时15分

Re: 真实的环境下测试 发表人 blogbin avatar 发表于 2007年11月16日 上午7时7分

按日期倒序排列

  1. 返回顶部
  2. 真实的环境下测试
  3. 2007年11月5日 上午8时15分 发表人 胡 凯
  4. 在项目中有同时使用JWebUnit和Selenium, 虽然每天都在Selenium缓慢的运行中煎熬, 但是依然推荐使用, 进行这样功能测试的目的之一就是希望在所有目标环境中这部分功能都是可以正常工作的。 也就是在真实的条件下作测试, 在JWebunit中正确通过的功能, 能否在IE6/7, firefox,中正确工作? 所有人大概心里都没底。
  5. JWebUnit的速度很快,但是在运行的过程中开发者缺乏对Web项目的最直观的体验, 而且其使用的JS 引擎对于某些正确的js也会抛出异常,后来不得不关闭JWebUnit的javascript engine.
  6. 事实上JWebunit测试可以用做整个开发流程的Checkin gate, 将覆盖基本功能,容易失败的测试用JWebunit完成,在测试通过后就可以提交,然后进行下一步的工作,同时在CI Server上在多个浏览器中运行较为缓慢的Selenium作为acceptance gate。 这大概是能兼顾速度和“真实”的一种方式。
  7. --
  8. Hu Kai
  9. 回复
  10. 返回顶部
  11. Re: 真实的环境下测试
  12. 2007年11月16日 上午7时7分 发表人 blogbin avatar
  13. 是否可以开发这样一种中间层,即大家只写一套测试,即可以运行在WebTest上,
  14. 又可以运行在Selenium之上?这样,大家就可以得到WebTest和Selenium各自带来的好处
  15. 同感:
  16. 测试脚本的设计,开发和维护的工作量相当大,能够让正常跑起来实属不易。
  17. 不同厂商和组织提供许多测试工具,不过这些测试脚本并没有形成统一的标准和规范。

Continue reading [转]WebTest比拼Selenium:模拟和真实浏览器上的测试

hibernate杂项

使用hibernate自动生成工具时 会自动加catorry
如:
<hibernate-mapping>
    <class name="co.iplatform.management.data.Health" table="tservice_health" catalog=”xxx”>
但是往往你刚开始用的数据库名是暂时的,与产品库不一样,所以发布时要注意改正这些名字。( 如果不一致mysql报错却是什么拒绝访问某表,根本不知道是数据库选错了)
一般的不需要catalog比较好,在数据库连接字符串里指定默认数据库就行了。
数据库表名大小写敏感?反正mysql是这样的aBc != abc
乱码问题,数据库要设置好编码, 连接也需要写好编码 例如 :
jdbc:mysql://localhost:13306/moviebug?useUnicode=true&amp;characterEncoding=UTF-8
还不行,则要查找其他原因

--------------------

native sql

以前查询把查询放在事务里面就可以保证取得最新数据,这次在management console里面就遇到问题,调用native sql后查询的还是旧数据。

hibernate说当调用commit或session.flush时会同步数据,网上说commit是先flush在提交。
不管怎样,flush一定会同步数据,这是最保险的做法。

且查询不一定需要放在事务里面(某些情况除外)。

对于使用了native sql的情况,要注意,hibernate并不知道native sql会对数据产生影响,所以,执行了native sql后要session.flush而且要clear。

-------------------------


Continue reading hibernate杂项

爬数据问题

想截取豆瓣的内容 ,发现以下问题 
一般的 网站都有防止被 iframe包含的脚本 ,所以 用iframe不行
我再试 window.open打开窗口来 加载脚本 ,但是
window的 onload事件 不能 监听,可能是跨域 问题 ,那么就做不下去了
-------------------
>

(function() {
function g_log(msg) {
if (!window.mylog_win) {
 window.mylog_win = window.open('', 'log');
}
var doc = window.mylog_win.document;
doc.write(msg + '<br>');
}
function DoubanTask() {
var URL = 'http://movie.douban.com/subject/';
var INDEX_BEGIN = 1000000;
var INDEX_END = 1999999;
var TRYCOUNT = 3;
var tryicount = 0;
var win = window.open('', 'doubanwin');
var url_index = INDEX_BEGIN;
function log (msg) {
 g_log(msg);
};
function getData() {
 var doc = Ext.get(win.document.body);
 var score = doc.query('strong[property=v:average]')
 if (!score || !score.length) {
  log('score not find,return null.');
  return null;
 }
 score = score[0].innerHTML;
 var vote = doc.query('span[property=v:votes]')
 if (!vote || !vote.length) {
  log('score not find,return null.');
  return null;
 }
 vote = vote[0].innerHTML;
 var name = doc.query('span[property=v:itemreviewed]')
 if (!name || !name.length) {
  log('name not find,return null.');
  return null;
 }
 name = name[0].innerHTML;
 var year = doc.query('span[class=year]')
 if (year && year.length) {
  year = year[0].innerHTML;
 }
 var director = doc.query('a[rel=v:directedBy]')
 if (director && director.length) {
  director = director[0].innerHTML;
 }
 if (year) {
  var i0 = year.indexOf('(');
  if (-1 != i0) {
   year = year.substring(i0 + 1);
  }
  i0 = year.indexOf(')');
  if (-1 != i0) {
   year = year.substring(0, i0);
  }
 }
 return {
  score : score,
  vote : vote,
  name : name,
  year : year,
  director : director
 };
}
function onloadfunc(url) {
 var data = getData();
 if (!data) {
  log('retrive no data in [' + url + '],continue.');
  runtask();
  return;
 }
 data.url = url;
 log('get data:' + Ext.encode(data));
 Ext.Ajax.request({
    url : "mytime.ax",
    params : data,
    success : function() {
     tryicount = 0;
     log('submit ok for url:' + url);
     runtask();
    },
    failure : function() {
     tryicount += 1;
     log('submit fail[' + tryicount + '] for url:' + url);
     if (tryicount > TRYCOUNT) {
      tryicount = 0;
      log('cancel try for:' + url
        + ', move for next none.');
      runtask();
     } else {
      log('continue try for:' + url);
      onloadfunc(url);
     }
    }
   });
}
function runtask() {
 url_index += 1;
 if (url_index >= INDEX_END) {
  log('task complete!');
  return;
 }
 var url = URL + url_index;
 //no use, can't work
 win.document.body.onload = function() {
  onloadfunc(url);
 };
 win.location.href = url;
}
this.run = function() {
 runtask();
};
}
function onload() {
var dbTask = new DoubanTask();
var btnRun1 = Ext.get('btnStart');
btnRun1.on('click', function() {
   dbTask.run();
  });
}
Ext.fly(window).on('load', onload);
})();

-------------------------

>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>run.html</title>
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
    <script type="text/javascript" src="../js/ext-core.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
</head>
<body>
 <table>
  <tr><td>
  <button id="btnStart">Start</button>
       
  <td></tr>
  <tr><td><iframe id="frm1"></iframe><td></tr>
 </table>    
</body>
</html>

-------------------------------

换取思路,可以使用ajax请求由服务端通过httpclient取得数据返回给客户端,再由客户端

写到iframe里面,这样就避开了跨域问题了。但是httpclient爬数据时要注意伪装成浏览器,加上请求头'User-Agent' : 'Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101 Firefox/4.0',其余的就不要加了,加了反而会有问题(莫名其妙的返回)

HtmlUnit基于mozila实现,可以考虑

发现豆瓣提供api晕菜

-------------

Continue reading 爬数据问题

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1