zoukankan      html  css  js  c++  java
  • web test LoadRunner tomcat / websphere

    loadrunner监控tomcat解决方案

    http://bbs.51testing.com/viewthread.php?tid=142255&extra=&page=1

    loadrunner 测试tomcat+apache+mysql

    http://auuppp.bokee.com/6935513.html


    loadrunner8.0监控tomcat7 JVM参数:

    loadrunner lr_decrypt() 函数加密参考

    http://www.myloadtest.com/loadrunner-password-encryption/

    文件:D:\TestCase\20120723_tomcat7\Action.c

     

    #include "web_api.h"
    
    Action()
    {
    
    // 登陆tomcat7用户名和密码为:tomcat/s3cret
     	web_set_user("tomcat",lr_decrypt("500d0b4c56cf6e485992"),"localhost:8080");
    
    	lr_start_transaction("首页");
    
    	web_url("localhost:8080",
    		"URL=http://localhost:8080/",
    		"Resource=0",
    		"RecContentType=text/html",
    		"Referer=",
    		"Snapshot=t1.inf",
    		"Mode=HTML",
    		EXTRARES,
    		"Url=/bg-upper.png", ENDITEM,
    		"Url=/bg-nav.png", ENDITEM,
    		"Url=/asf-logo.png", ENDITEM,
    		"Url=/bg-button.png", ENDITEM,
    		"Url=/bg-middle.png", ENDITEM,
    		LAST);
    
    	lr_end_transaction("首页", LR_AUTO);
    
    	lr_start_transaction("登陆status");
    
    	web_reg_save_param("Free memory",
    		"LB=Free memory:",
    		"RB=MB",
    		"Ord=1",
    		"NotFound=ERROR",
    		"Search=All",
    		LAST);
    
    	web_reg_save_param("Total memory",
    		"LB=Total memory:",
    		"RB=MB",
    		"Ord=1",
    		"NotFound=ERROR",
    		"Search=All",
    		LAST);
    
    	web_reg_save_param("Max memory",
    		"LB=Max memory:",
    		"RB=MB",
    		"Ord=1",
    		"NotFound=ERROR",
    		"Search=All",
    		LAST);
    
    	web_link("Server Status",
    		"Text=Server Status",
    		"Snapshot=t2.inf",
    		LAST);
    
    	lr_end_transaction("登陆status", LR_AUTO);
    
    	web_url("status",
    		"URL=http://localhost:8080/manager/status",
    		"Resource=0",
    		"RecContentType=text/html",
    		"Referer=http://localhost:8080/",
    		"Snapshot=t3.inf",
    		"Mode=HTML",
    		LAST);
    
    	return 0;
    }

     

    运行结果:D:\TestCase\20120723_tomcat7\mdrv.log (Execution log)

    Virtual User Script started
    Starting action vuser_init.
    Web Turbo Replay of LoadRunner 8.0.0 for WIN2003; Web build 4141  	[MsgId: MMSG-27143]
    Run-Time Settings file: "D:\TestCase\20120723_tomcat7\\default.cfg"  	[MsgId: MMSG-27141]
    Ending action vuser_init.
    Running Vuser...
    Starting iteration 1.
    Starting action Action.
    Action.c(7): web_set_user was successful  	[MsgId: MMSG-26392]
    Action.c(9): Notify: Transaction "首页" started.
    Action.c(11): web_url("localhost:8080") was successful, 11780 body bytes, 155 header bytes, 20 chunking overhead bytes  	[MsgId: MMSG-26385]
    Action.c(26): Notify: Transaction "首页" ended with "Pass" status (Duration: 0.0522).
    Action.c(28): Notify: Transaction "登陆status" started.
    Action.c(30): Registering web_reg_save_param was successful  	[MsgId: MMSG-26390]
    Action.c(38): Registering web_reg_save_param was successful  	[MsgId: MMSG-26390]
    Action.c(46): Registering web_reg_save_param was successful  	[MsgId: MMSG-26390]
    Action.c(54): Linking to "http://localhost:8080/manager/status", Target Frame=""  	[MsgId: MMSG-27994]
    Action.c(54): Notify: Saving Parameter "Free memory =  86.97 "
    Action.c(54): Notify: Saving Parameter "Total memory =  230.25 "
    Action.c(54): Notify: Saving Parameter "Max memory =  1820.50 "
    Action.c(54): web_link("Server Status") was successful, 10458 body bytes, 663 header bytes, 12 chunking overhead bytes  	[MsgId: MMSG-26385]
    Action.c(59): Notify: Transaction "登陆status" ended with "Pass" status (Duration: 0.1329 Wasted Time: 0.0058).
    Action.c(61): web_url("status") was successful, 7920 body bytes, 208 header bytes  	[MsgId: MMSG-26386]
    Ending action Action.
    Ending iteration 1.
    Ending Vuser...
    Starting action vuser_end.
    Ending action vuser_end.
    Vuser Terminated.
    Vuser 0 (thread 17688), ended OK."
    

     

    第一种:
    LR本身是不支持的!有两种方式可以集成!
    1、自己写一个批处理程序 去取tomcat的数据
    2、使用sitescope去执行这个批处理,然后采集数据
    3、使用LR与sitescope集成,然后读取数据

    第二种:
    1、通过LR去访问tomcat监控页
    2、然后通过关联取监控数据
    3、使用lr_user_data_point()添加数据到图表中去

    关于第二种具体解决 方案如下:(监控tomcat服务器:http://192.168.1.173:1203 )

    1、打开Tomcat的status页面 ,方法为编辑Tomcat的conf目录下的tomcat-users.xml文件 ,在文件中添加
    <?xml version='1.0' encoding='utf-8'?>
    <tomcat-users>
      <role rolename="manager"/>
      <role rolename="admin"/>
      <user username="admin" password="pass" roles="admin,manager"/>
    </tomcat-users>

    2、开发 lr脚本

    vuser_init()
    {
    //定义tomcat内存使用情况的监视器事务;
    lr_start_transaction("monitor tomcat");  

    //保存3个参数
    web_reg_save_param("JVMFreeMemory",   
         "LB=Free memory: ",
         "RB= MB",
         "Ord=1",
       LAST);  
       web_reg_save_param("JVMTotalMemory",
       "LB=Total memory: ",
       "RB= MB",
       "Ord=1",
       LAST);

        web_reg_save_param("JVMMaxMemory",
         "LB=Max memory: ",
         "RB= MB",
         "Ord=1",
        LAST);
    //通过LR去访问tomcat监控页
       web_set_user("admin","pass","192.168.1.173:1203");

      web_url("status",
            "URL=http://192.168.1.173:1203/manager/status",
            "Resource=0",
            "RecContentType=text/html",
            "Referer=",
            "Snapshot=t1.inf",
            "Mode=HTTP",
        LAST);

        lr_end_transaction("monitor tomcat", LR_AUTO);

    // Tomcat JVM metrics  使用lr_user_data_point()添加数据到图表中去
        lr_user_data_point("Tomcat JVM Free memory", atof(lr_eval_string("{JVMFreeMemory}")));
        lr_user_data_point("Tomcat JVM Total memory", atof(lr_eval_string("{JVMTotalMemory}")));
        lr_user_data_point("Tomcat JVM Max memory", atof(lr_eval_string("{JVMMaxMemory}")));
    return 0;
    }

     

     

    运行 脚本后,在脚本日志显示效果图如下:(附件)
    运行场景后,在analysis显示的效果图如下:(附件)

    [ 本帖最后由 zhsh1203 于 2009-3-8 20:01 编辑 ]

    tomcat监控器运行脚本后查询日志效果图.JPG (170.42 KB)

    更高

    tomcat监控器运行脚本后查询日志效果图.JPG

    监控tomcat服务器在Analysis效果图.JPG (138.53 KB)

    更远

    监控tomcat服务器在Analysis效果图.JPG

    LR监控tomcat服务器.doc (727.5 KB)


    loadrunner action script

    1.注意脚本函数顺序

    #include "web_api.h"
    
    	//double atof (const char *string);	
    
    Action()
    {
    	//double atof(   const char *string );
    
    	web_set_user("tomcat",
    		lr_decrypt("4ec5fc8e30b3560971"),
    		"localhost:8080");
    
    	web_url("localhost:8080",
    		"URL=http://localhost:8080/",
    		"Resource=0",
    		"RecContentType=text/html",
    		"Referer=",
    		"Snapshot=t5.inf",
    		"Mode=HTML",
    		EXTRARES,
    
    		"Url=/bg-upper.png", ENDITEM,
    		"Url=/bg-nav.png", ENDITEM,
    		"Url=/asf-logo.png", ENDITEM,
    		"Url=/bg-button.png", ENDITEM,
    		"Url=/bg-middle.png", ENDITEM,
    		LAST);
    
    	lr_start_transaction("tomcat_jvm_start");
    	
    	web_reg_save_param("JVMFreeMemory",
    		"LB=Free memory:",
    		"RB=MB Total memory",
    		"Ord=1",
    		LAST);  
    
    //  lr_user_data_point("JVMFreeMemory_Lindows", atof(lr_eval_string("?")));     
        lr_user_data_point("JVMFreeMemory_Lindows", atof(lr_eval_string("{JVMFreeMemory}")));     
    //lr_output_message(lr_evel_string("=======param1========={param1}"));
       lr_output_message(lr_evel_string("=======param1========={JVMFreeMemory}"));
    
    	lr_end_transaction("tomcat_jvm_start", LR_AUTO);
    
    	web_link("Server Status",
    		"Text=Server Status",
    		"Snapshot=t8.inf",
    		LAST);
    
    	return 0;
    
    }
     

     

    loadrunner 测试tomcat+apache+mysql

    http://auuppp.bokee.com/6935513.html

    网站在Tomcat和应用程序进行了压力测试后,如果对应用程序的性能结果不太满意,就可以采取一些性能调整措施了,当然了前提是应用程 序没有问题,我们这里只讲Tomcat的调整。由于Tomcat的运行依赖于JVM,所以在这里我们把Tomcat的调整可以分为两类来详细描述:

      外部环境调整

      调整非Tomcat组件,例如Tomcat运行的操作系统和运行Tomcat的java虚拟机。

      自身调整

      修改Tomcat自身的参数,调整Tomcat配置文件中的参数。

      下面我们将详细讲解外部环境调整的有关内容,Tomcat自身调整的内容将在第2部分中阐述。

      1.JAVA虚拟机性能优化

       Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机。您可以选择自己的需要选择不同的操作系统和对应的 JDK的版本(只要是符合Sun发布的Java规范的),但我们推荐您使用Sun公司发布的JDK。确保您所使用的版本是最新的,因为Sun公司和其它一 些公司一直在为提高性能而对java虚拟机做一些升级改进。一些报告显示JDK1.4在性能上比JDK1.3提高了将近10%到20%。

      可以给Java虚拟机设置使用的内存,但是如果你的选择不对的话,虚拟机不会补偿。可通过命令行的方式改变虚拟机使用内存的大小。如下表所示有两个参数用来设置虚拟机使用内存的大小。
    参数
    描述

    -Xms<size>
    JVM初始化堆的大小

    -Xmx<size>
    JVM堆的最大值

       这两个值的大小一般根据需要进行设置。初始化堆的大小执行了虚拟机在启动时向系统申请的内存的大小。一般而言,这个参数不重要。但是有的应用程序在大负 载的情况下会急剧地占用更多的内存,此时这个参数就是显得非常重要,如果虚拟机启动时设置使用的内存比较小而在这种情况下有许多对象进行初始化,虚拟机就 必须重复地增加内存来满足使用。由于这种原因,我们一般把-Xms和-Xmx设为一样大,而堆的最大值受限于系统使用的物理内存。一般使用数据量较大的应 用程序会使用持久对象,内存使用有可能迅速地增长。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆 的最大值设置为可用内存的最大值的80%。

      Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。

      Windows下,在文件{tomcat_home}/bin/catalina.bat,Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下设置:

      JAVA_OPTS='-Xms【初始化内存大小】 -Xmx【可以使用的最大内存】'

      需要把这个两个参数值调大。例如:

      JAVA_OPTS='-Xms256m -Xmx512m'

      表示初始化内存为256MB,可以使用的最大内存为512MB。

       另外需要考虑的是Java提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾可以接受的速度与应用有关,应该通过 分析实际的垃圾收集的时间和频率来调整。如果堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。如果你把堆的大小和内存的需要一致,完全收集就很 快,但是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为保证最好的性能,要把堆的 大小设大,保证垃圾收集不在整个基准测试的过程中出现。

      如果系统花费很多的时间收集垃圾,请减小堆大小。一次完全的垃圾收集应该不超过 3-5 秒。如果垃圾收集成为瓶颈,那么需要指定代的大小,检查垃圾收集的详细输出,研究 垃圾收集参数对性能的影响。一般说来,你应该使用物理内存的 80% 作为堆大小。当增加处理器时,记得增加内存,因为分配可以并行进行,而垃圾收集不是并行的。

      2.操作系统性能优化

       这里说的操作系统是指运行web服务器的系统软件,当然,不同的操作系统是为不同的目的而设计的。比如OpenBSD是面向安全的,因此在它的内核中有 许多的限制来防止不同形式的服务攻击(OpenBSD的一句座右铭是“默认是最安全的”)。这些限制或许更多地用来运行活跃的web服务器。

       而我们常用的Linux操作系统的目标是易用使用,因此它有着更高的限制。使用BSD内核的系统都带有一个名为“Generic”的内核,表明所有的驱 动器都静态地与之相连。这样就使系统易于使用,但是如果你要创建一个自定义的内核来加强其中某些限制,那就需要排除不需要的设备。Linux内核中的许多 驱动都是动态地加载的。但是换而言之,内存现在变得越来越便宜,所以因为加载额外的设备驱动就显得不是很重要的。重要的是要有更多的内存,并且在服务器上 腾出更多的可用内存。

      小提示:虽然现在内存已经相当的便宜,但还是尽量不要购买便宜的内存。那些有牌子的内存虽然是贵一点,但是从可靠性上来说,性价比会更高一些。

      如果是在Windows操作系统上使用Tomcat,那么最好选择服务器版本。因为在非服务器版本上,最终用户授权数或者操作系统本身所能承受的用户数、可用的网络连接数或其它方面的一些方面都是有限制的。并且基于安全性的考虑,必须经常给操作系统打上最新的补丁。

      3.Tomcat与其它web服务器整合使用

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

      4.负载均衡

      在负载均衡的思路下,多台服务器为对称方式,每台服务器都具有同等的地位,可以单独对外提供服务而无须其他服务器的辅助。通过负载分担技术,将外部发送来的请求按一定规则分配到对称结构中的某一台服务器上,而接收到请求的服务器都独立回应客户机的请求。

      提供服务的一组服务器组成了一个应用服务器集群(cluster),并对外提供一个统一的地址。当一个服务请求被发至该集群时,根据一定规则选择一台服务器,并将服务转定向给该服务器承担,即将负载进行均衡分摊。

       通过应用负载均衡技术,使应用服务超过了一台服务器只能为有限用户提供服务的限制,可以利用多台服务器同时为大量用户提供服务。当某台服务器出现故障 时,负载均衡服务器会自动进行检测并停止将服务请求分发至该服务器,而由其他工作正常的服务器继续提供服务,从而保证了服务的可靠性。

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

    大家都知道,JAVA程序启动时都会JVM都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能。比如说在应用程序用到最大内存的时候,JVM是要先去做垃圾回收的动作,释放被占用的一些内存。
            所以想调整Tomcat的启动时初始内存和最大内存就需要向JVM声明,一般的JAVA程序在运行都可以通过中-Xms -Xmx来调整应用程序的初始内存和最大内存:
            如:java -Xms64m -Xmx128m a.jar.
    tomcat的启动程序是包装过的,不能直接使用java -X..... tomcat.*来改变内存的设置。在Tomcat在改变这个设置
    有两种方法:
    1.    就需要在环境变量中加上TOMCAT_OPTS, CATALINA_OPTS两个属性,
            如 SET CATALINA_OPTS= -Xms64m -Xmx512m;
            ms是最小的,mx是最大,64m, 512m分别是指内存的容量.
    2.    修改Catalina.bat文件
           在166行“rem Execute Java with the applicable properties ”以下每行
    %_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs ="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE %" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION% 中的%CATALINA_OPTS% 替换成-Xms64m - Xmx512m

    Tomcat性能优化

    1.停用DNS查询
    server.xml里
    <Connector
    port="8887" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" redirectPort="8443" acceptCount="100"
    debug="0" connectionTimeout="20000"
    disableUploadTimeout="true" />

    加上enableLookups="false";这样就不使用DNS查询,也不会有延迟了
    除非需要所有连接到服务器的HTTP客户端的完整主机名称

    注:Connector的enableLookups性属的意义是:调用request.getRemoteHost()是否会通过DNS查询来取得远处客户端的真正主机名称。true表示会查询,false表示以字符串格式传回客户端的IP地址。默认值是:true

    2,调整线程的数目
    Tomcat使用线程池以便对传入的请求提供快速的响应。
    通过更改Connector的minProcessors与maxProcessors的值,可以控制所分配的线程数目
    将 这两个参数设为最佳值的最好方式是对各个参数尝试许多不同的设定值,然后以仿真的网络流量进行测试,同时并观察响应时间与内存的使用量。每一种机器、操作 系统与JVM的组合都可能有不同的表现,而且并非所有人的网站流量都会相同,所以没有现成的规则来决定最小与最大的线程数

    3.加快jsp的编译速度,预先编译jsp

    4.容量规划:经验式的容量规划,企业容量规划

    经验式的容量规划与企业容量规划最大的差异就是深度。经验式容量规划使用经验法则,因此比较像是经验预测,而企业容量规划则是深度地研究需求与性能,其目标是尽可能产生最精确的数字


    apache+tomcat+mysql

                Apache+Tomcat+Mysql网站配置
    前言:
    公司开发了一个网站,估计最高在线人数是3万,并发人数最多100人。开发的网站是否能否承受这个压力,如何确保网站的负荷没有问题,经过研究决定如下:
    (1) 采用负载平衡和集群技术,初步机构采用Apache+Tomcat的机群技术。
    (2) 采用压力测试工具,测试压力。工具是Loadrunner。
    硬件环境搭建:
    为了能够进行压力测试,需要搭建一个环境。刚开始时,测试在公司局域网内进行,但很快发现了一个问题,即一个脚本的压力测试结果每次都不一样,并且差别很大。原来是受公司网络的影响,于是决定搭建一个完全隔离的局域网测试。搭建后的局域网配置如下:
    (1) 网络速度:100M
    (2) 三台服务器:
    负载服务器 :操作系统windows2003,
    Tomcat服务器:操作系统windows2000 Professional
    数据库服务器:操作系统windows2000 Professional
    三台机器的cpu 2.4 G, 内存 2G。
    软件环境搭建:
    软件的版本如下:
    Apache 版本:2.054,
    Tomcat5.0.30,
    mysql :4.1.14.
    JDK1.5
    压力测试工具:Loadrunner7.8。
    负载平衡方案如下:
    一台机器(操作系统2003)安装apache,作为负载服务器,并安装tomcat作为一个worker;一个单独安装tomcat,作为第二个worker;剩下的一台单独作为数据库服务器。
        Apache和tomcat的负载平衡采用JK1.2.14(没有采用2.0,主要是2.0不再维护了)。
    集群方案:
         采用Tomcat本身的集群方案。在server.xml配置。
    压力测试问题:
    (1) 采用Tocmat集群后,速度变得很慢。因为集群后,要进行session复制,导致速度较慢。Tomcatd的复制,目前不支持application 复制。复制的作用,主要用来容错的,即一台机器有故障后,apache可以把请求自动转发到另外一个机器。在容错和速度的考虑上,我们最终选择速度,去掉 了Tomcat集群。
    (2) 操作系统最大并发用户的限制:
    为了采用网站的压力,我们开始的时候,仅测试Tomcat的最大负载数。 Tomcat服务器安装的操作系统是windows2000 Professional。当我们用压力测试工具,并发测试时,发现只要超过15个并发用户,会经常出现无法连接服务器的情况。经过研究,发现是操作系统 的问题:windows2000 Professional 支持的并发访问用户有限,默认的好像是15个。于是我们把操作系统全部采用windows2003 server版本。
    (3) 数据库连接池的问题:
    测 试数据库连接性能时,发现数据库连接速度很慢。每增加一些用户,连接性能就差了很多。我们采用的数据库连接池是DBCP,默认的初始化为50个,应该不会 很慢吧。查询数据库的连接数,发现初始化,只初始化一个连接。并发增加一个用户时,程序就会重新创建一个连接,导致连接很慢。原因就在这里了。如何解决 呢?偶尔在 JDK1.4下的Tomcat5.0.30下执行数据库连接压力测试,发现速度很快,程序创建数据库连接的速度也是很快的。看来JDK1.5的JDBC驱 动程序有问题。于是我们修改 JDK的版本为1.4.

    (4) C3P0和DBCP
    C3P0是Hibernate3.0默认的自带数据库连接池,DBCP是Apache开发的数据库连接池。我们对这两种连接池进行压力测试对比,发现在并发300个用户以下时,DBCP比C3P0平均时间快1秒左右。但在并发400个用户时,两者差不多。

    速度上虽然DBCP比C3P0快些,但是有BUG:当DBCP建立的数据库连接,因为某种原因断掉后,DBCP将不会再重新创建新的连接,导致必须重新启动Tomcat才能解决问题。DBCP的BUG使我们决定采用C3P0作为数据库连接池。
    调整后的方案:
    操作系统Windows2003 server版本
    JDK1.4
    Tomcat 5.0.30
    数据库连接池C3P0
    仅采用负载平衡,不采用集群。
    软件的配置:
    Apache配置:主要配置httpd.conf和新增加的文件workers.properties
    Httpd.conf:
    #一个连接的最大请求数量
    MaxKeepAliveRequests 10000
    #NT环境,只能配置这个参数来提供性能
    <IfModule mpm_winnt.c>
    #每个进程的线程数,最大1920。NT只启动父子两个进程,不能设置启动多个进程
    ThreadsPerChild 1900
    每个子进程能够处理的最大请求数
    MaxRequestsPerChild 10000
    </IfModule>

    # 加载mod_jk
    #
    LoadModule jk_module modules/mod_jk.so
    #
    # 配置mod_jk
    #
    JkWorkersFile conf/workers.properties
    JkLogFile logs/mod_jk.log
    JkLogLevel info
    #请求分发,对jsp文件,.do等动态请求交由tomcat处理
    DocumentRoot "C:/Apache/htdocs"
    JkMount /*.jsp loadbalancer
    JkMount /*.do loadbalancer
    JkMount /servlet/* loadbalancer
    #关掉主机Lookup,如果为on,很影响性能,可以有10多秒钟的延迟。
    HostnameLookups Off
    #缓存配置
    LoadModule cache_module modules/mod_cache.so
    LoadModule disk_cache_module modules/mod_disk_cache.so
    LoadModule mem_cache_module modules/mod_mem_cache.so

    <IfModule mod_cache.c>
    CacheForceCompletion 100
    CacheDefaultExpire 3600
    CacheMaxExpire 86400
    CacheLastModifiedFactor 0.1

    <IfModule mod_disk_cache.c>
    CacheEnable disk /
    CacheRoot c:/cacheroot
    CacheSize 327680
    CacheDirLength 4
    CacheDirLevels 5
    CacheGcInterval 4
    </IfModule>
    <IfModule mod_mem_cache.c>
    CacheEnable mem /
    MCacheSize 8192
    MCacheMaxObjectCount 10000
    MCacheMinObjectSize 1
    MCacheMaxObjectSize 51200
    </IfModule>
    </IfModule>
    worker. Properties文件
    #
    # workers.properties ,可以参考
    ::URL::http://jakarta.apache.org/tomcat/connectors-doc/config/workers.html
    # In Unix, we use forward slashes:
    ps=\

    # list the workers by name

    worker.list=tomcat1, tomcat2, loadbalancer

    # ------------------------
    # First tomcat server
    # ------------------------
    worker.tomcat1.port=8009
    worker.tomcat1.host=localhost
    worker.tomcat1.type=ajp13

    # Specify the size of the open connection cache.
    #worker.tomcat1.cachesize

    #
    # Specifies the load balance factor when used with
    # a load balancing worker.
    # Note:
    # ----> lbfactor must be > 0
    # ----> Low lbfactor means less work done by the worker.
    worker.tomcat1.lbfactor=900

    # ------------------------
    # Second tomcat server
    # ------------------------
    worker.tomcat1.port=8009
    worker.tomcat1.host=202.88.8.101
    worker.tomcat1.type=ajp13

    # Specify the size of the open connection cache.
    #worker.tomcat1.cachesize

    #
    # Specifies the load balance factor when used with
    # a load balancing worker.
    # Note:
    # ----> lbfactor must be > 0
    # ----> Low lbfactor means less work done by the worker.
    worker.tomcat1.lbfactor=2000

    # ------------------------
    # Load Balancer worker
    # ------------------------

    #
    # The loadbalancer (type lb) worker performs weighted round-robin
    # load balancing with sticky sessions.
    # Note:
    # ----> If a worker dies, the load balancer will check its state
    #        once in a while. Until then all work is redirected to peer
    #        worker.
    worker.loadbalancer.type=lb
    worker.loadbalancer.balanced_workers=tomcat1,tomcat2

    #
    # END workers.properties
    #

    Tomcat1配置:
    <!--配置server.xml
    去掉8080端口,即注释掉如下代码:-->
    <Connector
    port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                   enableLookups="false" redirectPort="8443" acceptCount="100"
                   debug="0" connectionTimeout="20000"
                   disableUploadTimeout="true" />

    <!--配置8009端口如下:-->
    <Connector port="8009"
    maxThreads="500" minSpareThreads="400" maxSpareThreads="450"
                   enableLookups="false" redirectPort="8443" debug="0"
                   protocol="AJP/1.3" />
    <!--配置引擎-->
    <Engine name="Catalina" defaultHost="localhost" debug="0" jvmRoute="tomcat1">

    启动内存配置,开发configure tomcat程序即可配置:
    Initial memory pool: 200 M
    Maxinum memory pool:300M
    Tomcat2配置:
    配置和tomcat1差不多,需要改动的地方如下:
    <!--配置引擎-->
    <Engine name="Catalina" defaultHost="localhost" debug="0" jvmRoute="tomcat2">

    启动内存配置,开发configure tomcat程序即可配置:
    Initial memory pool: 512 M
    Maxinum memory pool:768M
    Mysql配置:
    Server类型:Dedicated MySQL Server Machine
    Database usage:Transational Database Only
    并发连接数量:Online Transaction Processing(OLTP)
    字符集:UTF8
    数据库连接池的配置:
    我们采用的是spring 框架,配置如下:
    <property name="hibernateProperties">
    <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
    <prop key="hibernate.connection.url">jdbc:mysql://202.88.1.103/db</prop>
    <prop key="hibernate.connection.username">sa</prop>
    <prop key="hibernate.connection.password"></prop>

    <prop key="hibernate.show_sql">false</prop>
    <prop key="hibernate.use_sql_comments">false</prop>

    <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
    <prop key="hibernate.max_fetch_depth">2</prop>

    <prop key="hibernate.c3p0.max_size">200</prop>
    <prop key="hibernate.c3p0.min_size">5</prop>
    <prop key="hibernate.c3p0.timeout">12000</prop>
    <prop key="hibernate.c3p0.max_statements">50</prop>
    <prop key="hibernate.c3p0.acquire_increment">1</prop>
    </props>
    </property>
    其他的没有额外配置。
    LoadRunner 常见问题:
    (1)sofeware caused connction:这种情况,一般是脚本有问题,或者loadrunner有问题。解决方法:重新启动机器,或者重新录制脚本,估计是loadrunner的bug。
    (2)cannot connect to server:无法连接到服务器。这种情况是服务器的配置有问题,服务器无法承受过多的并发连接了。需要优化服务器的配置,
    如操作系统采用windows 2003 server,
    优化tomcat配置:maxThreads="500" minSpareThreads="400" maxSpareThreads="450"。但是tomcat 最多支持500个并发访问
    优化apache配置:
    ThreadsPerChild 1900
    MaxRequestsPerChild 10000
    其他的错误如:
    Action.c(10): Error -27791: Server has shut down the connection prematurely
    HTTP Status-Code=503 (Service Temporarily Unavailable)
    一般都是由于服务器配置不够好引起的,按照问题(2)处理,如果仍旧不行,需要优化硬件和调整程序了。
    Apache问题:
    (1) File does not exist: C:/Apache/htdocs/favicon.ico:
    这个问题是apache,htdocs目录没有favicon.ico文件引起的,该文件是网站的图标,仅在firefox,myIE等浏览器出现。
    (2) 图片无法显示:
    配置apache后,却无法显示图片。
    解决方法:把程序的图片,按照程序结构copy到apache的htdocs目录下。
    (3) 无法处理请求:
    当我们输入 ***.do 命令后,apache确返回错误信息,而连接tomcat却没有问题。原因是没有把.do命令转发给tomcat处理。解决方法如下:
    在apache配置文件中配置如下内容:
    DocumentRoot "C:/Apache/htdocs"
    JkMount /*.jsp loadbalancer
    JkMount /*.do loadbalancer


    网站的压力测试,涉及的知识面挺广的,不仅要熟悉压力测试工具,还要知道如何配置和优化应用服务器和数据库,并且需要知道如何优化网络、操作系统、硬件系统。
    测 试中不仅要善于发现问题,要知道如何解决。最重要的一点,要有良好的测试方法。刚开始测试时,可以从最简单的测试脚本入手,不需要太复杂的脚本,这样便于 发现问题。如我们刚开始时,就从一个简单的下载登陆界面的脚本入手,测试一个tomcat的压力负载。一个简单的获取登陆的脚本,帮助我们优化了 tomcat的配置;后来再测试数据库连接,也是一个简单的数据库连接脚本,帮助我们优化了数据库连接池;然后利用这些简单的脚本,测试apache的负 载平衡,优化了apache配置。最后运行复杂的脚本,模拟多种角色的用户在不同时间下的处理,以测试网站压力负载。

     

    loadrunner websphere performance 

    促销中心寻源项目性能异常解决

    Question:

    促销中心PRE_寻源项目_WAS_exception 

    WAS CPU 应用消耗有大掉坑现象,WAS JVM GC 次数过于频繁,JVM 内存消耗达1.5GB左右

    http://dl2.iteye.com/upload/attachment/0098/0712/98045e35-1d88-3af4-8a25-3721db998714.jpg

    Answer:

    促销中心PRE_寻源项目_WAS_jvm.jpg 

    调整WAS 应用会话默认30分钟改为3分钟后压测,CPU 大掉坑现象消失,WAS JVM gc 在1.0GB左右,性能有所上升,如下图,右边曲线图。

    http://dl2.iteye.com/upload/attachment/0098/0714/9be6e7c8-f65c-3703-94b6-27cbf6b60b6e.jpg

     

     

    WebSphere 中池资源调优 - 线程池、连接池和 ORB

    http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1106_zhuxl_websphereenhancement/1106_zhuxl_websphereenhancement.html 朱修磊, 软件工程师, IBM 2011 年 6 月 13 日

     

    WebSphere 性能优化概述

    是什么引起了性能问题?或者如何提高系统的性能?这是我们在系统的开发和维护时经常会碰到的问题,但是这两个问题很难回答。正如下图所示,性能问题可能发生于系统的各个环节中,当性能问题出来后很难马上就定位性能的瓶颈在哪里,即使找到了性能瓶颈,在进行调优的时候也要考虑系统整体环境,从上下文中分析,确定调优的策略;系统中一个或者多个“短板”的存在,就能让系统无法达到设计时的目标,无法达到预期的性能提升。

    在本文中,我们将重点放在 WebSphere 中各种池资源的调优上,包括线程池、数据库连接池以及 ORB 的连接数调优。池(Pool)是 WebSphere 中最常涉及的概念之一。从网络、Web 服务器、Web 容器、EJB 容器,一直到数据源,每一个环节都有线程池、连接池的影子。这些池资源从上到下被连接在一起,就形成了一个访问和应答的队列。在 WebSphere 的调优中,如果能合理的配置这些池资源,可以从很大程度上提高整个系统的运行效率。

    图 1. 性能问题发生在 WAS 和操作系统的各个环节中

    图 1. 性能问题发生在 WAS 和操作系统的各个环节中

    WAS 性能差的几种表现及解决方法

    系统性能差一般有以下两种非常明显的表现形式,第一种是 CPU 使用不高,用户感觉交易响应时间很长;第二种是 CPU 使用很高,用户感觉交易响应时间很长。对于第一种情况,可以断定是由于系统的某一小部分造成了瓶颈,导致了所有的请求都在等待。简单举例来说,线程池的数量开的太小,导致所有的请求都在排队等待进入线程池,因为没有可用的线程使用,所以这个交易请求一直在排队,导致交易响应时间很长。如果数据库连接池开的太小,也会有同样的表现。对于第二种情况,比较复杂。可能的根源之一是硬件资源不够。根源之二是应用系统中产生了多个大对象。根源之三是程序算法有问题。解决思路如下: 用性能分析器,如 RAD 或 JProfiler, 对运行环境进行分析,分析哪个类甚至于哪个函数消耗了这么多的 CPU,并找到相应的解决方案。

    WAS 性能调优没有捷径和魔术,因为每一个应用都有自己独特的特性和资源需求,而且他们使用 WAS 的资源也有各种不同的方式,每一套调优的参数和策略仅适用于当前的系统环境,在实际的系统环境中不能简单的将一种调优策略原封不动的移植到另外一个系统环境中,这样往往得不到预期的调优目的,还可能照成更多的性能瓶颈。

     

    WebSphere 系统队列介绍和调优

    WAS 是由一系列相互作用的组件连接而成的,必须对这些被连接在一起的组件进行合理的调优,才能够满足客户的应用对系统性能的要求。这些调整和调优将帮助系统达到最大的吞吐率和最高的使用效率。

    WebSphere 排队网络

    当客户端发出一个请求时,该请求会从网络端开始依次进入 WehSphere 服务器的各个组件,这些请求会在各个组件中进行排队等候使用服务器资源或者等待进入下一个组件进一步被服务器处理请求,每个组件里的请求组成请求队列,而组件依次排列,就够成了 WebSphere 排队网络。正如下图所示,该排队网络包括互联网、Web 服务器、Web 容器、EJB 容器以及数据库端的连接池队列等等。WebSphere 队列里的各个组件是互相资源依赖的,对请求的平均服务时间依赖于服务器队列中每个组件在同一时间的最大并发数。

    图 2. WebSphere 排队网络

    图 2. WebSphere 排队网络

    保守队列和开放队列

    在组成 WebSphere 排队网络的队列中,大部分都属于保守队列。对于保守队列,我们可以设置某些参数来限制队列中请求被处理的最大并发数,相反,开发队列则没有这样的限制。与开放队列相比,保守队列的好处是,可以使系统资源被有效的管理和利用,避免因为资源耗尽而引起的系统崩溃。例如,在 Web 容器中,假设平均处理一个 servlet 请求要创建 10M 大小的对象,如果我们设置其最大连接数是 100,那么这样就可以将 Web 容器对内存的最大消耗控制在 1G 左右。因此,保守队列使得系统管理员更有效的管理系统应用。

    保守队列中的用户请求有两种状态,分别是激活状态和等待状态。当请求处于激活状态时,表明该请求正在被服务器进行处理;当请求处于等待状态时,表明该请求还未被处理,而是在等待被激活,进而才能够使用服务器资源。只有当一个处于激活状态的请求被处理完毕离开队列后,才会有一个处于等待状态的请求被激活,否则该请求将一直处于等待状态,直到服务器超时抛出异常,如果出现此种情况,则表明服务器需要进行系统优化。

    在 WebSphere 服务器的队列网络中,Web 服务器、Web 容器以及数据库连接池都属于保守队列。EJB 容器则继承了对象请求代理(ORB)的队列特性,属于开放队列。

    WebSphere 中的队列调优和设置

    在 WebSphere 中,我们主要通过最大和最小连接数两个参数来对其队列进行调优和设置,接下来我们会给出一个在进行 WebSphere 队列调优时的基本准则。读者在以后的调优中可以参照这个准则,然后结合自己的实际系统环境来进行队列调优。

    “漏斗”原则

    WAS 调优的第一原则就是漏斗原则。一般来说,让客户不能及时得到处理的请求在网络中等待,比让它们在 WebSphere 服务器中等待要好。下图的设置使得只有即将被服务器接受处理的请求才能进入 WAS 的排队网络,这样更能提高服务器的稳定性,而不至于当大量请求突然进入 WAS 时引起资源耗尽的情况。要实现这个原则,那么越往下游的组件,其处理请求的最大并发数应小于上游组件的最大并发数。如下图所示,只有可以被处理的请求才会进入相应的组件被处理,而大于该组件并发数的其他请求,则都处于排队状态,等待服务器接受处理。

    图 3. Upstream queuing

    图 3. Upstream queuing

    在上图的例子中,我们可以看出,在 WebSphere 排队网络中,从上到下队列中处理请求的并发数越来越小。当 200 客户端请求到达 Web 服务器的时候,因为 Web 服务器设置了自己的最大并发数是 75,所以剩下的 125 个客户请求只能暂留在网络中进行排队等待被 Web 服务器处理;当这 75 个请求经过 Web 服务器被处理后,其中 25 个仍在停留在 Web 服务器中排队,而剩下的 50 个请求则进去 Web 容器被进一步处理;直到最后有 25 个请求到达最后的数据库端,这时请求被处理完毕。在这个系统中,每一个组件都在充分的工作,没有因为等待请求到来而造成的资源浪费,因为在任何一个时刻,每个队列里都有少量请求在等待着被下一个组件处理。因为大量的请求被阻止在 WebSphere 服务器的外面(网络),所以 WebSphere 的各个组件不会因为大量请求同时到来而引起资源耗尽,这样的设置增加了系统的稳定性。

    绘制吞吐率曲线

    上面介绍了在对 WebSphere 服务器池资源进行调优时的一个最重要的准则,下面我们来介绍如何根据这个准则,并结合用户实际的系统环境来进行调优设置。首先我们需要画出系统在运行时的吞吐率曲线,要完成曲线,需要准备一个测试用例,然后将系统运行起来,我们的目的是要将系统的潜能发挥到最大,即系统运行达到一个资源利用的饱和点。系统运行达到饱和点最有代表性新的特征就是 CPU 的利用率接近 100%。

    在运行测试用例的开始阶段,我们将 WebSphere 排队网络中所有的队列并发数都设置为一个较大的值,而且各个队列的值也设成是相等的。要保证这样的设置可以使你的系统在运行时达到最大的处理能力。例如,将排队网络的每一个队列的最大并发数都设置成 100。

    现在,我们开始进行一系列的测试,根据测试数据绘出吞吐率曲线。在每一次的测试后,增加用户并发数,迭代测试,例如:把用户并发数设置成如下一组数值进行一系列测试(1,5,10,25,50,100,150,200...),在每次测试后,记录下本次系统的吞吐率和响应时间,就得到了类似于下图的吞吐率曲线。

    图 4. 吞吐率曲线

    图 4. 吞吐率曲线

    吞吐率是 WebSphere 服务器在同一时间处理用户请求的并发数,反应的是 WebSphere 处理并发请求的能力。从上图中我们可以看出,曲线可以分为三个阶段,在第一阶段,也就是 A 阶段的时候,这时并发的数量比较少,吞吐率随着并发数目的增加而增加。因为在这个时候,并发数较小,队列中几乎没有请求在排队,每当一个请求到来时就能立刻得到处理,随着并发数的增加,在某一时刻,排队情况开始出现,吞吐率曲线的增长变的缓慢,直到达到了系统处理能力的饱和点,这个时候也就是出现了系统的性能瓶颈。最具代表性的系统瓶颈是,在饱和点时,系统 CPU 利用率几近 100%,这时我们只要换上更加高性能的 CPU 就可以提高整个系统的性能。在经过饱和点后,吞吐率曲线进入第二个阶段 B,这时,随着并发数的增加,吞吐量并没有增加,而是维持在一个稳定的水平。然而,客户端所感受到的服务器响应时间则会随着并发数的增加而加长,这时因为很多的请求都在队列里排队,并没有及时的被服务器处理。此刻,并发数继续增加,就会进入第三个阶段 C,这时,随着并发数的增加,吞吐率反而会急剧下降,这时因为系统中某一个组件负载过重,导致资源已经被消耗殆尽。

    在进行曲线绘制的过程中,我们需要注意一个问题,如果在饱和点出现的时候,系统的 CUP 利用率接近 100%,那么我们就能进行进一步的调优设置了;如果 CPU 利用率没有达到 100%,那么就说明,系统中所运行的应用程序存在问题,也就是性能瓶颈所在。比如,你的应用程序可能创建了很多的大对象,导致了 JAVA 中的频繁 GC,大量占用系统资源而出现性能瓶颈,对于性能瓶颈,我们需要认真检查程序源代码,找出问题所在,然后修改排查,消除因为应用而造成的系统瓶颈。找出性能系统瓶颈的方法很多,不是本文论述的重点,读者可以参考其他资料来进行排查。

    队列初调

    在吞吐率曲线达到饱和点时的用户并发数是系统应用所能处理的最大并发数,这也是 A 阶段和 B 阶段的分界线。这个值将做为我们调整队列大小的一个基准值。如上图所示,饱和点时,并发数是 50,我们选择 48 来做为调整队列的基准值,因为在此刻吞吐率和响应时间都是最佳的,这个值称为程序所能处理请求的最大并发数。正如我们前面所介绍的,理想的情况是确保大量的等待请求处于网络中,而不是 WebSphere 服务器中,所以参照“漏斗”原则,我们可以对 WebSphere 服务器中的各个组件的最大并发数进行如下设置:Web 服务器 , 75,Web 容器 50,数据库连接池 45。然后我们在进行一系列的测试,对这些值进行微调,以使系统的性能达到最优。

    根据应用的实际情况来调整队列

    仅仅根据上面的准则来调优 WAS 是远远不够的,我们还应根据应用的使用环境和访问模型来调整各个队列的大小。并不是所有的请求都会从上一个队列进入到下一个队列中,比如,有些请求可能在经过 Web 服务器处理后就返回给客户端了,因为这些用户仅仅是想请求一些静态的页面内容,这时我们可以将 Web 服务器的队列值设的大一些,我们上面将 Web 服务器设成 75 就是这样的考虑;又比如,如果在一个应用中,大部分的请求都需要进行复杂而耗时的数据库操作,这时我们就应该考虑同时加大数据库连接池和 Web 容器的队列值大小。所以,在我们实际的调优中,必须结合具体的应用来确定合适的值,并在不断调整的过程中,监控 CPU 和内存的使用,避免系统资源耗尽的情况出现。

     

    WebSphere 池资源调优的最佳实践

    我们在这里给出 WebSphere 池资源调优的一些建议,但真正合适的大小还要参考实际情况,调优是一个循序渐进的过程,需要经过不断的尝试和修改才能最终达到系统设计所需要的最佳性能。

    ORB 调优

    当配置 ORB 线程池的时候,需要了解 EJB 客户端对应用的访问模式。比如,如果在一个 servlet 中只是有很少的 EJB 调用,而且每一次方法调用的时间相对很短,那么你就应该调整 ORB 线程池的值尽量小于 Web 容器的最大并发数。

    图 5 . EJB 调用模式

    图 5 . EJB 调用模式

    并行调用 EJB 的 servlet 的数量和每次方法调用所持续的时间是我们调整 ORB 线程池大小的两个依据。如上图,是两种在 WAS 里从 servlet 中调用 EJB 的场景。第一种场景中,servlet 主要做一些持续时间非常短的远程调用,servlet 可以重用已经存在的 ORB 线程。在这种情况下,ORB 线程池可以设的比较小,例如只要设置为 Web 容易最大并发量的一半就行;第二种场景中,持续时间比较长的 EJB 调用将会长期的占用 ORB 连接,因此该连接被重用的机会很小,所以在这种场景中,最好将 ORB 线程池的大小与 Web 容器的最大并发量设置成相等,或者更大。可以使用 WAS 管理控制台进行 ORB 线程池的配置,位于 Application servers > AppServer name > Thread pools > ORB.thread.pool

    Web 容器线程池

    一般来说,每个服务器 CPU,5 至 10 个线程将会提供最佳吞吐量。另外我们也可以利用 WAS 自带的 TPV 来帮助我们设置 Web 容器线程池。对系统做一个压力测试,保持一定的负载,观测 TPV 中的 PercentMaxed 和 ActiveCount的值,PercentMaxed 表示所有线程被使用的平均百分比,如果该值较大,那么就应该增大线程池的值;ActiveCount 表示被激活的线程个数,如果该值远小于当前线程池的大小,那么可以考虑减小线程池的值。可以 使用 WAS 管理控制台进行 Web 容器线程池的配置,位于 Application servers > AppServer name > Thread pools > WebContainer

    数据库连接池

    当我们连接任何数据库时,数据库连接的初始化是一个非常耗资源的操作,所以当性能问题出现时,只是一味的加大数据库连接池往往并不能提高性能。通常的做法是,首先将数据库连接池的大小增大一倍,看看是否可以解决性能问题,如果可以,再逐步减少数据库连接池的值,找到性能瓶颈以及达到最优性能时连接池的大小。一般来讲,数据库连接池的值小于 Web 容器线程池的值是比较好的选择。

    在实际的环境中,我们可以利用 TPV 去监控数据库连接池的使用情况,以此来调整数据库连接池的大小,从而确定最优的调优策略。可以从 TPV 的以下监测值中寻找答案。

    表 1. TPV 监控列表
    监测值名称描述调优策略
    PooSize连接池的大小PooSize 会随着新连接的建立而增加,会随着连接的销毁而减少;应该为连接池设立一个最大值。
    PercentUsed连接池线程被使用的百分比如果该值长时间都很小,那么你应该调小 PooSize,反之应该增大。
    WaitingThreadCount单位时间内正在等待建立数据库连接的线程的个数系统最佳的性能体现在该值总是保持在很小的数目,如果该值偏大,则需要对系统进行调优
    PercentMaxed数据库所有连接都被使用的时间所占的百分比确保这个值不会长时间的达到 100%,如果是那样,那么你该考虑增大 PooSize 值

    可以使用 WAS 管理控制台进行数据库连接池的配置,位于 JDBC providers > Provider name > Data sources > Data source name > Connection pools

     

    结束语

    在本文中,我们详细的讨论了 WebSphere 服务器中池资源的概念以及调优,并在介绍 WebSphere 排队网络的基础上,阐述了如何在实际的生产环境中进行池资源配置。通过阅读本文,读者可以基本掌握 WebSphere 性能调优的一般准则,并能初步掌握性能优化的一些技巧和方法。

     

    end

  • 相关阅读:
    转发:招聘一个靠谱的 iOS
    转发:经典面试题
    APP上架证书无效:解决
    转发:Xcode插件
    Alcatraz:插件管理
    类似禅道的多条件搜索功能,比如或者并且和模糊查询和指定查询,见下图吧
    关于angularjs中,数据模型被改变,页面不刷新的解决办法
    angluar1+ionic详情页返回在原来的位置(缓存数据和页面高度)
    unable to resolve module react-native-gesture-handler from
    解决React Native:Error: Cannot find module 'asap/raw'
  • 原文地址:https://www.cnblogs.com/lindows/p/14390298.html
Copyright © 2011-2022 走看看