qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

性能调优之我见

谈到软件产品的性能调优,我认为可以从狭义和广义两个范围来理解。从狭义的范畴来看,性能调优主要是指通过修改软件程序逻辑、结构等技术手段提升软件产品的各项性能指标,如响应时间等等;而从广义的层面来看,就不仅限于程序内部了,因为造成系统性能问题的瓶颈很可能来源于方方面面,而这种情况往往是性能调优很普遍的情况,下面就从广义的范围细分成几个角度来进行阐述。

  一、软件层面

  a)首先要谈到的肯定是我们自己提供的软件产品,因为它的内部设计是我们最清楚的,用户在应用时遇到性能问题首先要质疑的也是我们的产品,因此这个层面的调优肯定是我们软件供应者的重中之重!举例来说:比较复杂的业务,通常会在程序中输出一些关键操作的执行时间,然后再分析哪些操作比较耗时,之后再找原因。具体分析原因就比较多了,比如多次循环查询数据库,复杂耗时的SQL语句,频繁的远程调用,复杂算法,等等。

  b)数据库层面:设计数据库时应考虑到在少访问和简化、优化访问的前提下实现产品功能,多用存储过程代替完整SQL,尽量用连接池使用户和服务的连接实现可复用,尽量不使用游标结构等,对基本表的设计进行优化如第三范式、引入“中间表”的技术思路,控制用户实际数据量的增长;对数据库进行索引优化,避免整表扫描;对数据库的事务处理进行调优(去除不必要的锁、将事务切分成小的粒度、适当降低隔离级别、减少访问热点等);SQL语句调优(尽量优化那些无意义的、拙劣的、复杂的SQL)等等。这方面主要就是本着一个通过尽可能少的磁盘访问而获得所需要的数据这么一个基本原则。

  c)中间件软件:某些软件产品为数据库、中间件、客户端的三层架构设计,此时为系统运行提供服务的中间件软件也将成为制约性能的一个瓶颈。因此在这个层面上也是有很大调优空间的,比如各种相关参数的设置优化,使用性能包、性能监控分析工具等,避免竞争线程资源,批处理,堆大小的设置,为溢出条件设置执行队列,后备缓冲,减少非重要应用的资源占用,使用集群等。举个简单的实例,我曾经遇到一个产品的性能问题,当查询数据大到一定程度时,系统一直灰屏死机状态,结果只是通过把JVM内存参数设置从默认值的128调为256就轻松解决了,只是参数值的一个小变动,反映到具体的用户面前就是出的来和出不来数据的本质差别!

  d)操作系统:无论是服务器还是用户终端,都脱离不了操作系统这个基础的应用平台的支持,因此这个层面的性能调优工作也千万不能遗漏。例如同厂商的不同版本(如WINDOWS各系列)、不同厂商(MS/HP/SUN等)不同的操作系统(WINDOWS/LINUX/UNIX等),这些操作系统的性能表现本身就有所差异,如内存的分配、虚拟内存的处理、数据的读写交换、兼容稳定抗压性等等方面,利用相应的调优方法和工具,可以对此环节进行优化。

  二、硬件层面

  a)CPU:中央处理器,决定数据处理速度的核心部件,与性能表现的相关度可想而知,硬件方面具体调优方法及工具本文中不再赘述,下同!

  b)内存、缓存:数据交换的临时存储空间,它的大小形象的说就像是火车站候车室的面积,与性能的关系可想而知。比如有些程序设计的操作对内存回收设计有漏洞,导致频繁操作时内存泄漏越来越多,系统就会越来越慢。

  c)硬盘、I/O:数据存储、调用的载体,如果存储器像候车室,那这些就像是车箱的大小与节数等。

  d)网络:如果还是用坐火车为例,网络的差别就像是普通、快速、动车、磁浮等各种等级的差别,如果一个“系统”频繁需要通过火运完成,那它的性能表现和网络的相关性就不言而喻了。比如某些软件功能设计时没有考虑网络流量方面的风险,导致每次操作时网络连接次数很多,频繁调用或是数据包过大,这些都会导致在一定网络条件下产生性能问题。

  e)显卡等特殊硬件:不同软件产品应用的业务可能用到不同的专用硬件或外设,比如一个很炫的游戏对显卡的要求就会很高,当显示成为短板时死机、跳帧等异常;一个收款台的扫描、信用卡POS机如果质量或兼容性、稳定性不佳时,也可能会造成性能表现的不理想,等待诸如此类问题。

  三、业务层面

  a)业务流程重组:项目甲方在购买软件产品或系统服务前,一般会找相关专家、售前人员作一些相关的评估或“体检”,找出现有运作模式下的一些存在优化空间的错误环节或繁冗流程、制度体系等。因此在这个阶段是否对项目应用方作了足够的优化,也对未来产品上线后的应用性能表现在宏观上起着决定作用。取例来说:如果一个系统设计前没有作过这方面的优化,最后应用时需要100人操作10个步骤才能完成,通过流程重组后,从业务上只需要40个人干5个步骤就搞定了,那么没上软件前我们就能从理论上把性能表现优化80%!

  b)需求定位:与上一条阐述的类似,只是介入的阶段和角色有所区别。需求人员有时是从项目乙方发起的,主动地、有策略性的去选择一些有代表性的单位去调研软件产品的概要或详细需求,为后续的产品开发设计提供依据。在这一阶段是否有效的考虑了未来产品的性能表现,对其提出相关的设计目标,也对后续的性能表现有一定的影响。

  c)实施方案:一般当大型一些的项目合同签订完毕后,就会分期安排实施人员负现场牵头并组织双方成立实施小组团队,共同制订系统的上线、操作培训、应用方案等,并执行方案直至系统正常上线运行,项目交付。因此,这个方案制定的是否精简、高效,也直接关系了用户应用系统的性能表现。


 四、意识层面

  当今社会万事讲求以人为本,如果从软件应用系统涉及的各级人员角色的内心没有把性能表现当回事,那么一切调优最多也都是亡羊补牢而已。比如:

  a)产品经理:项目乙方产品总负责人,产品目标、市场定位、基本框架的制定者。

  b)一线人员:售前咨询、实施顾问等。

  c)需求设计:对产品具体功能设计提出明确要求的角色。

  d)代码实现:按需求定义进行产品的具体实现的角色。

  e)测试人员:对产品质量进行检测、对开发过程进行监管的角色。

  f)最终用户:系统最终的使用者、应用效果的影响者。

  对于一个软件产品来讲,只有以上这些环节的角色人等在各自的工作岗位上,真正的在意识层面上提高优化系统性能的地位,而不是把它作为功能优先实现之外的附属品,才能把系统性能优化的工作最大程度的作在前面、作的全面、作得到位!

  综上所述,我们看到了各类导致性能瓶颈的可能原因(也可以说是性能调优的入手点),下面我们用一个比较常用的鱼骨图分析法来展示一下,可能会更为清晰:

  然后我们再把这些原因按一定的规则进行分门别类,一般采用如下的二维矩阵分析的方法,按可推行的难易度和收效的影响度高低来形成四个象限,把这些问题按具体情况分布在这四个象限中,看到这些问题中哪些是我们要优先解决的,哪些是可以暂时放一放的,调优时可以借鉴这个顺序来进行。

  当然在不同的企业这四个象限中的原因分布是会相互转化的,比如在一个预算有限的私企中可能额外的硬件投资对其来说就是应该放入暂时搁置的象限,而对于财大气粗的单位中可能费用预算不是问题但是想改变他的办事流程和组织架构将是非常困难的,这时解决的优先次序也就要相应调整了。

posted @ 2011-11-25 18:07 顺其自然EVO 阅读(171) | 评论 (0)编辑 收藏

软件测试讲义(上)

     摘要: 在一个软件团队里,不同的人有不同的投入,不同的人还要在团队中担负不同的任务,我们也要讲一下。  团队中的 PM 负责分析市场,设想功能,定义用户到底要什么 – Why & What.  团队中的 Dev 负责实现功能,搞清楚怎么才能满足用户的需求 – How.  团队中的测试人员搞清楚我们的软件是否满足了用户的需求 – Whether.  最后所有成员一...  阅读全文

posted @ 2011-11-25 18:06 顺其自然EVO 阅读(404) | 评论 (0)编辑 收藏

打造高效的技术团队,我会关注的7个点

1、使用分布式的版本管理系统

  如果你觉得不需要使用版本管理系统,那我们沟通会有代沟,如果你是cvs、svn的粉丝,或者由于某种原因没有使用过分布式版本管理系统,比如git,那强烈建议你去看一下“why git is better than x”。

  2、一键式发布

  这里发布的目标位置,既可以是开发机,做本地测试;也可以是测试机,为QA准备好捉虫游戏的森林;还可以是生产环境(或者beta环境),供用户直接访问。

  如深度xp一键恢复系统一样,一键式发布需要自动完成很多工作:代码自动化测试(开发阶段),打包压缩,编译(测试阶段),数据同步(外网)。也许还有很多工作要加入进来,但核心是是否能通过一个脚本的执行就全部完成所有流程,这点至关重要。如果中间多出几个环境,那将来一定会引入发布的灾难。

  3、TDD / BDD 请对你自己写的代码负责

  不要为了TDD/BDD而TDD/BDD,只要能及时获得自己写的代码运行情况的反馈就行,也无需一次把test case都覆盖全。对于没有任何单元测试的代码,将来想引入单位测试,将举步维艰!如果,你认为测试完全是QA的事情,那你就花大笔的钱去招聘一个规模庞大的QA集团吧,期望他们能让你偷懒。

  4、使用靠谱的bug记录工具

  人脑的潜力虽然无限,但大脑皮层只会对进入缓存区的数据做高效的反应。记忆再好的开发,也可能被各种牛魔鬼怪折磨的忘记了昨日的痛(曾经产生的bug)。所以,从团队第一次提测,就应该使用靠谱的bug记录工作。所谓好记性不如烂笔头就是这个道理。

  那一个靠谱的bug记录工具应该要记录这些数据:

  ● bug复现的整个操作流程
  ● 产品需求中的正常情况
  ● 出现bug后,变成为什么情况
  ● 谁将负责修复这个bug
  ● bug最后修复没有

  至于怎么修复的bug,是重新设计还是漏提交了代码,我觉得无关紧要。如果一个bug修复的经验值得分享,可以单独做一次团队的技术分享,而这往往是由于对现有产品的(技术或者其他的)信息获取不够导致的。

  5、尽快修复bug

  我的开发经验告诉我,一个bug越晚修复,被修复的可能性越小,将来产生危害的可能性越大。试想,你刚提测或者发布的代码,出现的bug,往往你能最快得到解决它需求的时间,而时间在项目管理上是非常重要的。反之,如果积累了很多bug,且有一定时间了,那修复它就需要对所有相关的系统进行了解,这将花费大量你可以用来度假,娱乐的美好时光。所以,从团队一开始就贯彻这点,可以释放成员修复bug的压力。

  6、给团队成员一个安静的环境

  最近很多同学告诉我,白天基本上没有什么效率,总是受到各种骚扰。我们做一个假设:假如A同学进入最佳状态需要30分钟,那么如果他比较惨,在30分钟间隔内,他总是被打断,那么他一天都无法最高效的工作。又或者同学B google查询一个技术问,花费2分钟可以解决,但问同学A只要20秒钟(好吧,同学A表达很清晰)。这样同学B节省了100秒钟,而同学A至少损失了30分钟。

  从这个假设,我们不难发现,如果能避免团队成员受到外来信息的骚扰,他就有可能更加高效的工作,从而写出更好的产品。而常识告诉我们,人不可能一直高效的工作,所以,我们应该利用好无法集中精力的时间去进行一些沟通。但分出这个界限显然十分困难,所以我觉得不妨这样:规定每天的安静时间段,在这个时间段,其他人都不能来打扰这位同学,而在非安静时间段,可以随意访问,从而让这位同学形成一个新的生物钟(人体的自我调节能力是非常强悍的)。

  7、给员工最好的工具

  做同样一件事情,如果使用工具A,消耗的时间为5分钟,而使用工具B,消耗的时间为1分钟,那我一定给员工提供B工具,即使B工具的价格是A工具的5倍。因为,假如人在连续高效工作中的抵抗干扰时间为1分钟,那么意味着B工具能保证高效工作的时间连续,而A将可能分散了用户精力,导致需要更多的时间才进入最佳状态。事实上,之所以要更好的cpu,更大的内存,更好的编译器,更好的编辑器,多显示器,都是让程序员尽快能回到核心业务上来,而在等待上花费更少的时间。

  同时,别忘了,一把好的椅子也是维持更长高效工作时间的保证,所以,别吝啬,给员工更好的椅子吧,他们会感到你的温怀。

posted @ 2011-11-25 18:06 顺其自然EVO 阅读(167) | 评论 (0)编辑 收藏

如何应对没有需求的测试

软件测试时候发现根本没有需求,一问开发和需求,发现原来是我们的项目经理口口相传,告诉开发要怎么怎么做。

  可想而之,这个过程是没有设计的,开发过程当中遇到问题,就会问,项目经理即时马上给出答复。

  而到了测试,测试人员在完全不了解状况的时候,在界面上点了点,也不知道要点多少东西,反正一会告诉我说版本测试完了。我心里没底,想着版本上提到改了这么多东西,怎么马上就测试完了呢?

  于是我抱着怀疑的态度去做测试,结果一看发现我们的系统已经大变样了。以前一个流程的三种状态变成了现在的未知种数。我傻眼了,这样怎么可能做测试呢?没有需求,无法预估到测试场景。怎样才是测试完成了?更可恨地是部门经理说测试完了没问题就上线,我的问题是怎样是测试完了,怎样是没问题呢?

  我告诉部门经理,我无法决定是否上线,因为我不知道如何设计测试场景了,而通过我的测试,我发现了一些开发人员也无法回答的问题,于是我把所有我知道范围之内的可能造成状态不同的条件全部列出来了,要求项目经理可我填写,如果是这样的输入条件,输出是怎样的?经我这么发问,项目经理也无法填写我的结果,又推给需求去确认。当然事情暂时没有结论,现在的状态是版本暂时没有上线,我的测试我认为是没有做完的。

  针对以上的问题,我觉得好险。测试是项目最后的一道关,如果我不能发现这些问题,上线后,客户发现了,我们如何解释呢,我们的项目经理会挺身而出帮你说话,说是因为没有需求吗?

  如果出了问题,我对项目经理没有这样的信心。但是我越发觉得测试是多么的重要了,每次上线都是对我个人能力的考验。而这种混乱状态下,如果我不能够发问,我这个测试组的地位只会越来越低,成为别人推卸责任的那个背着黑锅的家伙。

  这次我也发现自己在进入这个部门两个月以后的第一次反抗,前期由于不了解项目的情况,所以出这种问题也是无法察觉的。需求和开发没有文档,需求分析和设计没有做好,我的测试也只能定位比较低。但是通过这次的考验,我自己越来越多的相信,我能够做好项目的测试管理,我的测试组能够在项目过程中充当着不可或缺的角色。

  没有需求的测试,很危险,但是我绝不是每次都要用这种方法来对付这个问题,我要告诉部门,你们前期的需求分析是否可以做得更全面一点,开发设计可以多考虑一些,不要每次把问题丢给测试,提高项目的间接成本。

posted @ 2011-11-25 18:06 顺其自然EVO 阅读(193) | 评论 (0)编辑 收藏

深入分析SQL字符串限制长度漏洞

 MySQL字符串的限制长度看似重要性不要,其实和整个MySQL数据库的安全性是息息相关的,很值得我们去深入研究分析。

  SQL注入攻击一直都在被广泛的讨论,然而人们却忽略了今天我将要介绍的这两个安全隐患,那就是超长SQL查询和单列SQL字符长度限制可能会带来的问题。

  首先我们来谈论一下超长SQL查询

  max_packet_size

  这个东西是用来限制mysql客户端和服务器通信数据包的长度的,比如一个查询为“select * from user where 1”,那么这个长度仅仅几十个字节,所以不会超标。在绝大多情况下,我们很难会超过mysql的默认限制1M(可以想象一下,1M的SQL语句还是很长的)。这里插一句,看到这篇文章之后,我终于清楚我当初用PEAR DB 的INSERT插入数据失败的原因了,很可能就是数据长度超标。对于MySQL来说,如果查询MySQL字符串的大小超过了这个限制,mysql将不会执行任何查询操作

  如果访问者有可能控制你的sql长度,那么你的程序可能会受到攻击。哪些情况访问者可能控制sql的长度呢,比如不限制关键字长度的搜索。还有可能就是你的程序如果要将用户的登录作为日志启用,总之凡是涉及到超长sql查询的地方,一定得小心检查自己的sql,防止超长而查询失效。不过说实在的,本人认为这个问题倒不是多大,数据库管理员也可以自行设置MySQL的max_packet_size的长度,或者在处理可能超长的SQL查询的时候做一个长度判断。

  MySQL列长度限制

  这个是本文的重点。MySQL对于插入的字符串,如果长度超过了数据表限制的长度,MySQL将会截取前面部分MySQL字符串插入数据库中,而不会将错误报给web程序。对于粗心的程序员,这个问题可能会导致程序的漏洞,其实目前的wordpress有很多限制,通过这个漏洞攻击应该没有任何作用。下面是原作者的几个假设,如果同时满足这几个条件,获取一个站点的用户名是相当容易的事情,幸运的是目前的wordpress并不太可能会同时满足下面的条件:

  该web应用允许用户注册(开放注册的wordpress满足此条件);

  超级管理员的用户名已知的,比如admin,这样方便攻击者寻找目标(可怜wordpress也满足)

  MySQL使用的是默认的配置(估计大多数都满足)

  注册新用户的时候,程序没有对用户名的长度给予限制(我测试过,wordpress也满足)

  用户名被限制在16个字符(这个和上面的没有关系,仅仅是方便举例)

  下面我们来看看攻击者是怎么攻击的:

  首先攻击者用已知的超级管理员id如admin注册,那么这个时候程序就会用

以下是代码片段:
    (show/hide)plain text
  SELECT * FROM user WHERE username='admin '

  来检查该ID是否已经存在,如果存在,这不允许注册,当然,攻击者尝试注册admin肯定会失败;

  但是如果攻击者用 admin X(admin和x之间有11个或以上的空格)来注册呢,按照上面的判断,由于admin x不存在数据库中,所以当然就能注册成功了,事实上wordpress2.6.1之前的版本确实可以这样,由于列长度的限制在16个字符内,所以末尾的x就被截掉了,那么现在数据库中就存在两个一模一样的用户admin了。(旁白:糟糕,那我的程序不是都要去修改。其实没有必要,你只要把ID设置为UNIQUE就可以了,于是乎,下面的问题就和你没有关系了)

  攻击者继续,这个时候攻击者就顺利的注册了admin这个用户名,然后攻击者用admin和自己的密码登录进入账户管理(wordpress即使注册了也无法登陆),由于真正的admin的帐号先于攻击者admin注册,所以在账户信息页面,显示的信息非常有可能就是真正admin的信息,包括密码提示和email等,这个时候攻击者就可以对admin的信息进行任意修改,包括密码和密码找回。

  所以,写web程序的你,是不是该去检查一下自己的程序是否有此类的漏洞呢。

posted @ 2011-11-25 17:43 顺其自然EVO 阅读(637) | 评论 (0)编辑 收藏

OpenStack详细解读:定义,好处与使用实例

     摘要: OpenStack是一个旨在为公共及私有云的建设与管理提供软件的开源项目。它的社区拥有超过130家企业及1350位开发者,这些机构与个人都将OpenStack作为基础设施即服务(简称IaaS)资源的通用前端。OpenStack项目的首要任务是简化云的部署过程并为其带来良好的可扩展性。本文希望通过提供必要的指导信息,帮助大家利用OpenStack前端来设置及管理自己的公共云或私有云。  内容详解  ...  阅读全文

posted @ 2011-11-25 17:40 顺其自然EVO 阅读(1399) | 评论 (0)编辑 收藏

Equinox加载Bundle Class的实现

 Equinox在创建Bundle的ClassLoader时,首先获取bundle的classpath,然后执行createBCLPrevileged方法,此方法最后转交由BaseData来创建ClassLoader。

  BaseDate创建ClassLoader的关键代码片段为:

  • ClassLoadingHook[] hooks = adaptor.getHookRegistry().getClassLoadingHooks(); 
  •     ClassLoader parent = adaptor.getBundleClassLoaderParent(); 
  •     BaseClassLoader cl = null
  •     for (int i = 0; i < hooks.length && cl == null; i++) 
  •        cl = hooks[i].createClassLoader(parent, delegate, domain, this, bundleclasspath); 
  •     if (cl == null
  •        cl = new DefaultClassLoader(parent, delegate, domain, this, bundleclasspath); 
  •     return cl;
  •   在Equinox中,默认的情况下adaptor.getBundleClassLoaderParent返回的为bootstrap classloader,可通过修改启动的osgi.parentClassLoader 来改变这个parent classloader,

      osgi.parentClassLoader 的可选值有四个,分别是:

      ● boot:默认

      ● app:SystemClassLoader

      ● ext:SystemClassLoader的parent

      ● fwk:启动Equinox的ClassLoader

      ClassLoadingHook在createClassLoader的时候都没有做动作,因此最后ClassLoader都是通过创建DefaultClassLoader对象来构建的,其中parent参数为null,delegate参数为BundleLoader实例,bundleclasspath参数为bundle的classpath。

      经过以上步骤后,完成了ClassLoader的创建,可以开始加载class了,根据上面上述,Bundle的Class就由DefaultClassLoader来完成了。

      查看DefaultClassLoader的loadClass代码,发现真正的加载class的过程是转为调用了delegate 的findClass来完成的,delegate参数对应的为BundleLoader实例,转为跟踪BundleLoader的findClass方法。

      BundleLoader的findClass方法的代码片段:

  • if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE)) 
  •    return parentCL.loadClass(name);
  •   从以上这个代码片段,可以看到,Equinox将java.开头的类转交给了parent classloader去加载,这也意味着没必要在系统中提供对外export java.开头的package。

      如果不是java.开头的类,则交由findClassInternal方法来完成加载。

      findClassInternal方法遵循的为OSGi规范中定义的Class的加载顺序,不过仍然稍有改动:

      1)判断是否交由parent classloader去完成加载

      在启动Equinox时,Equinox会读取org.osgi.framework.bootdelegation属性,该属性对应配置的为需要从parent classloader中加载的package,如值配置的为*,说明所有的都从parent classloader中加载 ,如值配置的为具体的package,那么则放入bootDelegation集合;如配置的为带通配符的package,那么则放入bootDelegationStems集合。

      判断时Equinox首先判断是否所有的都从parent classloader中加载,如是则从parent classloader中加载;

      如需要加载的类的package位于bootDelegation或bootDelegationStems集合中,那么同样从parent classloader中加载。

      如不从parent classloader中加载,则进入下面的步骤。

     2)尝试调用Equinox提供的ClassLoaderDelegateHook的扩展来加载

      Equinox对外提供了ClassLoaderDelegateHook的接口扩展,可编写ClassLoaderDelegateHook的实现,注册到Framework中,那么当有Class需要加载等动作时都会得到通知。

      在默认情况下,Equinox中没有ClassLoaderDelegateHook的实现,因此继续下面的步骤。

      3)判断是否在import-package中,如在则交由相应的PackageSource去加载

      根据Bundle配置的import-package,判断目前需要加载的类是否在import-package中,如在则交由对应的PackageSource进行加载,PackageSource在加载时即直接交由对应的Bundle的classloader去加载,如加载的类的package在import-package中,但加载后仍然没有找到Class,则直接抛出ClassNotFoundException,如加载到,则直接返回。

      如所需要加载的类的package不在import-package中,则继续下面的步骤。

      4)尝试从require-bundle中加载

      尝试使用require-bundle来加载,如加载到,则直接返回,如加载不到,则继续下面的步骤。

      5)尝试从当前Bundle中加载

      直到经过以上步骤的尝试,才尝试由当前Bundle中加载,当前Bundle加载的方法即从Bundle-Classpath或当前Bundle的Fragment中查找相应名称的class文件,并读取该文件进行加载,如class文件已加载,则进行缓存,再次加载时则不需要查找和解析class文件。

      如从当前Bundle中仍然未找到所需的类,则继续下面的步骤。

      6)尝试从DynamicImport-Package中加载

      判断需要找的类的package是否在DynamicImport-Package中,如果在,则交由相应的PackageSource进行加载,如PackageSource中加载不到,则抛出ClassNotFoundException;如不在DynamicImport-Package中,则继续下面的步骤。

      7)再次尝试调用Equinox提供的ClassLoaderDelegateHook的扩展来加载

      这步和第2)步相同,因此在默认情况下继续下面的步骤。

      8)尝试使用eclipse的buddy机制来加载

      Buddy机制是Eclipse的扩展,并不符合OSGi规范,因此在此不做深入分析。

      9)判断一定的条件,如符合则从parent classloader中加载

      判断的条件为:parent classloader不为null、不从parent classloader中加载、Equinox的向后兼容属性(osgi.compatibility.bootdelegation)为true以及jvm的bug class,如满足以上条件,则尝试从parent classloader中加载。

      如经过以上所有步骤后,仍然未找到需要加载的class,则抛出ClassNotFoundException。

      从上面的代码分析中,在Equinox中可以通过osgi.parentClassLoader、org.osgi.framework.bootdelegation来控制从Bundle ClassLoader外来加载Class,这对于集成Equinox其他容器而言,非常有用,另外,还可以通过实现ClassLoaderDelegateHook来改变Class的加载。

    posted @ 2011-11-25 17:21 顺其自然EVO 阅读(204) | 评论 (0)编辑 收藏

    Tomcat部署多个应用站点的方法

    Tomcat部署多个应用站点的方法

    分类: 服务器相关类2010-11-02 11:30 360人阅读 评论(0) 收藏 举报

    前些天用Tomcat的时候遇到一个问题,那就是如何在一个服务下部署两个应用,通俗说就是一个web server,下面有两个网站,对应不同的二级域名,两者指向的是同一IP地址。如何做才能分别访问而不受干扰呢?为此,g了一下,找到了相关解决办法。祥见Tomcat建立多个应用(Web Server),多个主机,多个站点的方法,粗略了研究了一下,恍然大悟。原来只消把Tomcat下的server.xml修改一下即可,现把我的配置贴出来,仅供参考。

        <service name="Catalina">
      <connector port="8080" protocol="HTTP/1.1" maxHttpHeaderSize="8192" maxThreads="800" minSpareThreads="10" maxSpareThreads="100" enableLookups="false" redirectPort="8443" acceptCount="200" connectionTimeout="20000" disableUploadTimeout="true">
      </connector>
      <connector port="8009" protocol="AJP/1.3" redirectPort="8443"></connector>  
      <engine name="Catalina" defaultHost="localhost">
       <realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase">
       </realm>
       <host name="qss.pmlove.com.cn" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
        <alias>qss.pmlove.com.cn</alias>
        <context path="" docBase="D:/apache-tomcat-6.0.18/webapps/qss" debug="0" reloadable="true"></context>
       </host>
       <host name="vp.pmlove.com.cn" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
                 <alias>vp.pmlove.com.cn</alias>
                 <context path="" docBase="D:/apache-tomcat-6.0.18/webapps/vp" debug="0" reloadable="true"></context>
                </host>
      </engine>
     </service>
    以上代码是server.xml的一部分,只要对应拷贝即可实现,本人已测试成功。

    posted @ 2011-11-25 17:15 顺其自然EVO 阅读(22851) | 评论 (0)编辑 收藏

    页面性能测试

      一、页面性能测试概述

      页面性能测试则是针对于页面性能优化而开展的一种性能测试,目的是对Web系统的页面进行测试以确认系统页面是否会影响系统的性能并为页面的优化提供依据与建议,最终提升系统的整体性能表现,提高用户体验满意度。可见,Web系统页面性能测试是相对Web系统后台测试的另外一种性能测试,是Web系统性能测试的一个重要部分。

      二、页面性能测试必要性

      相对于C/S架构的应用系统,Web应用系统所有数据都需要从服务器端下载,虽然浏览器有缓存机制,但客户每次访问仍然需要下载大量的数据。特别是用户对系统要求越来越高,除了要求功能完备,对界面的美观、易用性也提出了更高的要求,越炫的页面也就意味着页面中要包含更多的脚本、样式表、图片和Flash,页面的数据量也就越大,这对Web系统的性能提出了极大的挑战。

      曾经有个在线打印服务的应用提供商说他们的系统不需要关注系统性能问题,没有必要进行性能测试,因为他们可以购买足够多的服务器来支撑系统;不少业界同行也认为只要有足够多的服务器资源,性能就不会存在问题。其实不然,他们都只关注到了应用系统的后台性能表现,而忽略了页面对系统整体性能的影响。举个例子,当一个页面中包含几百个请求,页面中没有经过优化的javaScript文件、CSS 文件与图片件大小达到10MB,即使当前只有一个用户在访问该系统,页面的访问速度也会慢得惊人,纵使增加再多的服务器也不见得会有明显的性能提升。

      可见,对Web应用系统的页面进行性能测试和优化是非常有必要的。只有通过对页面的性能测试,发现页面存在的性能问题并根据性能测试结果进行页面优化以提升页面的加载性能,从而提升系统的整体性能。在应用系统高并发访问时,更能体现出Web页面优化后所带来的系统整体性能提升效果。

      2种方式来提升你的web 应用程序的速度:

      ● 减少请求和响应的往返次数

      ● 减少请求和响应的往返字节大小。

      减少请求和响应的往返次数:

      HTTP缓存是最好的减少客户端服务器端往返次数的办法。缓存提供了提供一种机制来保证客户端或者代理能够存储一些东西,而这些东西将会在稍后的HTTP 响应中用到的。(即第一次请求了,到了客户端,缓存起来,下次如果页面还要这个JS文件或者CSS文件啥的,就不要到服务器端去取下来了,但是还是要去服务器上去访问一次,因为请求要对比ETAG值,关于这个值,我将会在下次翻译中介绍其作用)这样,就不用让文件再次跨越整个网络了。

      缓存相关的请求头

      为了提高性能,微软的IE和其他的web客户端总是想尽办法来维持从远程服务器上下载下来的本地的缓存。

      当客户端需要一个资源(html,css.js…),他们有3种可能的动作:

      1、发送一个一般的HTTP请求到远程服务器端,请求这个资源。

      2、发送一个有条件的HTTP请求到服务器,条件就是如果它不同于本地的缓存版本。

      3、如果缓存的拷贝可用,就使用本地的缓存资源。

      当发送一个请求,客户也许会使用如下的几个HEADER

      减少请求肯响应往返的字节大小:

      1、使用更少的图画

      2、将所有的CSS浓缩到一个CSS文件中

      3、将所有的脚本浓缩到一个JS文件中

      4、简化你的页时间

      5、使用HTTP压缩

      三、页面性能测试工具介绍

      第一种是通过HTTP代理的方式来截取客户与服务器之间的通讯。

      此类的工具非常的多,如:

      charles是一个HTTP代理/ HTTP监视器/使开发人员可以查看所有的计算机和互联网之间的HTTP和SSL/ HTTPS流量的反向代理。这包括请求,响应和HTTP标头(其中包含的cookies和缓存信息)。

      charles界面清爽,采用中国的瓷器为logo,给人的感觉简洁高雅。而且使用也非常简单。进入下载页面,选择你适合你的版本,安装也非常简单,一路“next”就OK了。

      点击工具栏上的“红色”按钮,就自动的记录你浏览器访问的所有网站。

      Fiddler是一个Web调试代理,记录所有的HTTP(S)之间的计算机和互联网的交通。提琴手允许您检查交通,设置断点,和“捣鼓”传入或传出数据。菲德勒包括一个强大的基于事件的脚本子系统,并可以使用任何。NET语言扩展。

      Fiddler是免费软件,可以调试,从几乎任何应用程序,支持代理,包括IE浏览器,谷歌Chrome,苹果Safari,Mozilla Firefox中,歌剧,还有数千交通。您也可以像Windows电话,iPod/ iPad和其他流行的设备调试的交通。

      Fiddler2相比Charles功能要更强大一些。当然了,如果单单把他们理解成页面性能测试工具有此片面,尤其Fiddlers2功能强大,当然了,我也没有深究,在此就不过多评论了。


    posted @ 2011-11-24 18:08 顺其自然EVO 阅读(342) | 评论 (0)编辑 收藏

    软件测试管理的一点经验

      测试工作头绪较多,专业性强,如何做好测试管理工作,特别是量化管理,提高测试效率、督促测试人员完成好测试工作,是很重要的。

      我负责三位XXX测试人员对XXX进行测试。测试规程主要是按协议的各个要求编写的,测试规程的通过准则是测试人员根据对协议的理解、对系统的理解编写的。三位测试人员根据测试规程进行分工,分别编写、测试不同的规程。测试的平台是测试部自已开发的专用XXX测试环境。

      前一段时间,对XXX测试如何进行管理没有一个头绪,使得XXX测试计划一再推迟,并且对实际的进展、测试的质量都不太清楚。为了加强对XXX测试的管理,并争取做到量化,进行一些尝试,并取得一定的成功。现在每天可以看到实际的测试进展,并能发现每位测试人员的进度、质量,也可以看到XXX测试结果的情况。

      以下是我近期对测试管理的经验。

      做好每日汇报工作

      每日汇报工作可以与项目、部门的一些具体要求结合起来。比如,项目要求每天的测试应当有一份测试日报。测试部要求测试规程、测试结果要入到测试中心。还要求故障及时提交,并导入CQ。

      除此之外,为了做好统计工作,我在CC上建立了一个execl的汇总文件,输入了所有的测试规程、通过准则。每天,测试人员有新增加的测试规程、通过准则,要加到该文件中;每天的测试结果,要填到该文件中。要填的内容,如果是测试规程、通过准则,是与测试中心的是一致的。测试结果只是一个通过或不通过,加上一个当天日期。这是一个非常简单的填表,并不会增加太多的工作量。

      采用CC,可以保证汇总文件的一致性,还可以检查测试人员填写的情况,可以提取不同版本的汇总文件。这充分利用了CC的优点。

      以下是汇总文件中的一部分:

    posted @ 2011-11-24 17:43 顺其自然EVO 阅读(160) | 评论 (0)编辑 收藏

    仅列出标题
    共394页: First 上一页 357 358 359 360 361 362 363 364 365 下一页 Last 
    <2024年11月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    导航

    统计

    常用链接

    留言簿(55)

    随笔分类

    随笔档案

    文章分类

    文章档案

    搜索

    最新评论

    阅读排行榜

    评论排行榜