不一样的思想~~ http://shop34712791.taobao.com MSN:wins0910@hotmail.com

发布新日志

  • 性能测试的一些思路(四)~

    2007-08-06 09:47:48

    选取场景---〉单用户单事务执行当前场景---〉获取执行时间(请求时间+响应时间+服务时间)---〉获取CPS---〉以此作为当次场景的基准值--〉换算到并发请求场景中--〉多用户并发单事务执行当前场景--〉获取TPS--〉以当前服务环境为基准(当前最大线程数)获取当前TPS、最大并发数、当前最大吞吐量--〉换算出以上最优理论值--〉调整间隔时间--〉引入TCA--〉获取单用户多事务TPS--〉换算出以上实际测试指标--〉多用户多事务渗入测试--〉调整以上指标--〉结论
  • 调ws的一些方法(未消化的)~

    2007-08-04 00:19:03

    当然也可以自己写程序测试web service,这样既可以生成客户端代码也可以生成服务器端代码,结合Junit,Ant很方便的实现自动化测试.通用的java类库有Axis 和 Xfire,可以根据不同需要选择版本.

    以Axis1.4为例,生成服务器端代码用一下命令

    java -cp .;.\lib\axis.jar;.\lib\axis-ant.jar;.\lib\axis-schema.jar;.\lib\commons-discovery-0.2.jar;.\lib\commons-logging-1.0.4.jar;.\lib\jaxrpc.jar;.\lib\log4j-1.2.8.jar;.\lib\saaj.jar;.\lib\wsdl4j-1.5.1.jar;.\lib\activation.jar;.\lib\mail.jar; org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true XXXX.wsdl

    客户端代码

    java -cp .;.\lib\axis.jar;.\lib\axis-ant.jar;.\lib\axis-schema.jar;.\lib\commons-discovery-0.2.jar;.\lib\commons-logging-1.0.4.jar;.\lib\jaxrpc.jar;.\lib\log4j-1.2.8.jar;.\lib\saaj.jar;.\lib\wsdl4j-1.5.1.jar;;.\lib\activation.jar;.\lib\mail.jar; org.apache.axis.wsdl.WSDL2Java -client XXXX.wsdl

    deploy服务器

    java -cp .;.\lib\axis.jar;.\lib\axis-ant.jar;.\lib\axis-schema.jar;.\lib\commons-discovery-0.2.jar;.\lib\commons-logging-1.0.4.jar;.\lib\jaxrpc.jar;.\lib\log4j-1.2.8.jar;.\lib\saaj.jar;.\lib\wsdl4j-1.5.1.jar; org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService deploy.wsdd

  • Weblogic性能调优的一些思路(一)~

    2007-08-02 09:20:31

    为得到高性能的吞吐量,把Java堆的最小值与最大值设为相等。如:

    "%JAVA_HOME%\bin\java" -hotspot -Xms512m -Xmx512m -classpath %CLASSPATH% -

    在一个WebLogic域中,配置文件(config.xml)位于与管理服务器通信的机器里,提供WebLogic MBean的长期存储。管理服务器作为连接的中心点,为服务实例与系统管理工具提供服务。域也可以包括其他的WebLogic实例,称之为从服务,主要为应用程序提供服务。

    ExecuteQueue//执行队列缺省处理线程数

    ThreadsIncrease //线程增量,以支援溢出,减缓执行队列的负荷量

    ThreadsMaximum //处理中的最大线程数

    Execute Queues
     默认的执行线程为15。
     
     默认的执行线程为25。

    如果你不配置额外的执行队列,并且指定应用给这些队列,web 应用程序和RMI对象就使用默认的队列weblogic.kernel.default。

    注意;如果自带的执行包没有在你的平台上使用,你可能需要调整默认的执行队列线程数和担任socket读的线程的百分比,去实现最佳性能。

    为了给执行队列决定一个理想的线程数,当队列中所有应用程序都运行在最大负荷的情况下,监视队列的吞吐量。增加线程数,重复负载测试,直到达到最佳的吞吐量。(在某些情况下,增加线程数将产生足够多的上下文转换程序,使得队列中的吞吐量开始减少。)

    注意:WebLogic管理控制台显示的是所有服务器执行队列累积的吞吐量。
    设置理想的执行队列的线程数,我们可以启动管理控制台,在域(如:mydomain)> 服务器 > server实例(如:myserver)> 监视 > 性能中监控最大负载时执行队列的吞吐量和队列中的等待请求数,据此确定理想的数值。

    n         队列长限制百分比(Queue Length Threshold Percent):达到队列长度百分比(1-99)时,就构成了溢出条件的产生。实际队列大小在限制的百分比之下时才被认为是正常的;在限制百分比之上就会产生溢出。当出现溢出,WebLogic日志就会产生一个错误消息,并且按线程数增量(Threads Increase)属性的值增加线程数,以帮助减少负载量。
    默认的队列长限制百分比为90%。一般情况下,应保留90%或其左右,以应对一些潜在的情况,使得有额外的线程可以去处理一些请求中的异常。记住,队列长度限制百分比不是一定作为自动优化参数――因为正常运作情况下,这个限度从不会被触发。

    n         线程数(Thread Count):指派到这个队列的线程数。如果你不需要使用超过15个线程(默认),就不必更改这个属性值。

    n         线程数增量(Threads Increase):是指WebLogic探测到有溢出时,增加到执行队列的线程数。当你指定为0(默认),出现溢出时,WebLogic会把运行良好状态改为"警告",而且也不会指派额外的线程去减少负荷量。如果CPU和内存不是足够的高,尽量不要改变默认值"0"。因为Weblogic一旦增加后不会自动缩减,虽然最终可能确实起到了降低请求的作用,但在将来的运行中将影响程序的性能。

    注意:如果WebLogic实例的线程数响应了溢出,那么这些额外的线程就会滞留在执行队列,直到服务器重启。监视错误日志,以判断溢出产生的原因,以便根据需要重配置线程数,防止以后类似情况产生。不要同时使用线程数增量和队列长限制百分比作为自动优化的手段。如此做通常结果会产生比正常需要还多的线程被指派到执行队列,这样上下文转化程序的增多会使服务器遭受很差的性能。

    n         最大线程数:是指执行队列中能运行的,这个值保护WebLogic为了响应频繁溢出,创建过多的线程数。默认情况下,最大线程数为400。

    n         堵塞线程最大时间(Stuck Thread Max Time):输入秒数,线程一定是不断的运行,服务器才会诊断这个线程作为堵塞。默认情况下,WebLogic认为线程连续不断运行600秒后置为堵塞。

    n         堵塞线程时间间隔(Stuck Thread Timer Interval):输入秒数,这个时间是WebLogic周期性的扫描线程以察觉它们是否连续不断运行了某一线程的时间达到通过堵塞线程最大时间属性指定的时间长度。默认时间间隔为600秒。

    Config.xml文件中的元素接受缓存数(AcceptBacklog)属性是用来设定请求WebLogic实例的连接数,在拒绝额外的请求之前,能接受设定的缓存数。AcceptBacklog属性指定有多少TCP连接缓存在等待队列,规定服务器向操作系统请求的队列大小,这个固定的队列存放了TCP堆栈已经收到但应用程序还没有收到的连接请求。默认值是50,最大值由操作系统决定。

    根据需要修改默认的接受缓存数(Accept Backlog):

    n         在运行期间,如果许多客户端连接得不到响应或被拒绝,并且服务器端也没有错误消息,说明接受缓存的值可能太小。

    n         在你访问WebLogic时,如果收到"拒绝连接(connection refused)"的提示,则应该增加接受缓存的默认值的25%。继续增加其值的25%,直到停止出现这样的提示。
        
     对于Portal类型的应用,默认值往往是不够的。Login Timeout和SSL Login Timeout参数表示普通连接和SSL连接的超时时间,如果客户连接被服务器中断或者SSL容量大,可以尝试增加该值。

    虽然Web应用程序的处理需求变化多端,但BEA公司发现WebLogic实例与CPU最理想的比例是1:2。

  • tomcat性能调优(一)~

    2007-08-02 09:14:13

    当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值的80%。

    一次完全的垃圾收集应该不超过 3-5 秒。

    你应该使用物理内存的 80% 作为堆大小。

    虽然tomcat也可以作web服务器,但其处理静态html的速度比不上apache,且其作为web服务器的功能远不如apache,因此我们想把apache和tomcat集成起来,将html与jsp的功能部分进行明确分工,让tomcat只处理jsp部分,其它的由apache,IIS等这些web服务器处理,由此大大节省了tomcat有限的工作"线程"。

    负载均衡实现的方式大概有四种:
        第一是通过DNS,但只能实现简单的轮流分配,不能处理故障,
        第二如果是基于MS IIS,Windows 2003 server本身就带了负载均衡服务,
        第三是硬件方式,通过交换机的功能或专门的负载均衡设备可以实现,
        第四种是软件方式,通过一台负载均衡服务器进行,上面安装软件。使用Apache Httpd Server做负载平衡器,Tomcat集群节点使用Tomcat就可以做到以上第四种方式。这种方式比较灵活,成本相对也较低。另外一个很大的优点就是可以根据应用的情况和服务器的情况采取一些策略。

    Tomcat4中可以通过修改minProcessors和maxProcessors的值来控制线程数。这些值在安装后就已经设定为默认值并且是足够使用的,但是随着站点的扩容而改大这些值。minProcessors服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载。也就是说,如果一天内每秒仅发生5次单击事件,并且每个请求任务处理需要1秒钟,那么预先设置线程数为5就足够了。但在你的站点访问量较大时就需要设置更大的线程数,指定为参数maxProcessors的值。maxProcessors的值也是有上限的,应防止流量不可控制(或者恶意的服务攻击),从而导致超出了虚拟机使用内存的大小。如果要加大并发连接数,应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。

    maxThreads
     Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。
     
    acceptCount//等待队列
     指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
     
    connnectionTimeout
     网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
     
    minSpareThreads//线程递增最小范围
     如果当前没有空闲线程,且没有超过maxThreads,一次性创建的空闲线程数量。Tomcat初始化时创建的线程数量也由此值设置。
     
    maxSpareThreads //线程递增最大范围
     一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。

    线程数可以大致上用 "同时在线人数*每秒用户操作次数*系统平均操作时间" 来计算。

    理解:tomcat在2个条件(没有空闲线程也没有超出maxthreads)下一次创建的空闲线程数量。
          TOMCAT需要启动一些线程来处理请求,就算没有请求,这些线程也不关闭(如果线程数量没有超过maxThreads)
          如果线程不够的话就要增加,但是每次增加不是增加一个而是一批,一批数量就是minSpareThreads到maxSpareThreads之间的取值。
       当仍没有超出maxThreads,且已经达到maxSpareThreads上限的时候(当所有可以使用的处理请求的线程数都被使用时), acceptCount取值为:可以放到处理队列中的请求数,如100。

      最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同,而且并不是所有人的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值。

     

     

     

  • 客户端生成多线程(一)~

    2007-08-02 09:07:00

    package autotest;

    import java.io.BufferedOutputStream;
    import java.io.IOException;

    public class PPPThread extends Thread{
         static ReadXml rx = new ReadXml("config/interface.xml");
         int threadId = -1;
         BufferedOutputStream ōut = null;
        
         public PPPThread(int threadId,BufferedOutputStream tmpOut) {
             this.threadId = threadId;
             this.out=tmpOut;
         }

         public void run() {
             System.out.println("threadId:"+threadId);
          //String tmp="GZ_HWSCP:1234@218.190.14.158:8088";
          String tmp="buddyv20:buddyv20@218.190.14.158:8088";
          //String tmp="buddyv20:buddyv20@10.17.42.96:8088";
             byte[] strByteArray;

       //----------
       String[] int_tmp;
          String test_type=rx.getItem("project","test_type");
          System.out.println("test_type:"+test_type);
          int_tmp=test_type.split(",");
          String xml_dir=null;
          String url=null;
          String files;
          String[] file_list;
               
          XmlSendClient mySend = new XmlSendClient();
          //openlog();
          for(int i=0;i<int_tmp.length;i++){
           url=rx.getItem("project/interface"+int_tmp[i],"url");
           System.out.println("url:"+url);
           xml_dir=rx.getItem("project/interface"+int_tmp[i],"xml_dir");
           System.out.println("xml_dir:"+xml_dir);
           files=rx.getItem("project/interface"+int_tmp[i],"files");
           System.out.println("files:"+files);
           file_list=files.split(",");
           XmlSendClient.setbnetID(rx.getItem("project/interface"+int_tmp[i],"bnetID"));
           XmlSendClient.setbnetAccount(rx.getItem("project/interface"+int_tmp[i],"bnetAccount"));
           XmlSendClient.setproductSpecID(rx.getItem("project/interface"+int_tmp[i],"productSpecID"));
           XmlSendClient.setproductInfo1(rx.getItem("project/interface"+int_tmp[i],"productInfo1"));
           XmlSendClient.setproductInfo2(rx.getItem("project/interface"+int_tmp[i],"productInfo2"));
           XmlSendClient.settimeStamp(rx.getItem("project/interface"+int_tmp[i],"timestamp"));
           XmlSendClient.setshareKey(rx.getItem("project/interface"+int_tmp[i],"shareKey"));
           for(int j=0;j<file_list.length;j++){
            System.out.println("Process the file : "+xml_dir+"/"+file_list[j]+".xml"); 
            mySend.SendXmlFile(url,xml_dir,file_list[j]+".xml",int_tmp[i]);
            System.out.println(" ------------SendXmlFile:"+file_list[j]+" over------------");
           }
           System.out.println(" ------------test_type:"+int_tmp[i]+" over------------");
          }
          System.out.println("Program over!");
          //closelog();
          System.exit(0);      
          
          //------------
          
          strByteArray = tmp.getBytes();
          
          try {
    //       Thread.sleep(100000);
                 this.out.write(strByteArray, 0, strByteArray.length);
                 this.out.flush();
             } catch (Exception ex) {
              ex.printStackTrace();
             }
         }
    }

  • 利用http协议走soap请求ws服务(二)~

    2007-08-02 09:05:37

    package autotest;

    import com.gsta.neva2.config.*;
    import java.lang.*;
    import java.util.Properties;

    public class ReadXml {

     public Configure myConfigure = new Configure();
     String filepath=null;

     public ReadXml(String path){
      this.filepath =path;
            System.out.println("filepath:"+filepath);
      
            try{
       myConfigure.parse(filepath);
      }catch(ConfigException ex){
       System.out.println(ex.getMessage());
      }
      
     }
     
     public String getItem(String tPath,String tNodeName){
      
      
      String tReturn="";
      
      try{
       tReturn = myConfigure.getItemValue(tPath, tNodeName);
      }catch(ConfigException ex){
       System.out.println(ex.getMessage());
      }
      return tReturn;
     }
     public String getItemprop(String tfieldNode,String tfieldValue){
      
      
      String tReturn="";
      
      try{
       tReturn = myConfigure.getItemProp(tfieldNode,tfieldValue);
      }catch(ConfigException ex){
       System.out.println(ex.getMessage());
      }
      return tReturn;
     }

    }

  • 利用http协议走soap请求ws服务(一)~

    2007-08-02 09:03:54

    package autotest;

    import java.io.*;
    import java.net.*;
    import java.io.BufferedReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import autotest.*;


    // 系统主要函数,功能:发送xml文件到接口,然后接收接口返回消息,并打印消息中的相关信息
    public class XmlSendClient {
     
     static FileWriter fw=null;
     static PrintWriter ōutlog=null;
     static ReadXml rx = new ReadXml("config/interface.xml");
     ReadProxy myProxy = new ReadProxy();
     static String productSpecID=null;
     static String bnetId=null;
     static String timestamp=null;
     static String bnetAccount=null;
     static String productInfo1=null;
     static String productInfo2=null;
     static String shareKey=null;
     
     @SuppressWarnings("static-access")
     public void SendXmlFile(String url_wsdl,String xml_path,String xml_file,String interface_index){

            String SOAPUrl=url_wsdl;
            String xmlFile2Send=xml_path+"/"+xml_file;
            //System.out.println("xmlFile2Send:"+xmlFile2Send);
      String SOAPAction = "";

      try{
    //   设置IE代理:
    //   System.getProperties().put("proxySet", "true");
    //   System.getProperties().put("proxyHost", "xx.xx.xx.xx");
    //         System.getProperties().put("proxyPort", "8080");
    //         String authString="xxxxxxxx:xxxxxxxx";
    //   String auth="Basic"+new sun.misc.BASE64Encoder().encode(authString.getBytes()); 
       // 建立同接口之间的连接,以备发送接口文件。
             URL url = new URL(SOAPUrl);
            
             URLConnection connection = url.openConnection();
    //         connection.setRequestProperty("Proxy-Authorization",auth);
             System.out.println("urlconnetction:"+connection);
             HttpURLConnection httpConn = (HttpURLConnection) connection;
             System.out.println("httpurlconnection:"+httpConn);
             httpConn.setFollowRedirects(true);
             httpConn.setInstanceFollowRedirects(true);
             httpConn.usingProxy();
            
            
             // 打开输入的接口xml文件
             FileInputStream fin = new FileInputStream(xmlFile2Send);
             // 初始一个空的字节输出流
             ByteArrayOutputStream bout = new ByteArrayOutputStream();
             copy(fin,bout);
             fin.close();
            
             byte[] b =null;
             // 进行模板的参数替换
             b=getReplace(bout,interface_index,xml_file);
            
             // 设置HTTP参数

             httpConn.setRequestProperty("Content-Length",String.valueOf(b.length));
             httpConn.setRequestProperty("Content-Type","text/xml; charset=UTF-8");
       httpConn.setRequestProperty("SOAPAction",SOAPAction);
             httpConn.setRequestMethod( "POST" );
             httpConn.setDoOutput(true);
             httpConn.setDoInput(true);
             // 发送接口文件,发送完毕后关闭输出流
             OutputStream ōut = httpConn.getOutputStream();
             out.write(b);   
             out.close();
            
             // 从对话通道中读取接口返回信息。
             System.out.println("xml_file:"+xml_file);
             //outlog.println("------"+xml_path+"------");
             InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
             BufferedReader in = new BufferedReader(isr);
             String inputLine;
            
             int int_start;
             int int_end;
             int int_start_info;
             int int_end_info;
             String str_inputLine="";
            
             // 不断循环从通道中读取返回信息,直至读取为空
       while ((inputLine = in.readLine()) != null){
        str_inputLine=str_inputLine+inputLine;
        System.out.println("inputLine:"+inputLine);
        System.out.println("str_inputLine:"+str_inputLine);
       }
       
       // 打印resultNo节点的信息
       int_start=str_inputLine.indexOf("ns2:result");
       int_end=str_inputLine.indexOf("/ns2:result");
       if(str_inputLine.indexOf("ns2:result")>=0){
        //outlog.println("xml_file:"+xml_file);
        System.out.println("result: "+str_inputLine.substring(int_start+50,int_end-1));
       }
     
       // 当resultNo的值不为0时,还需打印resultInfo信息,以供查问题
       int_start_info=str_inputLine.indexOf("ns3:info");
       int_end_info=str_inputLine.indexOf("/ns3:info");
       if(str_inputLine.indexOf("ns2:result")>=0){
        if(str_inputLine.indexOf(">0<")<0){
         System.out.println("info:"+str_inputLine.substring(int_start_info+48,int_end_info-1));
        }
       }
       //outlog.println();
      }catch(Exception ex){
             ex.printStackTrace();
             outlog.println(xml_file+" : this file is failed!");
             outlog.println();
            }
        }
     
        private boolean hasProxy() {
      // TODO Auto-generated method stub
      return false;
     }

     // 同步拷贝文件流到字节输出流,并保证在拷贝过程中,这两个流不受其他线程影响
        public void copy(InputStream in, OutputStream out) throws IOException {
           synchronized (in) {
           synchronized (out) {
             byte[] buffer = new byte[256];
             while (true) {
               int bytesRead = in.read(buffer);
               if (bytesRead == -1) break;
               out.write(buffer, 0, bytesRead);
             }
           }
         }
        }
       
        // 打开写日志的文件
        static void openlog(){
         try {
          fw = new FileWriter("interface_test.log");
          outlog = new PrintWriter(fw);
      } catch (IOException e) {
       e.printStackTrace();
      }
        }
       
        // 关闭写日志文件的句柄
        static void closelog(){
         
         try {
          outlog.println("Program has executed successfully!");
          outlog.close();
          fw.close();
      } catch (IOException e) {
       e.printStackTrace();
      }
        }

       
        // 更换接口文件模板中,需要更换的节点值
        public byte[] getReplace(ByteArrayOutputStream b,String inter_index,String xml_file){
         String tmp1=b.toString();
         String inputValue1=null;
         
          tmp1=tmp1.replace("bnetid_String",getbnetID());
             tmp1=tmp1.replace("bnetAccount_String",getbnetAccount());
             tmp1=tmp1.replace("productSpecID_String",getproductSpecID());
             tmp1=tmp1.replace("productInfo_String",getproductInfo1());
             tmp1=tmp1.replace("timestamp_String",gettimeStamp());
          if (xml_file.endsWith("order.xml")){
    //       System.out.println(getbnetID());
    //       System.out.println(getbnetAccount());
    //       System.out.println(getproductSpecID());
    //       System.out.println(getproductInfo1());
    //       System.out.println(gettimeStamp());
    //       System.out.println("getshareKey:"+getshareKey());
           inputValue1 = MD5Crypter.encode(getbnetID()+getbnetAccount()+getproductSpecID()+getproductInfo1()+gettimeStamp()+getshareKey());
           System.out.println("order hashcode:"+inputValue1);
           tmp1=tmp1.replace("hashCode_String",inputValue1);
           tmp1.trim();
           System.out.println("order tmp1:"+tmp1);
           return tmp1.getBytes();
          }else if(xml_file.endsWith("modify.xml")){
                 tmp1=tmp1.replace("productInfo_String",getproductInfo2());
           inputValue1 = MD5Crypter.encode(getbnetID()+getproductSpecID()+getproductInfo2()+gettimeStamp()+getshareKey());
           System.out.println("modify hashcode:"+inputValue1);
           tmp1=tmp1.replace("hashCode_String",inputValue1);
           return tmp1.getBytes();
          }else if(xml_file.endsWith("cancel.xml")){
           inputValue1 = MD5Crypter.encode(getbnetID()+getproductSpecID()+gettimeStamp()+getshareKey());
           System.out.println("cancel hashcode:"+inputValue1);
           tmp1=tmp1.replace("hashCode_String",inputValue1);
           return tmp1.getBytes();
          }
      //};
     return null;
    }

     //获得bnetID
        static String getbnetID(){
         //System.out.println("getbnetId:"+bnetId);
         return bnetId;
        }
        static void setbnetID(String tmp_bnetId){
         bnetId=tmp_bnetId;
         //System.out.println("setbnetid:"+bnetid);
        }
        static String getbnetAccount(){
         //System.out.println("getbnetAccount:"+bnetAccount);
         return bnetAccount;
        }
       
        // 当前接口循环中,给外部公用的帐号名称变量赋值,以供取值使用
        static void setbnetAccount(String tmp_bnetAccount){
         bnetAccount=tmp_bnetAccount;
         //System.out.println("setbnetAccount:"+bnetAccount);
        }
       
        static String getproductInfo1(){
         //System.out.println("getproductInfo1:"+productInfo1);
         return productInfo1;
        }
       
        //当前接口循环中,给外部公用的帐号名称变量赋值,以供取值使用
        static void setproductInfo1(String tmp_productInfo1){
         productInfo1=tmp_productInfo1;
         //System.out.println("setproductInfo1:"+productInfo1);
        }
       
        static String getproductInfo2(){
         //System.out.println("getproductInfo2:"+productInfo2);
         return productInfo2;
        }
       
        //当前接口循环中,给外部公用的帐号名称变量赋值,以供取值使用
        static void setproductInfo2(String tmp_productInfo2){
         productInfo2=tmp_productInfo2;
         //System.out.println("setproductInfo2:"+productInfo2);
        }
           
        // 取得当前接口循环中,外部公用的帐号名称
        static String getproductSpecID(){
         //System.out.println("getproductSpecID:"+productSpecID);
         return productSpecID;
        }
           
        // 当前接口循环中,给外部公用的帐号名称变量赋值,以供取值使用
        static void setproductSpecID(String tmp_productSpecID){
         productSpecID=tmp_productSpecID;
         //System.out.println("setproductSpecID:"+productSpecID);
        }
        static String gettimeStamp(){
         //System.out.println("gettimestamp:"+timestamp);
         return timestamp;
        }
          
        static void settimeStamp(String tmp_timestamp){
         timestamp=tmp_timestamp;
         //System.out.println("settimeStamp:"+timestamp);
        }
        static String getshareKey(){
         //System.out.println("getshareKey:"+shareKey);
         return shareKey;
        }
          
        static void setshareKey(String tmp_shareKey){
         shareKey=tmp_shareKey;
         //System.out.println("setshareKey:"+shareKey);
        }
       
        // 主程序入口
        public static void main(String[] args){
         String[] int_tmp;
         String test_type=rx.getItem("project","test_type");
         System.out.println("test_type:"+test_type);
         int_tmp=test_type.split(",");
         String xml_dir=null;
         String url=null;
         String files;
         String[] file_list;

         XmlSendClient mySend = new XmlSendClient();
         //openlog();
         for(int i=0;i<int_tmp.length;i++){
          url=rx.getItem("project/interface"+int_tmp[i],"url");
          System.out.println("url:"+url);
          xml_dir=rx.getItem("project/interface"+int_tmp[i],"xml_dir");
          System.out.println("xml_dir:"+xml_dir);
          files=rx.getItem("project/interface"+int_tmp[i],"files");
          System.out.println("files:"+files);
          file_list=files.split(",");
          mySend.setbnetID(rx.getItem("project/interface"+int_tmp[i],"bnetID"));
          mySend.setbnetAccount(rx.getItem("project/interface"+int_tmp[i],"bnetAccount"));
          mySend.setproductSpecID(rx.getItem("project/interface"+int_tmp[i],"productSpecID"));
          mySend.setproductInfo1(rx.getItem("project/interface"+int_tmp[i],"productInfo1"));
          mySend.setproductInfo2(rx.getItem("project/interface"+int_tmp[i],"productInfo2"));
          mySend.settimeStamp(rx.getItem("project/interface"+int_tmp[i],"timestamp"));
          mySend.setshareKey(rx.getItem("project/interface"+int_tmp[i],"shareKey"));
          for(int j=0;j<file_list.length;j++){
           System.out.println("Process the file : "+xml_dir+"/"+file_list[j]+".xml"); 
           mySend.SendXmlFile(url,xml_dir,file_list[j]+".xml",int_tmp[i]);
           System.out.println(" ------------SendXmlFile:"+file_list[j]+" over------------");
          }
          System.out.println(" ------------test_type:"+int_tmp[i]+" over------------");
         }
         System.out.println("Program over!");
         //closelog();
         System.exit(0);
         
        }
    }

  • 性能测试的一些思路(三)~

    2007-08-02 09:01:58

    查找瓶颈时按以下顺序,由易到难。

        服务器硬件瓶颈-〉网络瓶颈(对局域网,可以不考虑)-〉服务器操作系统瓶颈(参数配置)-〉中间件瓶颈(参数配置,数据库,web服务器等)-〉应用瓶颈(SQL语句、数据库设计、业务逻辑、算法等)

        注:以上过程并不是每个分析中都需要的,要根据测试目的和要求来确定分析的深度。对一些要求低的,我们分析到应用系统在将来大的负载压力(并发用户数、数据量)下,系统的硬件瓶颈在哪儿就够了。
       
    服务器在不受压情况下,内存占用率最佳为25%,多了影响服务器性能;
    压力负载测试中也需要注意:
    1、注意区别内存泄露和动态内存分配问题;
    2、注意压力端和服务器端的网络流量,一般来说目前的网络不会是系统的瓶颈,但是也需要注意;
    3、单机的压力用户数不要过多,否则会影响测试结果,最好不要超过300;
    4、分不同的组来运行不同的事务脚本,应真实的模拟系统情况;

    -----------
    网络时间是从发出第一个http请求到收到ACK的时间。
    服务器时间是从收到ACK到第一个字节返回的时间。
    ACK是TCP首部中的确认标志,对已接受到的TCP报文进行确认。

    -----------
    压力系统必须超越功能测试,要同时遍历多条代码路径。至于怎么做到这一点取决于具体的产品。例如,一个 Web 服务压力测试需要一次模拟多个客户机。Web 服务(或者任何多线程代码)通常会访问多个线程实例间的一些共享数据。因额外方面的编程而增加的复杂性通常意味着代码会具有许多因并发引起的错误。由于引入并发性意味着一个线程中的代码有可能被其他线程中的代码中断,所以错误只在一个指令集以特定的顺序(例如以特定的定时条件)执行时才会被发现。把这个原则与重复原则结合在一起,您可以应用许多代码路径 和定时条件。

    -----------
    频率*时间=端口数
    这个公式可以延伸到很多额定的场景内。

    -----------
    应用服务器都通过线程去处理相应的请求,不管容量规划也好,不管做性能测试也好,都要找到比较根本的源头,这里指出的是:线程数(端口)。   

  • 性能测试的一些思路(二)~

    2007-08-02 09:01:12

    3、交易成本分析
    1) 使用和站点概况
    A. 在线使用概况
    下表列出了本文中项目组所用的在线使用概括。 峰值乘数用于计算与平均负载有关的系统的最大容量。 如果每秒钟的平均请求数量是 150 ,如果您的峰值乘数是 3 的话那么预期峰值将会是每秒钟 150 次请求。 为了对实施进行容量规划,您应当为系统的峰值容量做规划。
    描述 值
    会话的平均时间 7 分钟(420 秒)
    峰值乘数 3x 平均值
    每个用户每次访问的请求数 141
    由“业务话务模型”可知,User1:Use+login+fax+sms+ctd+cfcc 各模块最大时长是120S,因此sms100条/S*120=12,000,平均时间约为:7分钟(420S)。

    B. 事务比例选取
    对于行业应用,测试数据的准备中最重要的就是事务的选取,由于去年全年处理业务(传真\短信\视频会议)约3万笔,按照以上从业务比例(4/4/2)抽取每个客户类型的事务比例:
    比例的分布:
    操作 分布权重 发送比例 每个操作的请求数 每个会话的请求数 标准化 
    定购(ws)  0.05 30000*0.05 1 1 164*0.05 Ws:canuse
    请求使用 0.05 30000*0.05 1 1 164*0.05 
    登录 0.10 30000*0.1 1 2 164*0.1 Login->logout
    发送传真 0.20 30000*0.20 60 3+3+60 164*0.2 Osap->pxy->comp->sip
    已发/接收传真 0.03 30000*0.03 2 2 164*0.03 Osap->pxy->comp->
    发送短信 0.20 30000*0.20 120/2=60 3+2+60 164*0.2 Osap->pxy->comp->sc
    已发/接收短信 0.05 30000*0.05 2 2 164*0.05 Osap->pxy->comp->
    点击拨号 0.20 30000*0.20 1.5秒/次:
    40/1.5=
    26.7次 3+2+27 164*0.2 Osap->pxy->comp->ctd
    发起会议 0.09 30000*0.09 18 3+2+18 164*0.09 Osap->pxy->comp->ipunity
    定制语音流程 0.03 30000*0.03 3 3+3 164*0.03 Osap->pxy->comp->->sip
    总计 1  159 164 164 
    其中 分布权重 一栏给出某类操作占总请求数的百分比。
    其中 标准化 一栏表示分布权重乘以每用户每次访问请求数得到的结果。 注意这一栏合计达164。
    其中 每个操作的请求数 一栏给出了执行某一操作所用的用户请求数量。 由于回帖或服务器重定向等原因,有些操作会产生多个请求。
    其中 每个会话的请求数 一栏给出了用户在每次会话中发起的对某一操作的请求数量。

    2) 使用TCA 方法进行容量规划
    A. 测试强度估算:
    测试强度估算时采用如下假设前提:
    *全年的业务量集中在10个月完成,每个月20个工作日,每个工作日8个小时;
    *采用80—20原理,每个工作日中80%的业务在20%的时间内完成,即每天80%的业务在1.6小时内完成;
    测试压力的估算结果:
    按照3万笔业务每用户每次访问的164请求数,每7分钟一次会话计算。
    根据以往统计结果,其中,假设早上9点及下午15点为高峰期,须按照2个小时段的业务处理量。
    每年总的请求数量为:30000*140=4,200,000次/年=420万次/年。
    系统平均每天的请求数量为:4200000/200=21,000次/日
    系统平均每分钟的处理数量为:(30000*80%)/(200*8*20%)=75笔/时=1.25笔/分钟请求;
    系统平均每秒的请求数量为:(21,000*80%)/(8*20%*3600)=16800/5760=2.93次/秒。
    正常情况下,应用服务器平均处理请求数的能力至少应达到:2.93次/秒。
    (某种程度上,可认为请求数量约等于交易数量)
    B. 用户频率成本估算:
    发送传真频率:63 (每个会话的请求数 )/ (7分钟*60秒*0.2分布权重) =0.7 每个用户每秒钟的请求数。.
    操作 前:后(1:1)比例所占COMP的执行时间(秒) 各模块对应权重下每秒钟每事务次数 
    定购(ws)    
    请求使用   
    登录   
    发送传真 63/3=21 63/(450*0.2)=0.7
    3/0.7=4.3 当传真在会话中耗时450*0.2/4.3=21秒时,CPS=3
    已发/接收传真   
    发送短信 62/12000=0.05 62/(450*0.2)=0.69
    1200/0.69=1450 450*0.2/145=0.62秒时,CPS=100
    已发/接收短信   
    点击拨号 29/60=0.48 29/(450*0.2)=0.32
    60/0.32=188 450*0.2/188=0.48秒时,CPS=60
    发起会议 20/0.2=100 20/(450*0.2)=0.22
    0.2/0.22=0.9 450*0.2/0.9=100秒时,CPS=0.2
    定制语音流程   
    总计   

    C. 根据频率计算最大并发用户数:
    1、 根据公式:CPS*会话平均执行时间=同时运行用户数(同时运行最大端口数)
    30000(多用户单次会话): 2.93*420=1218 (并发用户)
    1(单用户单次会话):0.3334*420=140.028 (同时运行中用户)
    3) 结论
    确认:CPU 的利用率约为百分之75左右时,请求频率是否达到2.93次/秒,同时吞吐量为xxx (bytes);
    这相当于预定使用方案中所定的 1218名并发模拟用户的情况。
    通过以上理论值计算,3万笔处理量将满足现行的硬件配置及部署。当需要扩充业务量或系统业务变更的时候,也需要遵循以上计算模式,线性扩充硬件配置及部署。

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

     

  • 错误代码

    2007-08-02 00:02:33

    4.400 Invalid syntax. 语法问题
    401 Access denied. 访问拒绝
    402 Payment required. 必须完整
    403 Request forbidden. 请求被禁止
    404 Object not found. 对象没有找到
    405 Method is not allowed. 方法不允许
    406 No response acceptable to client found. 客户端没有响应
    407 Proxy authentication required. 代理需要验证
    408 Server timed out waiting for request. 等等请求时服务器断开连接
    409 User should resubmit with more info. 有冲突用户应该进行检查
    410 Resource is no longer available. 资源不可用
    411 Server refused to accept request without a length. 服务器拒绝接受没有长度的请求
    412 Precondition given in request failed. 放弃请求失败的条件
    413 Request entity was too large. 请求太大
    414 Request Uniform Resource Identifier (URI) too long. 请求的URI 太长
    415 Unsupported media type. 不支持MEDIA类型
    449 Retry after doing the appropriate action. 在作了适当动作后重试
    500 Internal server error. 服务器内部错误
    501 Server does not support the functionality required to fulfill the request. 服务器不支持请求的功能
    502 Error response received from gateway. 从网关收到错误应答
    503 Temporarily overloaded. 过载
    504 Timed out waiting for gateway. 等待网关时请求断开
    505 HTTP version not supported. 不支持HTTP的版本

    HTTP status codes returned by servers on the Internet.
    从Internet返回的HTTP status代码(HTTP 状态字)
    HTTP_STATUS_CONTINUE (100)
    The request can be continued.
    请求不能被继续
    HTTP_STATUS_SWITCH_PROTOCOLS (101)
    The server has switched protocols in an upgrade header.
    通过新的header服务器的协议被转换了
    HTTP_STATUS_OK (200)
    The request completed successfully.
    请求成功的完成
    HTTP_STATUS_CREATED (201)
    The request has been fulfilled and resulted in the creation of a new resource.
    通过新的资源请求已经被完成
    HTTP_STATUS_ACCEPTED (202)
    The request has been accepted for processing, but the processing has not been completed.
    请求已经被接受处理,但是处理还没有完成
    HTTP_STATUS_PARTIAL (203)
    The returned meta information in the entity-header is not the definitive set available from the origin server.
    从服务器返回的在entity-header中的meta信息是无效的
    HTTP_STATUS_NO_CONTENT (204)
    The server has fulfilled the request, but there is no new information to send back.
    服务器实现了请求,但是没有返回信息
    HTTP_STATUS_RESET_CONTENT (205)
    The request has been completed, and the client program should reset the document view that caused the request to be sent to allow the user to easily initiate another input action.
    请求已经被完成,并且web程序(客户端程序浏览器程序)已经重置了文档视图目录(content),这个目录很容易允许使用者用另一个动作发送请求
    HTTP_STATUS_PARTIAL_CONTENT (206)
    The server has fulfilled the partial GET request for the resource.
    服务器已经为资源完成了部分GET请求
    HTTP_STATUS_AMBIGUOUS (300)
    The server couldn't decide what to return.
    服务器不能判定返回什么
    HTTP_STATUS_MOVED (301)
    The requested resource has been assigned to a new permanent URI (Uniform Resource Identifier), and any future references to this resource should be done using one of the returned URIs.
    被请求的资源已经被分配给新的URI,并且以后引用时都使用这个URIs资源。
    HTTP_STATUS_REDIRECT (302)
    The requested resource resides temporarily under a different URI (Uniform Resource Identifier).
    请求的资源临时在不同的uri下
    HTTP_STATUS_REDIRECT_METHOD (303)
    The response to the request can be found under a different URI (Uniform Resource Identifier) and should be retrieved using a GET HTTP verb on that resource.
    请求的资源不能在不同的uri下找到,并且从新使用GET HTTP在服务器上从新检索
    HTTP_STATUS_NOT_MODIFIED (304)
    The requested resource has not been modified.
    请求的资源没有被改变
    HTTP_STATUS_USE_PROXY (305)
    The requested resource must be accessed through the proxy given by the location field.
    请求的资源必须通过特定的代理获得
    HTTP_STATUS_REDIRECT_KEEP_VERB (307)
    The redirected request keeps the same HTTP verb. HTTP/1.1 behavīor.
    从定位请求,
    HTTP_STATUS_BAD_REQUEST (400)
    The request could not be processed by the server due to invalid syntax.
    因为语法不能被服务器处理
    HTTP_STATUS_DENIED (401)
    The requested resource requires user authentication.
    请求资源命令必须被验证(拒绝访问)
    HTTP_STATUS_PAYMENT_REQ (402)
    Not currently implemented in the HTTP protocol.
    没有完全实现HTTP协议
    HTTP_STATUS_FORBIDDEN (403)
    The server understood the request, but is refusing to fulfill it.
    服务器理解了请求,但是拒绝完成他
    HTTP_STATUS_NOT_FOUND (404)
    The server has not found anything matching the requested URI (Uniform Resource Identifier).
    没有找到任何被指定的URI

    HTTP_STATUS_BAD_METHOD (405)
    The HTTP verb used is not allowed.
    Http动作不被允许
    HTTP_STATUS_NONE_ACCEPTABLE (406)
    No responses acceptable to the client were found.
    应答没有被客户接受
    HTTP_STATUS_PROXY_AUTH_REQ (407)
    Proxy authentication required.
    代理必须被验证
    HTTP_STATUS_REQUEST_TIMEOUT (408)
    The server timed out waiting for the request.
    服务器在等待请求时中止了
    HTTP_STATUS_CONFLICT (409)
    The request could not be completed due to a conflict with the current state of the resource. The user should resubmit with more information.
    请求不能被完成,问题是资源冲突。用户应该进行调整
    HTTP_STATUS_GONE (410)
    The requested resource is no longer available at the server, and no forwarding address is known.
    请求的资源在服务器上不再可用,而且没有转发地址
    HTTP_STATUS_LENGTH_REQUIRED (411)
    The server refuses to accept the request without a defined content length.
    服务器拒绝接受没有定义目录大小的请求
    HTTP_STATUS_PRECOND_FAILED (412)
    The precondition given in one or more of the request header fields evaluated to false when it was tested on the server.
    当在服务器上测试请求头文件放弃一个或者多个请求的条件
    HTTP_STATUS_REQUEST_TOO_LARGE (413)
    The server is refusing to process a request because the request entity is larger than the server is willing or able to process.
    服务器拒绝处理请求,原因是请求的大小超过服务器能够处理的大小
    HTTP_STATUS_URI_TOO_LONG (414)
    The server is refusing to service the request because the request URI (Uniform Resource Identifier) is longer than the server is willing to interpret.
    服务器拒绝服务,原因是请求的URI超过了服务器能够揭示的长度
    HTTP_STATUS_UNSUPPORTED_MEDIA (415)
    The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.
    服务器拒绝服务,原因是请求格式不被支持
    HTTP_STATUS_RETRY_WITH (449)
    The request should be retried after doing the appropriate action.
    在作了适当的动作后请求被重试
    HTTP_STATUS_SERVER_ERROR (500)
    The server encountered an unexpected condition that prevented it from fulfilling the request.
    服务器遇到请求失败意外
    HTTP_STATUS_NOT_SUPPORTED (501)
    The server does not support the functionality required to fulfill the request.
    服务器不支持必须完成请求的功能
    HTTP_STATUS_BAD_GATEWAY (502)
    The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request.
    服务器当作为网关或代理时,从上行服务器接受的响应请求失败
    HTTP_STATUS_SERVICE_UNAVAIL (503)
    The service is temporarily overloaded.
    服务器负载
    HTTP_STATUS_GATEWAY_TIMEOUT (504)
    The request was timed out waiting for a gateway.
    等待网关时请求断开,没有响应
    HTTP_STATUS_VERSION_NOT_SUP (505)
    The server does not support, or refuses to support, the HTTP protocol version that was used in the request message.
    服务器不支持或者拒绝支持正在使用请求的HTTP协议的版本

  • 记忆的碎片-汇总

    2007-08-02 00:01:24

    1、报错:Server redirected too many  times (20)

    查了很多资料,怀疑是jdk1.5的bug
    程序背景:通过http协议走的ws请求。重定向是http协议支持的标准。
    jdk1.3中有描述解决 redirects =5的问题,且重定向个数在1.4版本中运用没问题。

    提示:重定向太多次(20)
    后来发现:去掉代码里的代理服务器设置就好了。

    2、java.net.SocketException: No buffer space available (maximum connections reached?): recv failed
     at java.net.SocketInputStream.socketRead0(Native Method)
     at java.net.SocketInputStream.read(Unknown Source)
     at java.io.BufferedInputStream.fill(Unknown Source)
     at java.io.BufferedInputStream.read1(Unknown Source)


    在多线程并发过程中,会报以上错误,怀疑是连接请求次数过多导致,同一请求至多3个线程同时处理能力。
    后来发现:
    去掉程序中的代理服务器代码即可。


    3、error_code : 407
       Proxy Authentication Required

       504:
       Gateway Timeout

    4、某些表执行速度很慢,相对相同的另一个库。
    执行计划中表分析的一些方法:
    ANALYZE TABLE T_IVR_BILL ESTIMATE STATISTICS SAMPLE 10 percent;

    5、内存溢出或内存缺报错:
    加入gc日志监控以及MaxPermSize大小:
    JAVA_OPTS="-XX:MaxPermSize=256m -Xloggc:./gclog.log -Xms256m -Xmx1024m

    http://www.matrix.org.cn/thread.shtml?topicId=37096&forumId=1
    62.708: [GC 94686K->11549K(325760K), 0.0383360 secs

    6、现象:

    1、基本在上传文件、提交等场景。
    2、并发压力比较大的话,2个小时后,tomcat报内存溢出。
    3、压力不大的前提下,场景持续运行时间较长,基本要3天以上。
    4、内存值明显增长,到2G后报错。
    5、tomcat+tapestry+oracle

    解决办法是:到应用里面的WEb-INF下的lib,更新2个jar包。
    commons-fileupload-1.1.1.jar
    commons-io-1.2.jar
    为最新版本

     

     

  • 性能测试的一些思路(一)~

    2007-08-01 23:55:20

    测试目标:
    测试过程是否满足以上过程指标及最终的需求指标;
    及如何通过结合2者指标评估出被测系统及上线环境的线性对比指标;
    最后得到系统的性能、可扩展性、可用性等测试结论。

    测试步骤:
    1) 基准测试:分步测试。测试结果是一致的且可重现。测试环境一直处在相同的高负载下进行。
    2) 容量规划测试:系统测试。容量规划在测试需求阶段就需要从设计获取了,详见附件《性能指标容量规划.DOC》。如果要确定系统的容量,需要考虑几个因素。这些用户中有多少是并发与服务器通信的,其次是,每个用户的"考虑时间"即请求时间是多少,以及本次请求服务通信总响应的时间是多少,等等。通过用户考虑时间+服务器响应时间=场景总运行时间,且通过调整各参数及随机因子(利用"调步"的理念向负载场景中引入更多的随机性),换算出最大及最优同时并发用户数。接着引入ramp-up测试及flat测试不断微调。
    3) 峰谷测试:系统测试。峰谷测试通过一系列的快速ramp-up测试,继之以一段时间的平稳状态(取决于业务需求),然后急剧降低负载,然后再进行快速的ramp-up;反复重复这个过程。这样可以确定以下事项:
    第二次高峰是否重现第一次的峰值?
    其后的每次高峰是等于还是大于第一次的峰值?
    在测试过程中,系统是否显示了内存或GC(内存释放)性能降低的有关迹象?
    测试运行(不停地重复"峰值/空闲"周期)的时间越长,系统的性能越被了解。 
    4) 渗入测试:系统测试。渗入测试所需时间较长,也叫疲劳测试。渗入测试以2端负载通过低负载/高负载运行较长时间,即运行两次测试,一次使用较低的用户负载(要在系统容量之下,以便不会出现执行队列),一次使用较高的负载(以便出现积极的执行队列)。
    测试所需指标:
    1、 获取各WEB服务的性能指标,包括 WEB SERVER的性能(包括线程数(为了给执行队列决定一个理想的线程数,当队列中所有应用程序都运行在最大负荷的情况下,监视队列的吞吐量。增加线程数,重复负载测试,直到达到最佳的吞吐量。(在某些情况下,增加线程数将产生足够多的上下文转换程序,使得队列中的吞吐量开始减少。))、最大并发数、最优并发数、TPS);
    ---最佳线程数(调整并满足既定的配置数,详见2.2硬件环境描述)
    ---最佳吞吐量 for server (tomcat/sip/oracle)
    ---响应时间 for case(OSAP/PXYWEB/xxxCOMP/WEB SERVICES)
    ---最大同时并发用户数 for osap
    ---最佳同时并发用户数 for osap
    ---最佳用户数下的TPS for case(OSAP/PXYWEB/xxxCOMP/WEB SERVICES)
    2、 能力组件性能
    ---最大并发用户数下的CPS for case(xxxCOMP)
    ---最佳线程数(调整并满足既定的配置数,详见2.2硬件环境描述)
    ---最佳吞吐量 for server (tomcat)
    ---响应时间 for case(xxxCOMP)
    ---最大同时并发用户数 for case(xxxCOMP)
    ---最佳同时并发用户数 for case(xxxCOMP)
    3、 应用服务(SIPSVR)的性能指标:
    ---最佳线程数
    ---最佳吞吐量 for case5
    ---CPS for case2/case5
    4、 后置指标:
    ---各服务器的CPU占用百分比(基准测试/容量规划测试/渗入测试)
    ---各服务器的Memory平均占用比例 (基准测试/容量规划测试/渗入测试)
    (例如,如果想知道增加JVM内存是否会影响应用程序的性能,就逐次递增JVM内存(例如,从1024 MB增至1224 MB,然后是1524 MB,最后是2024 MB),在每个阶段收集结果和环境数据,记录信息,然后到下一阶段。)

    容量规划
    前提(测试结果有效的先决条件):
    1、 web/sip/oracle/第三方后台服务器配置满足建设方案标准配置或以上;

    2、 系统正常工作时,用户访问系统的基本性能需求如下:
    1) 软终端用户登录时间<= 3秒
    2) WEB终端用户页面初始化操作<= 3秒
    3) WEB接入的系统响应时间:在带宽足够的情况下,用户点击访问页面时间不超过3秒,请求提交响应时间最大不超过5秒;
    4) 系统一般性操作最长时间<= 2秒
    5) 用户操作界面友好,交互性强,在出现错误时,应能显示错误提示信息,并且错误信息能够被用户取消,并恢复界面正常显示。

    3、 根据项目一期设计,系统建设要求满足3万用户需求,业务话务模型如下:
    1) 点击拨号
    按最大CAPS为60计算,普通用户的通话时长为60秒,媒体服务器为主叫放音时长为30秒。
    2) 网络传真
    按最大CAPS为3计算,每个呼叫时长为120秒,媒体服务器话音提示时长为15秒。
    3) Web会议
    按最大CAPS为0.2计算,每次会议保持时长为120秒,会议方数为5方,40%用户存在数据协同会议需求。
    4) 短信
    短信按每秒100条计算。
    5) 电话总机
    按最大CAPS为0.5计算,每个呼叫时长为90秒。

    4、 九的个数和时间之间的对应关系。
    可接受的运行时间百分比 每天的停机时间 每月的停机时间 每年的停机时间
    95 72.00 分钟 36 小时 18.26 天
    99 14.40 分钟 7 小时 3.65 天
    99.9 86.40 秒钟 43 分钟 8.77 小时
    99.99 8.64 秒钟 4 分钟 52.60 分钟
    99.999 0.86 秒钟 26 秒钟 5.26 分钟


    5、业务比例选取:
     “xx”平台用户主要针对中小企业用户,按照约有3万企业用户,xx商业客户分类如下:
    客户类型 客户员工规模 客户数量 比率
    1-2线客户 约3-10人 135万 86%
    3-10线客户 约10-100人 19.5万 12%
    10线以上客户 约20-500人 2.2万 2%
     按以上比例,3万用户中,2.58万为1-2线用户,3600为3-10线用户,600为10线以上用户。

    企业用户数:25800*2+3600*10+600*10=93600=9.4万
    如果再考虑未来几年的交易量的增加(每年增长15%),则可以归纳为:
    类型 第一年(万) 第二年(万) 第三年(万) 第四年(万) 合计(万)
    企业客户 3.45 3.97 4.56 5.25 17.23
    企业
    用户 10.81 12.43 14.30 16.44 53.98

    6、压力分解:
    对于一个由很多环节组成的复杂系统来说,如果想要模拟实际环境进行整体的联合性能测试的话,就需要针对整体压力进行各个层次的分解。
    例如:后台系统CPS是60次/秒,由于接口网关和后台主机在此环境中是1对1的关系,所以接口网关的压力要达到60次/秒。而一个接口网关对应着三个前置机,所以每个前置机要达到20次/秒送达主机的吞吐量,才可能使整个系统满负荷运转。考虑到其它层次类推。由于主机以外还存在其它服务系统,所以在前置机的压力上面加了一个“X”代表其它服务系统要求的压力。当某个层次的设备短缺,无法实际上达到其分解下来的压力时,往往需要使用软件手段,在上一层次上直接加压力解决。

    性能监控

    利用容器的管理界面,分析最大线程数、并发线程数(最优并发用户数)
    每秒钟运行成功的交易数量(TPS/CPS)
    Web 服务\Get 请求/秒(TPS)
    后台服务请求频率(CPS)
    单一客户端的响应时间(使用时间戳的差值,发出请求的时间和收到回应的时间)
    请求的执行时间(RPT:事务响应时间)
    网络流量占用率(最佳吞吐量)
    各服务器的CPU占用百分比(SHELL)
    内存的占用率(SHELL)
    硬盘使用率

  • 服务器的一些备忘

    2007-08-01 11:11:32

    IBM P 系列的小型机,应该安装IBM的  AIX 操作系统,其中,P520、P570 是可以安装 Linux 的,其他的,应该不行。
    SUN SPARC 体系结构的小型机,只有 Solaris、Linux 可以安装,一般都是安装的 Solaris (版本一般是 9、10)。如果想装 Linux ,只能自己装,厂家是不会提供服务的。
    SUN X96 体系结构的服务器,其实也是PC Server,芯片是 AMD Opteron,一般是安装 Solaris 10。也可自行安装 Linux
    HP 的小型机一般分两种体系结构,PA和安腾。都是安装HP-UX,版本不同,一般是厂家安装的。
    DELL 是 x86 体系结构的,能安装的系统包括 Windows 系列、Linux。Solaris 10 for x86 估计可也可以安装,不过 SUN 不会提供技术支持,DELL 也不会。
  • shell监控linux资源

    2007-08-01 11:11:32

    free |head -1 >smem.csv
    ps aux|head -1|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10"\n"}' >pmem.csv
    df -k /opt|head -2 >pdisk.csv
    top |head -7|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10","$11","$12","$13"\n"}' >pmem2.csv
    while :
    do
       sleep 61
       free |sed -n '2p' >> smem.csv
       date >> smem.csv
       ps aux|grep "3986"|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10"\n"}'>>pmem.csv
       top -n 1 -b |grep "3986"|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10","$11","$12","$13"\n"}'>>pmem2.csv
       printf "PIDtomcat\n">>pmem2.csv
       top -n 1 -b |grep "3336"|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10","$11","$12","$13"\n"}'>>pmem2.csv
       printf "PIDoracle\n">>pmem2.csv
       date >> pmem2.csv
       df -k /opt|sed -n '2p'>>pdisk.csv
       printf "#"
    done

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

    DirPath="logs/";
    fn_cpu=$DirPath"cpu.csv";
    fn_sm=$DirPath"smem.csv";
    fn_io=$DirPath"iostat.csv";
    fn_pm=$DirPath"pmem.csv";
    fn_pm2=$DirPath"pmem2.csv";
    fn_pd=$DirPath"pdisk.csv";
    pro_id="20424";

    echo >$fn_cpu;
    free |head -1 >$fn_sm;
    iostat|head -6>$fn_io;
    ps aux|head -1|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10"\n"}' >$fn_pm
    df -k /opt|head -2 >$fn_pd;
    top |head -7|awk '{printf $1","$2","$3","$4","$5","$6","$7","$8","$9","$10","$11","$12","$13"\n"}' >$fn_pm2;
    while :
    do
       sleep 2;
     
       top -n 1 -b|sed -n '3p'>>$fn_cpu;
  • ApacheBench的一点备忘

    2007-08-01 11:11:32

    ApacheBench-0.63

    下载直接解压当前目录:
    Root$ ab -k -n 1000 -c 127 -k http://tomcathost:8080/examples/date/date.jsp

    主要是对jsp页面响应时间做并发和迭代,造成压力。
    以后再记

  • LR关联

    2007-08-01 11:11:32

    嗯,今天很平静,啥事都没想,没多想,顶多鼻子“哼哼”了几下,一下子过眼云烟咯。最主要的是,我解决了一个很棘手的问题,关于登录界面图片校验码的问题,前段时间解决的,但不同技术构架不同思路,却在.net下被难住了,倒不是那种语言的问题,可能涉及数字校验和图片校验的区别。。想一想,试一试,弄不出来了,就到处走一走,换些其它的活儿干,清静一会/转移思路,过段时间再捡回它吧。。我经常用这种方法搞定东西的,主要自己太刻薄,钻进去就钻不出来了。吼吼
    比较得意,摘抄如下,以后再专门开个类别存放,省得以后记忆力完蛋:
    ...
    lr_think_time( 13 );
    web_set_max_html_param_len("100000000");
    web_reg_save_param("validNum","LB=images/randImg/","RB=.gif","ORD=ALL",LAST);
    web_submit_form("sysuserLoginAction.do;jsessionid={WCSParam_Diff1}",
      "Snapshot=t2.inf",ITEMDATA,
      "Name=sysuserName", "Value=CTAdmin", ENDITEM,
      "Name=password", "Value=CTAdmin", ENDITEM,
      //"Name=validNum", "Value=1879", ENDITEM,
      "Name=validNum", "Value={validNum}", ENDITEM,
      "Name=Submit", "Value=登 录", ENDITEM,
    这里,session原来是被j2ee安全机制屏蔽了的,要是去掉j2ee安全检查,就看不到这块了(记住)
    另外:Execution Log里面是这样的:
    (源代码找不到了,暂时把思路写下来:)
    ...
    <input=...type="text"...><src = ....image.jsp>
    <img src=..../../randimage/3.gif><img src=../../../randimage/7.gif>...(一般一共四个随机图片)
    由image.jsp内部调用rand()函数处理得到.而数字的随机校验,据说是从服务器处生成随机数字后,传到客户端,因此实现机制不一样,不能从类似的getcode.jsp得到里面的img src.总之,原则是找到每次随机数的左右边界,然后关联其中的数值,即可。很简单,理解了逻辑思维就可以咯~不管怎样,大雁飞过一定要吼吼一下哈。
        咳咳
563/3<123
Open Toolbar