qileilove

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

LoadRunner对不同协议的选择

 大家常用的是Loadrunner测试web(Http/Html),但其实协议多种多样。在B/S结构的网站多种业务的特点需要选择不同的协议,协议如何选择呢,寻找了相关资料。
  LoadRunner首先是一个测试工具,其次是一个性能测试工具,然后是该工具是一个基于协议,也就是说LoadRunner测试的对象都需要使用通信协议,对于那些不使用通信协议仅仅进行本地处理的软件例如Microsoft Word,LoadRunner就不适用。说到通信协议我们来熟悉一下协议的分层,按照OSI的分层模型,分层结构如下:
  按照TCP/IP协议的分层,分层结构如下:
  第一个分层是由OSI制定但不实用,后一个是目前广泛使用且被业界认做既定标准的协议分层,下文探讨的LoadRunner协议选择即按TCP/IP协议的分层模型讨论。
  接着来说说LoadRunnerVuGen中的协议分类,VuGen(LR8.1)中的协议分类如下表所示:
  LoadRunner VuGen中的协议与文章开头所说的通信协议还是有一定的区别的,例如像LoadRunner VuGen中的C 模板、Visual Basic 模板、Java 模板、Javascript. 和 VBScript. 类型的脚本均为开发语言,非通信协议。
  一般来说协议选择有如下原则:
  B/S结构,选择WEB(Http/Html)协议;
  C/S结构,可以根据后端数据库的类型来选择,如SybaseCTLib协议用于测试后台的数据库为Sybase的应用;MSSQLServer协议用与测试后台数据库为SQL Server的应用;
  对于有些使用纯JAVA编写的C/S结构的东东,采用JAVA,而且不能录制只能手工编写代码(工作量和难度还是有的)。同样不能录制的还包括C、VB Script、VB、VBNet User协议。
  对于一些没有数据库的Windows应用,可选用Windows Sockets底层协议;使用了数据库但使用的是ODBC连接的数据则选择ODBC协议;对于Windows Sockets协议来说,最适合的那些基于Socket开发的应用程序;但是由于网络通讯的底层都是基于Socket的,因此几乎所有的应用程序都能够通过Socket来录制,哪可能有人会问,哪既然Socket都能录制下来,还要那么多协议做什么,价格还贼贵,其实最主要的原因就是Socket录制的代码可读性较差,如果Socket的脚本可读性较高的话,实话就没有其他协议出现的必要性了。
  对于邮件来说,首先要看你收邮件的途径,如果你通过WEB页面收发邮件,毫无疑问,你选择协议时就需要选择HTTP协议,如果你通过邮件客户端,像OutLook、FoxMail之类的,则需要根据操作不同选择不同的协议了,例如发邮件你可能要选择SMTP、收邮件你可能需要选择POP3。

posted @ 2014-04-08 10:46 顺其自然EVO 阅读(199) | 评论 (0)编辑 收藏

测试金字塔新解之移动无线应用测试

 在看过吴穹对2014年测试的展望之后真的对于移动无线测试的未来大有信心。在文章中再次看到了熟悉的“测试金字塔”,该金字塔是分层测试思想的重要钥匙。我自己是移动互联网出身的测试,所以突发奇想从移动无线应用的测试角度重新来审视了下该金字塔并做了扩展,希望对于大家有一定的帮助。
  首先我们先来看下经典金字塔,如下图所示:
  这对于传统互联网的测试而言非常清晰的一个层次结构,但我相信对于很多移动互联网的同学们而言也许就多少有些迷茫,这不单单是因为技术上的实现不同于以前,也有些是名词定义问题。经过我思考之后,发现发现移动互联网的应用测试角度出发可以从该图上拆分出很多的东西,并且图还有些小小的变化,如下图所示:
  单从这个图上来看的话的确是比较迷惑的,那么我们接下来就一层一层来剥,以下内容很黄很暴力,大家做好准备了吗?
  我们先来说第一层:UI层。UI层顾名思义就是用户看到产品时候所长的样子,从技术实现角度而言,那就是产品的一层皮。那么UI层在移动无线应用的测试中分成哪些主要的部分呢?
  1.用户体验
  2.控件显示
  3.功能交互
  4.代码接口
  5.用户体验
  移动互联网应用是一款产品,相对其他类型的产品而言,其用户体验已经到达了举足轻重的地步,在我的新书《大话测试——移动互联网应用测试指南》中有单独阐述用户体验的一个章节,有兴趣的朋友可以等出版之后仔细阅读。
  现在各个公司也出现了大量的和用户体验相关的岗位,比如“产品体验师”、“产品设计师”、“交互设计师”等,也越来越说明着用户体验对于移动无线应用的重要性。
  很多人觉得用户体验好就是一定要画面优美,交互酷炫,界面上没有出现明显的瑕疵就可以了,虽然没有错,但这些仅仅是用户体验的表面一层。我们来看下以下的几个例子。还是那句老话,也许你觉得他们的成功或失败与用户体验关系不大,但其实从移动无线应用能够成功的情况来看,用户量、用户黏性才是最主要的,这些归根结底还是用户体验。在我的书中着实已经吐槽了非常多的应用了,在这里就再吐两个大家都认识的、知名度很高的应用。我们使用无线应用的时候难免碰见网络不好的情况,这也是现在大量测试工程师正头疼的事情(幸好fiddler和Charles能够为我们解决这个问题),但我相信如果我们在网络不太好,却看到以下界面显示的时候,肯定恨不得想摔手机
  也许我不说,大家也能够猜得出来是哪家的应用了吧。我几乎每次在餐馆想要使用一些优惠券的时候就会看到这个界面,恨之入骨。难道网络慢弹出个提示就那么难吗?难道为用户考虑一下就那么难吗?你能够告诉我“createorderxxx”这串外星文用户真的认识是什么吗?所谓用户体验好,就是要让用户觉得应用在说“人话”,而不是“火星语”。你采取如下方法都比现在的做法好:
  可以选择在用户点击的时候就向服务器做请求,此时并不跳转界面,短时间超时之后给出一个“网络差”的提示
  可以选择进入这个界面,但不要给用户看到“火星文”,短期超时之后再给出一个“网络差”的提示,并自动返回上一页
  说着说着我的火气就上来了,不过还有更可气的了。我们来看下面这个应用的行为。
  硕大的logo,这个是什么场景呢?现在支付宝和“喜士多”、“7-11”等多家便利店合作了,不但方便了大家的购物,同时也减少了零钱和假币的流通,的确是个大好事。便利店网络不好的情况也尤其多,当我选择好了很多商品,最后拿出支付宝,看到这个鸟样,我心里真的千万只草泥马奔过。但此时想想没有关系阿,我作为iOS高大上的用户可以杀进程,于是我熟练的杀掉支付宝的进程再次打开,事实证明我无法改变这个鸟样。我真的很焦虑,我知道支付宝要联网,但它不是一个网游吧,为什么没有网你就不能让我打开呢?我真的觉得让我看到一个进入的界面或者设置一个短时间就超时都比我看着一坨黑色上面有个“菊花”强数百倍吧,于是,我的手机真的被我摔坏了。
  控件显示 现在往往很多测试说测UI了就是拿过来看看界面显示对不对,所谓UI Automation也就是模拟用户的操作,但是真的仅仅只是如此吗?Android的应用界面一切都是以View来构成:
  请问有多少工程师关心过这些所谓的界面上的控件显示的到底对不对呢?像素值和比例与需求一致吗?我们一般可以通过三步来解决这个的问题。
  A. 先验证每个界面显示之后控件是否存在
  B. 再验证这些控件具体的位置、大是否正确
  C. 最后验证整体显示是否正确
  其中B可以使用如下所示的这个类来验证:
  而C的话我更偏向于自己去写,而不是用MonkeyRunner自带的图片对比方法,其精准度不高,很难判断图片是否真的有细小的差异性,我自己更偏爱用PIL库。iOS的话Xcode也自带了Inspector可做相关验证。
  功能交互
  手动测试,自动化的话可用框架太多。Robotium,Instrumentation,Appium,这里不多做解释。
  代码接口
  某些应用往往逻辑很复杂,但界面却很简单明了。其复杂程度体现在它的逻辑和数据场景。这类情况对于测试工程师而言尤其的痛苦,那么自然我们就可以跳过界面层来做功能代码的接口测试。
  接着我们来说下Service层。与传统金字塔描述的Service不同的是,移动互联网的应用同时存在“Service”和“Inner Service”(感谢晋恒温提供这样一个我觉得很不错的新词)这里的Inner Service主要指的是Android基础组建里面也有一个叫Service
  这里提到Inner Service这个概念就是为了和服务器端的Service区别开来。在这个金字塔中Service被虚线所区分开,原因有两个:
  Service不再单纯的指后台服务器的Service
  不是所有应用都有Inner Service或者Service
  其中后台的服务Service测试方法已经相对成熟,参考的资料也相对多,而Inner Service的测试相比困难很多,除了监听Service是否正确启动以及反馈之外,还有很多测试细节可挖掘。
  最后就是共同的Unit了。其实我们拨开金字塔的上面几层,到Unit test的时候就已经和应用所在的平台的特性关系不大了。Android使用Junit Test,iOS使用Xcode自带的OCunit,WP使用Windows Phone Toolkit Test Framework等。除了编写测试用例的语言不同以外,其用例的设计方法等已经不再去考虑Android、iOS、WP等系统架构或其他特性上的区别了。
  我个人是认为移动无线应用的金字塔理念不仅仅适用于功能测试,更多的也适用于压力、性能、自动化甚至安全等测试中。当我们需要加大测试颗粒度的时候,那么借助分层的理念往往能够让我们豁然开朗,找到新的突破口。

posted @ 2014-04-08 10:37 顺其自然EVO 阅读(148) | 评论 (0)编辑 收藏

Apache搭建HTTPS Virtual Host

 Apache 搭建HTTPS Virtual Host
  1.创建SSL证书
  首先需要安装openssl,linux系统默认已安装,如没有则用以下命令安装:
  sudo apt-get install openssl
  sudo apt-get install libssl-dev
  创建证书:
  cd /etc/ssl/private
  sudo openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout demo.key -out demo.crt
  参数说明:
  -x509 显示证书和签名工具
  -days 证书的有效期
  -sha1 证书加密算法
  -newkey rsa:1024 创建一个新key,1024表示公钥长度为1024bits
  命令执行完会创建demo.key与demo.crt
  更多参数说明可以参考:http://www.openssl.org/docs/apps/openssl.html
  创建步骤:
root@ubuntu:/etc/ssl/private# sudo openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout demo.key -out demo.crt
Generating a 1024 bit RSA private key
.......++++++
...........++++++
writing new private key to 'demo.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:GD
Locality Name (eg, city) []:GZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:fdipzone.Ltd
Organizational Unit Name (eg, section) []:test
Common Name (eg, YOUR name) []:demo.fdipzone.com
Email Address []:fdipzone@gmail.com
root@ubuntu:/etc/ssl/private#
  需要填写的项目:
Country Name (2 letter code) [AU]: 国家
State or Province Name (full name) [Some-State]:省份
Locality Name (eg, city) []:城市
Organization Name (eg, company) [Internet Widgits Pty Ltd]:公司名称
Organizational Unit Name (eg, section) []: 组织单位名称
Common Name (eg, YOUR name) []: 填写域名
Email Address []:电邮地址
  2.创建Virtual Host
<VirtualHost *:443>
DocumentRoot /home/fdipzone/demo
ServerName demo.fdipzone.com
<Directory "/home/fdipzone/demo">
allow from all
AllowOverride all
Options -Indexes FollowSymLinks
</Directory>
SSLEngine on
SSLCertificateFile /etc/ssl/private/demo.crt
SSLCertificateKeyFile /etc/ssl/private/demo.key
SSLCipherSuite AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
SSLHonorCipherOrder on
</VirtualHost>
  开启SSL Engine及设置使用的证书,端口443
  SSLEngine on
  SSLCertificateFile /etc/ssl/private/demo.crt
  SSLCertificateKeyFile /etc/ssl/private/demo.key

posted @ 2014-04-08 10:30 顺其自然EVO 阅读(126) | 评论 (0)编辑 收藏

容量规划概述

 俗话说,"人无远虑,必有近忧",容量规划就是"远虑"。所谓容量规划,是一个产品满足用户目标需求而决定生产能力的过程。当产品发展到一个较为稳定成熟的阶段,产品的整体处理能力的把控自然是不可或缺,尽管我们在线下做性能测试能够获得一些数据,其参考价值终究有限。但是我们常常被问到以下一些问题而无以应对。
  (1)单台节点到底最大处理能力是多少?
  (2)目前线上有多少容量正在被使用?
  (3)在一次大促前当前的机器数是否能够支撑?
  (4)什么时候需要增加机器?加多少?
  这时候,容量规划就显得格外必要了。通过集体组织的容量规划学习,谈谈自己对容量规划的认识和理解。
  什么样的集群适合做容量规划?只有线性可水平扩展的集群,我们才能通过获取一个节点的处理能力,计算出集群的处理能力,否则将会费很大物力和人力。
  怎么做容量规划?一句话概括:线上压测到单节点的某一指标达到临界值,从而计算出集群的最大处理能力,再根据线上历史监控获得当前集群实际运行负荷,通过计算即可求出理论机器。
  容量规划能指导我们做什么?如果计算出集群当前的负荷快达到极限处理能力时,我们可以垂直扩展(加CPU/内存/磁盘)和水平扩展(加机器)两种方式来增加集群容量。
  容量规划六步走
  Step1 明确目标
  容量规划和计算,我们可以用运筹学中的优化命题来定义,优化命题的目标是集群实际负荷 <=集群理想负荷,求解这样一个不等式优化命题,同时系统需要满足一定的不等式约束条件。
  ü  目标:
  ü  约束条件:
  当然满足目标的同时,集群的状态是受到约束的,资源是不可能无限供应,终会有一项资源会达到临界值
  Step2 了解集群特点
  不同的集群在选取容量指标和约束条件时是完全不同的,容量指标在后面会介绍,主要用于衡量集群的处理能力,而约束条件是压测停止的信号。举例说明,对于CPU密集型的集群,我们常常会选择TPS(每秒处理请求书)作为集群的容量指标来衡量集群的处理能力,而约束条件中则会重点关注CPU的使用率是否率先成为瓶颈;对于存储型的集群,选择流量(MB/S)作为容量指标,存储型的集群TPS依赖于业务数据大小,所有流量更适合作为表征集群的处理能力,而约束条件最先成为瓶颈的是网络流量或者IO。
  而判断集群式何种类型则可以通过线下的性能测试结果来判断,线下的性能测试可以作为线上压测的参考依据。
  Step3 选取容量指标
  容量指标主要用作衡量服务器的处理能力。容量指标的选取原则:1)线上数据可采集2)能够客观反映服务器处理能力
  作为容量指标,需要通过线上监控获取统计数据,其历史数据用于计算集群的实际负荷,而通过压测获得集群的最大处理能力。如上所说,CPU密集型集群常选TPS作为容量指标,而存储型集群常选流量作为容量指标。 Step4  明确约束条件
  约束条件的存在主要是作为线上压测停止的信号,常常会包括业务指标和资源指标。其中只要有一项指标达到临界值,则停止压测将当前容量指标的值作为集群的最大处理能力,例如某项服务质量要求响应时间不超过100ms,那当响应时间达到临界值时,尽管其它指标并没有达到极限但是也把此时作为集群最大处理能力。因此服务指标的选取原则:1)业务需求 2)资源使用瓶颈。一则保证产品的服务质量,二来保证系统的安全。
  Step5 线上压测
  线上压测的主要目的主要用于获取集群的最大处理能力,而对于线上压测的手段主要介绍三种,针对不同的集群系统架构特点和业务类型选取不同的压测手段。
  模拟请求
  模拟请求,即是模拟客户端的调用方式向压测服务器发起请求,简单易操作。
  测试数据:可以通过分析线上日志分析,根线上业务配比建立压测模型,对于HTTP请求业务还有一种简单的方式,通过提取线上日志数据URL直接用于压测请求数据。
  实施步骤
  ü  将线上一台节点offline,测试客户端直连被测服务器
  ü  客户端梯度增加并发(50),不断增加并发直至超过设定的服务指标
  优缺点
  测试效果不受服务实际流量的限制,压测时间灵活,适用于GET请求不会产生脏数据。业务指标可以通过测试客户端直接获取。
  风险评估
  风险低,首先机器offline不会影响到线上的正常请求;其次缓慢增加并发,不会造成服务崩溃的情况。
  线上引流
 
  线上引流,即将线上其它节点的请求复制到被测服务器上,推荐使用Tcpcopy工具。
  测试数据:线上请求直接复制引流,无需准备数据
  实施步骤
  ü  将线上一台节点Off-line,按照Tcpcopy部署的方法部署client和server,为了便于指标的统计,通常将Tcpcopy部署在nginx所在服务器,被压测服务器前需要增加一层nginx服务器。
  ü  将集群的其它节点流量复制到off-line节点上,可以通过tcpcopy –r参数逐步增加复制系数,不断增加-r参数直至超过设定的服务指标
  ü  如果100%全部线上流量都不能压测到off-line节点的瓶颈,再逐步放大引流系数
  优缺点
  请求真实,能够放大流量,测试效果不受服务实际流量的限制,压测时间灵活,但环境部
  署稍微麻烦,对于PUT请求需要做一些业务处理,避免产生脏数据。风险评估
  风险低,首先机器offline不会影响到线上的正常请求,缓慢增加流量复制,不会造成服务崩溃的情况。
  修改负载权重
  对于一个集群,前面往往会有负载均衡服务器,以Nginx为例,通过修改Upstream模块的负载均衡weight可以不断增加集群某一节点的请求数,增加其访问压力。
  测试数据:无需准备
  实施步骤
  ü  缓慢增加nginx的负载均衡系数,使被测节点压力不断增加
  ü  直至超过设定的服务指标停止增加压力
  优缺点
  完全真实的场景,压测数据准确,但是依赖自身的流量,压测时间不灵活,需在高峰期,对用户体验有一定影响,随着一台机器的负载增加响应时间会受到一定影响,会直接反馈给在线用户。
  风险评估
  风险低,虽然在高峰期进行,但是只需要修改nginx配置再reload,对服务基本无影响,且每次都逐步增加weight,不会造成服务器崩溃的情况。
  Step6 线上监控
  线上监控不仅用于集群历史数据的收集,计算集群的实际负荷的监控,还用于压测过程中监控约束条件中的各种指标是否超限并停止压测。根据集群的特点和之前性能测试经验关注容量指标和约束条件的业务和资源指标。而这里的历史数据,是需要长期的采集和整理。
  小结
  综上所述,容量规划主要围绕着这么一个等式展开工作,纸上谈来终觉浅,实践出真知。希望能够在接下来的实践中成长和收获。

posted @ 2014-04-04 13:34 顺其自然EVO 阅读(2414) | 评论 (0)编辑 收藏

自动化测试介入的时机

 今天,在我建的一个测试群里看到有位同学抛出了这个一个问题
  自动化测试是在开发阶段就介入呢,还是等手工测试结束之后,系统功能稳定后,介入?
  当时没时间去回答,就找了以前在淘测试上看到的一篇文章发给他了。回到家之后,我在跑步机上想了下这个问题,现在我在做的自动化测试,会怎么去判断准入条件呢?
  首先,搞清楚自动化的目的是什么?
  提供工作效率,运行自动化测试用例可以同时做其他的工作,而且测试效率有了提升,大量case可同时运行
  提供运行的准确性和稳定性,避免外界因素的影响
  避免重复劳动,防止大量的手工回归测试,节省成本
  对测试人员而言,也是提高技能的一种手段
  上面的4点,是我对自动化测试目的一个总结,我对自动化是否有意义的判断也是基于上面的认知。当然你也可能会有其它一些想法。
  对于上面提到的那个问题, 我觉得还是不好解释,毕竟场景不同,其对应的方案也会不一样。从我现在所在的团队来看,这样的问题,我会从整个项目的周期来判断,下面是目前我们的一个做法,当然并不是很完整,我简单说一下过程。
  软件开发流程,大家比较清楚的可能是瀑布流程,敏捷开发这些。不管采用什么样的流程,测试的工作如何接入配合到开发流程中才是最重要的,最关键的。而不是去考虑什么时间去做自动化测试,自动化测试应该是在合适的时间就得开展。
  现在,我们不会去区分角色,功能测试人员和自动化测试人员应该就是一个人,测试人员应该对应于一个产品,而不是一种技能。
  项目前期,kickoff结束,测试同学就应该参与到项目中,对项目的需求进行一定的把握。下面的流程是我们测试的一些关键时间点:
  1. 需求评审
  这个阶段可以了解项目的背景,并开始和开发,PD沟通一些功能上的设计问题。为后面设计case提供一些思路。
  2. 开发设计&&测试用例设计
  有些工作并不一定要等到开发全部完成再进行,紧密沟通合作,保证项目向前推进。在开发设计阶段就可以参与进来,并在开发设计完成后,对应完成测试用例的设计,明确哪些case可以实现自动化,并选择好测试框架和工具。
  3. 分层测试&&可自动化的部分先行
  在未得到稳定的测试版本之前,可以准备测试数据,一键部署的脚本,已经对应测试框架,测试代码的编写。不一定要全部完成,但至少准备工作都得做好。
  4. 冒烟&&测试执行
  提测之前,对部分重点功能进行常规冒烟测试。达到预期后,进行功能测试。这个测试工程中,即可以对一些自动化测试的case进行编码调试,后面这些功能可以在回归执行中有非常大的作用。
  5. bugfix版本,自动化回归
  对应一些bugfix的版本,除了验证bug之外,还得将之前的功能进行回归,这个阶段,自动化的case将节省不少的精力。
  6. 稳定版本,自动化回归,预发环境自动化验证
  在发布上线之前,会准备一个稳定的环境,做一次全量的测试执行,当然自动化case也是这个时候的重点。
  7. 发布上线,冒烟
  待上述测试执行都结束了,意味着项目也就安心上线发布了。这个时候需要简单的冒烟测试即可。
  经历这么一个项目的过程,自动化的case肯定是需要占有一定的比例。当然,大家肯定还是存在下面的一些疑问
  开发还未提交测试,或者功能也未稳到,如何进行自动化的测试?
  这个问题,我从下面的2点进行解释,其实前面我也有提到这些。
  a. 接口测试,待测的接口肯定需要事先定义好,这里更多的应该是测试数据的准备,已经测试类的编写,case的逻辑可以体现出来,当然调试case需要放到功能开发出来,但是我们的准备工作要都搞定。
  b. UI自动化,大家都会说页面还没出来,怎么写?道理是一样的,设计出来的场景是事先通过需求文档,交互PRD这些进行确认过的,同样,需要的测试数据可以先准备出来,代码的逻辑也可以写出一部分,这个时候缺的应该就是页面元素。
  如果设计的合理,我们的case应该做到测试数据和测试代码进行分离,这样你需要的部分可以配置为参数的形式,后期传入
  现在,在阿里不管是接口测试还是UI自动化,基本上都是在与开发同步进行,我们需要将自动化的作用最大化,提高测试的效率。
  所有,我最终的建议是尽量提前来做,将自动化的价值最大化。

posted @ 2014-04-04 13:33 顺其自然EVO 阅读(366) | 评论 (0)编辑 收藏

Selenium web driver 配合使用TestNG

 首先为eclipse添加testng插件
  1.步骤如下:help->Install New SoftWare...
  2. 添加testng链接,该链接可以在这里找到
For the Eclipse plug-in, we suggest using the update site:
Select Help / Software updates / Find and Install.
Search for new features to install.
New remote site.
For Eclipse 3.4 and above, enter http://beust.com/eclipse.
For Eclipse 3.3 and below, enter http://beust.com/eclipse1.
Make sure the check box next to URL is checked and click Next.
Eclipse will then guide you through the process.
 4.下载并安装 testng
  testng和junit相比为什么要使用testng
  1. testng 和junit功能基本相同testng支持suite,junit执行一大堆case,如果个别fail,只能所有case重跑
  而testng可以单独跑
  2.testng能生成漂亮的测试报告,比较直观
  添加一个testng case,复制一份,保存为
  openlinkTest1.java
package baidu;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import junit.framework.Assert;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class openlinkTest {
public static void snapshot(TakesScreenshot drivername, String filename)
{
// this method will take screen shot ,require two parameters ,one is driver name, another is file name
File scrFile = drivername.getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
try {
System.out.println("save snapshot path is:E:/"+filename);
FileUtils.copyFile(scrFile, new File("E:\\"+filename));
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Can't save screenshot");
e.printStackTrace();
}
finally
{
System.out.println("screen shot finished");
}
}
@BeforeMethod
public void tearUp()
{
//    WebDriver driver = new ChromeDriver();
}
@Test
public static void runSelenium() throws InterruptedException
{
String URL="http://www.baidu.com";
Pattern p = Pattern.compile("http");
Matcher m = p.matcher(URL);
if(m.find())
{
System.out.println(URL);
}
System.setProperty("webdriver.chrome.driver", "E:\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(URL);
//max size the browser
driver.manage().window().maximize();
/*
Navigation navigation = driver.navigate();
navigation.to(URL);*/
Thread.sleep(2000);
snapshot((TakesScreenshot)driver,"open_baidu.png");
//WebElement reg=driver.findElement(By.name("tj_reg"));
//reg.click();
//    WebElement keyWord = driver.findElement(By.id("kw1"));
//find the element
WebElement keyWord = driver.findElement(By.xpath("//input[@id='kw1']"));
keyWord.clear();
//send key words
keyWord.sendKeys("Selenium");
Thread.sleep(3000);
snapshot((TakesScreenshot)driver,"input_keyWord.png");
WebElement submit = driver.findElement(By.id("su1"));
System.out.println(submit.getLocation());
submit.click();
//System.out.println(driver.getWindowHandle());
Thread.sleep(5000);
// System.out.println(driver.getPageSource());
String pageSource=driver.getPageSource();
//  System.out.println(pageSource);
//WebElement link =driver.findElement(By.xpath(SELENIUM_LINK));
WebElement link =driver.findElement(By.xpath("//*[@id=\"1\"]/h3/a"));     //*[@id="1"]/h3/a
link.click();
Thread.sleep(5000);
driver.switchTo().window(driver.getWindowHandles().toArray(new String[0])[1]);
//get page title
System.out.println(driver.getTitle());
Thread.sleep(5000);
//     navigation.back();
snapshot((TakesScreenshot)driver,"open_bake.png");
System.out.println(driver.getTitle()+"\n"+driver.getCurrentUrl());
Assert.assertEquals(driver.getTitle(),"Selenium - Web Browser Automation");
driver.quit();
}
@AfterMethod
public void tearDown()
{
//driver.quit();
System.out.println("------------END----------------------");
}
}

 添加testng suite
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Test">
<classes>
<class name="baidu.openlinkTest"/>
<class name="baidu.openlinkTest1"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
  执行case:
  结果如下
[TestNG] Running:
C:\Users\Young\workspace\selenium\src\baidu\testng.xml
http://www.baidu.com
Starting ChromeDriver (v2.9.248315) on port 28218
save snapshot path is:E:/open_baidu.png
screen shot finished
save snapshot path is:E:/input_keyWord.png
screen shot finished
(858, 179)
Selenium - Web Browser Automation
save snapshot path is:E:/open_bake.png
screen shot finished
Selenium - Web Browser Automation
http://docs.seleniumhq.org/
------------END----------------------
http://www.baidu.com
Starting ChromeDriver (v2.9.248315) on port 5568
save snapshot path is:E:/open_baidu.png
screen shot finished
save snapshot path is:E:/input_keyWord.png
screen shot finished
(858, 179)
Selenium_百度百科
save snapshot path is:E:/open_bake.png
screen shot finished
Selenium_百度百科
http://baike.baidu.com/subview/478050/6464537.htm?fr=aladdin
------------END----------------------
===============================================
Suite
Total tests run: 2, Failures: 1, Skips: 0
===============================================

posted @ 2014-04-04 13:32 顺其自然EVO 阅读(309) | 评论 (0)编辑 收藏

认识loadrunner及相关性能参数

 LoadRunner,是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试。通过使用 LoadRunner,企业能最大限度地缩短测试时间,优化性能和加速应用系统的发布周期。 LoadRunner是一种适用于各种体系架构的自动负载测试工具,它能预测系统行为并优化系统性能。
  对象
  LoadRunner的测试对象是整个企业的系统,它通过模拟实际用户的操作行为和实行实时性能监测,来帮助您更快的查找和发现问题。此外,LoadRunner能支持广泛的协议和技术,为您的特殊环境提供特殊的解决方案。
  主要功能
  轻松创建虚拟用户
  使用LoadRunner的Virtual User Generator,您能很简便地创立起系统负载。该引擎能
  LoadRunner性能虚拟用户模拟测试
  够生成虚拟用户,以虚拟用户的方式模拟真实用户的业务操作行为。它先记录下业务流程(如下订单或机票预定),然后将其转化为测试脚本。利用虚拟用户,您可以在Windows ,UNIX 或Linux 机器上同时产生成千上万个用户访问。所以LoadRunner能极大的减少负载测试所需的硬件和人力资源。
  用Virtual User Generator 建立测试脚本后,您可以对其进行参数化操作,这一操作能让您利用几套不同的实际发生数据来测试您的应用程序,从而反映出本系统的负载能力。以一个订单输入过程为例,参数化操作可将记录中的固定数据,如订单号和客户名称,由可变值来代替。在这些变量内随意输入可能的订单号和客户名,来匹配多个实际用户的操作行为。
  为了进一步确定您的Virtual user 能够模拟真实用户,您可利用LoadRunner控制某些行为特性。例如,只需要点击一下鼠标,您就能轻易控制交易的数量,交易频率,用户的思考时间和连接速度等。
  创建真实的负载
  Virtual users 建立起后,您需要设定您的负载方案,业务流程组合和虚拟用户数量。用LoadRunner的Controller,您能很快组织起多用户的测试方案。Controller 的Rendezvous 功能提供一个互动的环境,在其中您既能建立起持续且循环的负载,又能管理和驱动负载测试方案。
  而且,您可以利用它的日程计划服务来定义用户在什么时候访问系统以产生负载。这样,您就能将测试过程自动化。同样您还可以用Controller 来限定您的负载方案,在这个方案中所有的用户同时执行一个动作---如登陆到一个库存应用程序----来模拟峰值负载的情况。另外,您还能监测系统架构中各个组件的性能---- 包括服务器,数据库,网络设备等----来帮助客户决定系统的配置。
  定位性能问题
  LoadRunner内含集成的实时监测器,在负载测试过程的任何时候,您都可以观察到应用系统的运行性能。这些性能监测器为您实时显示交易性能数据(如响应时间)和其它系统组件包括application serverweb server,网路设备和数据库等的实时性能。这样,您就可以在测试过程中从客户和服务器的双方面评估这些系统组件的运行性能,从而更快地发现问题。
  利用LoadRunner的ContentCheck TM ,您可以判断负载下的应用程序功能正常与否。ContentCheck 在Virtual users 运行时,检测应用程序的网络数据包内容,从中确定是否有错误内容传送出去。它的实时浏览器帮助您从终端用户角度观察程序性能状况。
  分析结果以精确定位问题所在
  一旦测试完毕后,LoadRunner收集汇总所有的测试数据,并提供高级的分析和报告工具,以便迅速查找到性能问题并追溯原由。使用LoadRunner的Web 交易细节监测器,您可以了解到将所有的图象、框架和文本下载到每一网页上所需的时间。例如,这个交易细节分析机制能
  够分析是否因为一个大尺寸的图形文件或是第三方的数据组件造成应用系统运行速度减慢。另外,Web 交易细节监测器分解用于客户端、网络和服务器上端到端的反应时间,便于确认问题,定位查找真正出错的组件。例如,您可以将网络延时进行分解,以判断DNS 解析时间,连接服务器或SSL 认证所花费的时间。通过使用LoadRunner的分析工具,您能很快地查找到出错的位置和原因并作出相应的调整。

重复测试保证系统发布的高性能
  负载测试是一个重复过程。每次处理完一个出错情况,您都需要对您的应用程序在相同的方案下,再进行一次负载测试。以此检验您所做的修正是否改善了运行性能。
  LoadRunner完全支持EJB 的负载测试。这些基于Java 的组件运行在应用服务器上,提供广泛的应用服务。通过测试这些组件,您可以在应用程序开发的早期就确认并解决可能产生的问题。
  利用LoadRunner, 您可以很方便地了解系统的性能。 它的Controller 允许您重复执行与出错修改前相同的测试方案。它的基于HTML 的报告为您提供一个比较性能结果所需的基准,以此衡量在一段时间内,有多大程度的改进并确保应用成功。由于这些报告是基于HTML 的文本,您可以将其公布于您公司的内部网上,便于随时查阅。
  接下来的文章编者就将辑录一篇网上的使用LoadRunner&reg;来测试BEA中间件产品文章来与大家分享如何使用LoadRunner进行实际的性能测试。
  性能测试
  1. LoadRunner的虚拟用户
  LoadRunner使用虚拟用户(Virtual users)来模拟实际用户对业务系统施加压力。虚拟用户在一个中央控制器(controller station)的监视下工作。
  在做一个测试方案时,要做的第一件事就是创建虚拟用户执行脚本。LoadRunner提供了Virtual User Generator来录制或编辑虚拟用户脚本。
  2. 使用Vugen创建虚拟用户执行脚本
  A.从菜单中选择运行Virtual User Generator:
  B.创建一个单协议脚本,选择协议类型为"Tuxedo 7"
  C.在弹出的窗口中输入Tuxedo客户机程序的可执行文件名(SimpApp.exe),并选择"Record into Action"为Action。
  点击"OK"开始录制脚本,这时Vugen就会启动Simpapp.exe,如下图所示,输入WSNADDR,输入字符串(Tuxedo is powerful!)之后,点击TOUPPER,TUXEDO服务器完成请求后把输出字符串(TUXEDO IS POWERFUL!)写到"Output string"中,点击停止录制按钮。
  D.编辑Vuser脚本。在C中做的所有操作都被录了下来,记录到一个脚本文件中,其内容如下,把它存为simpapp。
  脚本内容如下:
#include "lrt.h"
#include "replay.vdf"
Actions()
{
lrt_tuxputenv("WSNADDR=//172.22.32.25:7110");
lr_think_time(3);
tpresult_int = lrt_tpinitialize(LRT_END_OF_PARMS);
lrt_abort_on_error();
data_0 = lrt_tpalloc("STRING", "", 1);
lrt_strcpy(data_0, sbuf_1);
data_1 = lrt_tpalloc("STRING", "", 1);
tpresult_int = lrt_tpcall("TOUPPER", data_0, 0, &data_1, &olen, 0);
lrt_abort_on_error();
lrt_tpfree(data_0);
lrt_tpfree(data_1);
lrt_tpterm();
return 0;
}
  代码中加粗的函数是LoadRunner对TUXEDO函数的二次包装。
  E.点击工具栏中的"执行"按钮来执行我们刚才录制的脚本,确保执行无误。
  3. 使用控制器(Controller)来调度虚拟用户
  A.从菜单中选择运行Controller:
  B.创建一个新的Scenario,选择刚才录制的脚本(simpapp):
  点击"OK",弹出Scenario调度界面。在"Quantity"中输入100,表示使用100个虚拟用户。(虚拟用户与购买的LICENSE有关联)
  C.点击"Edit Schedule"来编辑压力调度。
  D.选择"Runtime settings"来作运行时设置。
  在Pacing的设置中,"Number of Iterations"用于设置Vusers的Actions被执行的次数;"Start new iteration"用于设置调度器在什么时机迭代执行Vusers的Actions。
  "Think Time"用于设置Vusers的反应和思考时间,以尽量做到和正常人一样来施压。"Ignore think time"表示忽略思考时间,这是理想状态,一般不使用。"As recorded"表示按照录制时的实际操作时间。"Multiply recorded think time by"表示Vusers的思考时间是实际录制时间的若干倍。
  在"Miscellaneous"中设置一些杂项,如使用进程还是使用线程等。对于TUXEDO,好象只能选进程模式。
  E.选择"Start scenario"来开始本次压力测试调度。
  执行结果分析如下:
  施压时间为5分41秒,Vusers数量为100,一共完成的Actions交易数量为5625笔,平均响应时间为5.561秒,TPS为17.8。[1]
  LoadRunner组件
  1、VuGen(虚拟用户生成器) 用于捕获最终用户业务流程和创建自动性能测试脚本 (也称为虚拟用户脚本)。
  2、Controller (控制器)用于组织、驱动、管理和监控负载测试。
  3、Load Generator(负载生成器)用于通过运行虚拟用户生成负载。
  4、Analysis (分析器)有助于您查看、分析和比较性能结果。
  实例应用
  在软件测试工具中如何巧用LoadRunner的随机函数
  LoadRunner有自带的随机函数,如果巧妙的加以采用,能解决一些看似很困难的实际问题。
  一个项目的性能测试。与数据库直连,根据外部传入的SQL ID和SQL参数,从指定数据库中读取SQL模版,拼装成真实的SQL语句、执行,并将得到的结果放入缓存中。目的是减少数据库的压力。
  该系统将支撑大量的SQL操作,性能自然成为备受关注的焦点之一。
  由于它跟SQL语句相关,在真实环境下,同一时间可能执行着不同类型的SQL,即便是同一类型,其参数也各式各样。那么,怎样才能模拟出最符合实际情况的性能测试场景呢?
  首先设计场景,即,在LoadRunner中按照比例随机取到某一类型的SQL,再随机传入参数给它,让最终的每条SQL都是随机生成,各不相同。
  从场景中,可以看到,此处涉及双重随机。只采用loadruner的参数设置是无法实现的。此时需要想办法先按设定好的比例随机取到SQL,然后在每条SQL上随机取参数列表中的参数。
  于是想到了loadrunner的随机函数。先实现随机取SQL ID,之后再在特定的SQL中随机取参数列表中的参数。
  LoadRunner中,随机函数是rand(),它用来产生0到rand_max之间的随机整数。函数原型是
  int rand ( void );
  然而调用rand之前,必须给随机数产生一个随机种子。这个种子由srand()函数产生。其原型是
  int srand ( seedTime );
  采用上述两个函数,就能实现第一重随机了。具体脚本代码如下:
//generate rand number
int rNum = 0;
srand(time(NULL));
rNum = rand() % 10;
lr_output_message(”the number is :%d”,rNum); //print the current random number
  生成随机数后,再按比例用if … else … 来取到各种类型的SQL,并给它们传参。具体脚本代码如下:
//get certain SQL and random value
if (rNum>=0 && rNum<2) {
web_url(”test”, “URL=http://host_name:8080/interface?sqlId=sqlid_name2&value={random_para2} “,
”Resource=0″,
”RecContentType=text/html”,
”Referer=”,
”Snapshot=tn.inf”,
“Mode=HTTP”,
LAST);
}
else if(rNum>=8 && rNum<10){
web_url(”test”, “URL=http://host_name:8080/interface?sqlId=sqlid_name2&value={random_para2} “,
”Resource=0″,
”RecContentType=text/html”,
”Referer=”,
”Snapshot=tn.inf”,
“Mode=HTTP”,
LAST);
}
else {
rNum = 0;
lr_output_message(”the number is :%d”,rNum);
}
  注:sqlid_name是SQL ID名称;random_para是通过file方式实现的随机参数;tn是web_url函数的快照名称。
  通过上面的脚本,实现了性能测试设计的场景。调试通过后,放入Controller中执行。实际执行过程中,Vuser将会按比例随机取到不同类型的SQL,并随机取到SQL中的参数,执行特定的SQL语句。

posted @ 2014-04-04 13:30 顺其自然EVO 阅读(294) | 评论 (0)编辑 收藏

Eclipse调试,以及JUnit测试工具用法

 调试:
  单步跳入(Step Info):进入代码内部观察,对应的快捷键是F5。
  单步跳过(Step Over):只观察代码的运行结果,对应的快捷键是F6。
  执行完毕(Resume):整个代码向后自动执行完毕,对应的快捷键是F8。目前没有发现有多大用处。
  JUnit测试工具
  JUnit测试是程序员测试,即白盒测试,因为程序员知道被测试的软件如何完成功能和完成什么样的功能,JUnit其实是一套框架,所有需要测试的类直接继承TestCase类
  1、新建一个方法
package com.tony.JUnit;
public class JUnit {
public int add(int i,int j )throws Exception{
int result=i+j;
return result;
}
}
  2、新建一个JUnit测试类
package com.tony.JUnit;
import junit.framework.*;
import org.junit.Test;
public class JUnitTest {
@Test
public void test() {
//fail("Not yet implemented");
try{
Assert.assertEquals(new JUnit().add(12,1),13);
}catch(Exception e){
e.printStackTrace();
}
}
}

posted @ 2014-04-04 13:28 顺其自然EVO 阅读(356) | 评论 (0)编辑 收藏

Java VM 参数描述

内部服务参数配置:
JAVA_OPTS="-server -XX:+UseParNewGC -Xms1024m -Xmx2048m -XX:MaxNewSize=128m -XX:NewSize=128m -XX:PermSize=96m -XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:CMSInitiatingOccupancyFraction=1 -XX:+CMSIncrementalMode -XX:MaxTenuringThreshold=0 -XX:SurvivorRatio=20000 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0  -XX:CMSIncrementalDutyCycleMin=10 -XX:CMSIncrementalDutyCycle=30 -XX:CMSMarkStackSize=8M -XX:CMSMarkStackSizeMax=32M"
  前端应用参数配置:
JAVA_OPTS="-server  -Xmx4096m -Xms4096m -Xmn480m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=8 -XX:CMSFullGCsBeforeCompaction=0
-XX:+UseCMSCompactAtFullCollection -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=7 -XX:GCTimeRatio=19
-Xnoclassgc -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:-CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0"
  参数说明:
  -Xmx1280m:设置JVM最大可用内存为1280m。最大可设为3550m。具体应用可适当调整。
  -Xms1280m:设置JVM初始内存为1280m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
  -Xmn480m:设置年轻代大小为480m。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
  -Xss256k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
  -XX:PermSize=64m:指定 jvm 中 Perm Generation 的最小值。 这个参数需要看你的实际情况。可以通过jmap 命令看看到底需要多少。
  -XX:MaxPermSize=128m:指定 Perm Generation 的最大值
  -XX:+UseConcMarkSweepGC:设置并发收集器
  -XX:ParallelGCThreads=8:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
  -XX:CMSFullGCsBeforeCompaction=0:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
  -XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片。
  -XX:SurvivorRatio=8:每个survivor space 和 eden之间的比例。
  -XX:MaxTenuringThreshold=7:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。
  -XX:GCTimeRatio=19:设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)。
  -Xnoclassgc:禁用类垃圾回收,性能会有一定提高。
  -XX:+DisableExplicitGC:当此参数打开时,在程序中调用System.gc()将会不起作用。默认是off。
  -XX:+UseParNewGC:设置年轻代为并行收集。可与CMS收集同时使用。
  -XX:-CMSParallelRemarkEnabled:在使用 UseParNewGC 的情况下 , 尽量减少 mark 的时间。
  -XX:CMSInitiatingOccupancyFraction=70:指示在 old generation 在使用了 70% 的比例后 , 启动 concurrent collector。
  -XX:SoftRefLRUPolicyMSPerMB=0:每兆堆空闲空间中SoftReference的存活时间。

posted @ 2014-04-04 13:26 顺其自然EVO 阅读(222) | 评论 (0)编辑 收藏

数据库架构的演变

 最近看了很多公司架构的演变的文章,发现其中的基本思路和架构演变都很类似,这里也总结一下数据库架构的演变以及演变背后的思路。
  单主机
  最开始网站一般都是由典型的LAMP架构演变而来的,一般都是一台linux主机,一台apache服务器,php执行环境以及mysql服务器,一般情况下,这些都在一台虚拟主机上,简称单主机模式。
  单主机模式缺点:
  1 web服务器和mysql服务器公用一台主机,共享硬件资源,可能存在某一方资源征用太大,导致整个应用产生瓶颈
  2 当业务增长之后,没有办法做到横向扩展。
  3 容错性太差,一旦主机存在问题,整个应用不可用
  独立主机
  随着业务的发展,可以把mysql服务器和web服务器主机分开,分别部署,就是独立主机模式。
  独立主机模式下,web服务器和mysql不再共享硬件资源,分别部署。没有把鸡蛋放在一个篮子里面,增加了容错性。如果只是mysql服务器故障,那么对于web上不访问服务器的应用是不会受到影响的。而且web服务器可以做到横向扩展,如果web服务器性能不够,可以增加多台web服务器,进行负载均衡,分散web服务器的压力。
  独立主机模式的缺点:
  1 可扩展性问题:虽然web服务器可以做到横向扩展,但是mysql服务器是没有办法做到横向扩展的。
  2 可用性问题:mysql服务器存在单点问题,一旦mysql服务器宕机,对影响的影响很大
  3 性能问题:单台mysql服务器能够支撑的服务是有限的。
  读写分离
  随着业务的不断发展,数据库的压力会越来越大,单数据库慢慢的就不能满足需求了,一些网站对数据实时性要求不高,就会慢慢发展读写分离模式,对于普通的查询请求,分配到读库(也可以说是备库),对于修改请求,在主库上完成。对于读库,由于是无状态的,可以做到横向扩展。对于写库,还只能是单台主机
  这种模式其实有限制的,要根据业务的类型来考虑。主库的数据是最新的,但是同步到读库会有时延,所以应用必须能够容忍短暂的不一致性。对于一致性要求非常高的场景是不适合的。
  这种模式的存在的问题:
  1 可扩展性:虽然读库可以做到横向扩展,但是写库还不行,读库不能够横向扩展
  2 可用性:读库成为单点,一旦故障,影响所有的写操作业务
  业务垂直拆分
  随着业务的发展,一台写库显然不能够满足高并发的情况,但是考虑到写库是有状态的,不能简单的横向扩展,假设有两台写库,那么随机更新一台的数据,就会导致另一方数据存在问题。出现一种数据两个不同版本,显然是无法接受的。在写库上,可以考虑按照业务来垂直进行分库。由于我们这里讨论的是数据库架构,对于web层来说,其实也是可以按照业务垂直拆分的。
  在按照业务垂直拆分以后,系统在性能上有了很高的提升,只需要把业务上分成垂直部分,分的越细,系统的整体扩展能力就越强。


这种模式下,存在以下几个问题
  1 可用性:假设一个完整的业务流程P访问的数据库被拆分为A、B、C、D、E 五个库,假设每个写库可用性为99%,那么这个业务流程P的可用性就为99%*99%*99%*99%*99%=95%,库拆分的越多,对系统的整体可用性挑战就越大。
  2 性能:由于垂直业务库每个库的负载可能不一样,假设交易库负载很高,一个交易写库肯定不能够满足需求,这个情况下,交易库成为整个系统的瓶颈。
  3 可扩展性:单个节点的可扩展性没有得到改善,交易库不能单独进行扩展。
  单业务库水平、垂直拆分
  在上一种情况,假设交易库是整个系统的瓶颈,需要对交易库进行单独的扩展。可以考虑交易的水平拆分或者垂直拆分,有可能同时进行两种方式拆分。
  水平拆分一般根据业务无关的关键字进行拆分,横向扩展性比较好,但是对于查询的挑战比较大
  垂直拆分一般根据业务来拆分,但是可能导致数据不均匀以及拆分不够灵活。对于查询来说,相对比较友好
  拿交易库举个例子,可以先交易的类型进行业务上的垂直分库,在按照订单号进行水平分库。
  假设可以分成M*N个库,那么单个库的故障会影响1/M*N 的交易,但是假设每个库可用性为99% ,那么交易数据库故障概率为 (99%)的(M+N)次方,如果数据库拆分的越多,发生单个数据库故障概率就越高。
  这种方式存在的问题:
  1 虽然单个节点故障影响的用户很少,但是整体可用会降低。
  2 数据库管理上带来复杂的挑战,假设交易库表结构变更,需要执行M×N次脚本变更。
  3 由于发生单个数据库故障的概率比较高,dba会很苦逼的,估计经常性要救火
  4 开发和测试起来会非常苦逼,开发和测试成本会变高,查询非常复杂。
  5 单个节点如果发生故障,没有失败检测并且切换机制
  6 分库还不能在水平方向做到无限扩展,我们的算法是事先分配M个库,如果添加一个库基本上不可行
  随机分库
  对于第六个问题,在水平方向的无线扩展,可以考虑一种机制,在insert数据的时候,申请一个数据库编号,然后把数据库的编号作为一个字段保存或者在把这个编号添加到已经字段上。
  例如假设我们申请insert数据库,得到一个数据库编号为1000,那么我们可以构造出来一个订单号为1000_tradeno,订单号前面是分库编号,订单号后面是实际tradeno,这样解决了水平无线扩展的问题。这种就是随机分库模式。但是这一种方式的局限性很大,
  随机分库的缺点:
  1 分库算法和业务耦合在一起,比较适合特定的场景,适用范围比较窄
  2 对于insert操作,比较容易,对于update操作,必须有分库编号,也就是说,只能根据特定的字段来进行更新
  3 不适合批量查询的场景,查询功能限制比较大,这也是分库带来的问题
  单数据库备份以及失败切换
  对于单个数据库,如果发生故障,会影响业务,但是能否在发生故障的时候进行切换。虽然可以实现,但是会存在一定的问题,需要特定场景进行特定的分析。这一块比较复杂,说起来可以在写一篇文章,就简单的介绍一下
  以上就是总结的数据库的架构演变,数据库的演变需要很多基础技术做支撑,主要包括
  1 强大的分布式数据库的管理中间件,主要屏蔽底层的数据库路由以及数据管理功能
  2 强大的数据运维团队以及监控体系,能够检测出每个节点的数据库状态
  3 强大的数据库管理管理团队,能够维护这么的数据库集群
  4 强大的业务架构能力和技术架构能力,能够掌控这么复杂的业务场景。

posted @ 2014-04-04 12:23 顺其自然EVO 阅读(172) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 129 130 131 132 133 134 135 136 137 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜