﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-gdufo-随笔分类-Tomcat</title><link>http://www.blogjava.net/gdufo/category/32717.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 02 Jun 2012 03:50:06 GMT</lastBuildDate><pubDate>Sat, 02 Jun 2012 03:50:06 GMT</pubDate><ttl>60</ttl><item><title>TOMCAT6配置负载均衡和集群 _2</title><link>http://www.blogjava.net/gdufo/archive/2012/06/02/379786.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Sat, 02 Jun 2012 00:55:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2012/06/02/379786.html</guid><description><![CDATA[<div><p><div>http://blog.csdn.net/dangerous_fire/article/details/6278435</div><br /></p><p>最近要配置tomcat集群，在网上搜了很多文章，但照着步骤一步一步做到最后却无法成功，着使我费了两天的劲查看了apache 和  tomcat的大量文档，才将问题一一解决。为方便自己和新手配置tomcat集群，我将整理好的过程晒一晒，希望可以帮到后来人少走一些弯路。</p> <p>==================</p> <p>目标: <br />使用 apache 和 tomcat 配置一个可以应用的 web 网站，要达到以下要求： <br />1、 Apache 做为 HttpServer ，后面连接多个 tomcat 应用实例，并进行负载均衡。 <br />2、 为系统设定 Session 超时时间，包括 Apache 和 tomcat<br />3、 为系统屏蔽文件列表，包括 Apache 和 tomcat</p> <p>注：本例程以一台机器为例子，即同一台机器上装一个apache和2个Tomcat。</p> <p>一、前期准备工作：安装用的程序（前提保证已安装了JDK1.5以上的版本）<br />APAHCE 2.2.8下载：apache_2.2.8-win32-x86-no_ssl.msi<br />TOMCAT6.0.14下载：apache-tomcat-6.0.14.zip直接解压。</p> <p>二、安装过程<br />APAHCE安装目录：D:/Apache。 <br />两个TOMCAT目录：自行解压到(D:/TomcatCluster/)下。<br />分别为 tomcat6-a，tomcat6-b</p> <p>三、配置 <br />1、Apache配置 <br />1.1 httpd.conf配置 <br />修改APACHE的配置文件D:/Apache/conf/httpd.conf </p> <p>这里并没有使用mod_jk.so进行apache和tomcat的链接，从2.X以后apache自身已集成了mod_jk.so的功能。只需简单的把下面几行去掉注释，就相当于以前用mod_jk.so比较繁琐的配置了。<br />这里主要采用了代理的方法，就这么简单。</p> <p>将以下Module的注释去掉<br />LoadModule proxy_module modules/mod_proxy.so <br />LoadModule proxy_connect_module modules/mod_proxy_connect.so <br />LoadModule proxy_ftp_module modules/mod_proxy_ftp.so <br />LoadModule proxy_http_module modules/mod_proxy_http.so <br />LoadModule proxy_ajp_module modules/mod_proxy_ajp.so <br />LoadModule proxy_balancer_module modules/mod_proxy_balancer.so </p> <p>再找到<br />&lt;IfModule dir_module&gt;<br />DirectoryIndex index.html<br />&lt;/IfModule&gt;<br />加上index.jsp修改成 </p> <p>&lt;IfModule dir_module&gt; <br />DirectoryIndex index.html index.jsp <br />&lt;/IfModule&gt; </p> <p>此处添加index.jsp 主要为了配置完成以后利用index.jsp输出测试信息！</p> <p>在 httpd.conf 最后面加入 <br />ProxyRequests Off <br />&lt;proxy balancer://cluster&gt; <br />BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=jvm1<br />BalancerMember ajp://127.0.0.1:9009 loadfactor=1 route=jvm2 <br />&lt;/proxy&gt; </p> <p>上面的两个BalancerMember成员是我们配置的tomcat集群。</p> <p><br />1.2 httpd-vhosts.conf设置 <br />接下来进行虚拟主机的设置。<br />APACHE的虚拟主机设置如下： <br />首先要修改 conf/httpd.conf<br />找到</p> <p># Virtual hosts<br />#Include conf/extra/httpd-vhosts.conf</p> <p>把Include语句注释去掉。改成 </p> <p># Virtual hosts <br />Include conf/extra/httpd-vhosts.conf </p> <p>在文件（extra/httpd-vhosts.conf）最下面加入 </p> <p>&lt;VirtualHost *:80&gt; <br />&nbsp;ServerAdmin adminname <br />&nbsp;ServerName localhost <br />&nbsp;ServerAlias localhost <br />&nbsp;ProxyPass / balancer://cluster/ stickysession=jsessionid nofailover=On lbmethod=bytraffic<br />&nbsp;ProxyPassReverse / balancer://cluster/ <br />&lt;/VirtualHost&gt; </p> <p>其中的域名和路径根据你自己情况设置 </p> <p>负载均衡有三种方式，可以通过设置 lbmethod 选择自己需要的方式，详细可查看apache文档</p> <p>proxy是位于客户端与实际的服务器之间的服务器，一般称为facade server，负责将外部的请求分流，也负责对内部的响应做一些必要的处理。<br />如果结合mod_cache，则可提高访问速度，适当的减轻网络流量压力。<br />闲话少说，直接拿个例子来：<br />&nbsp;&nbsp;&nbsp; 设本站地址为 <a href="http://www.test.com/">www.test.com</a><br />&nbsp;&nbsp;&nbsp; ProxyPass /images/ !<br />&nbsp;&nbsp;&nbsp; ProxyPass /js/ !<br />&nbsp;&nbsp;&nbsp; ProxyPass /css/ !<br />&nbsp;&nbsp;&nbsp; ProxyPass /example <a href="http://www.example.com/">http://www.example.com/</a><br />&nbsp;&nbsp;&nbsp; ProxyPassReverse /example <a href="http://www.example.com/">http://www.example.com/</a><br />&nbsp;&nbsp;&nbsp; ProxyPass / ajp://127.0.0.1:8009/<br />&nbsp;&nbsp;&nbsp; ProxyPassReverse / ajp://127.0.0.1:8009/<br />还是上一篇的例子，ProxyPass易理解，就是转发url上的请求，而其中的配置顺序也是需要遵守。<br />要禁止转发的url需要放在一般的请求之前。<br />对于<br /><a href="http://www.test.com/images/">http://www.test.com/images/</a>&nbsp; <br /><a href="http://www.test.com/js/">http://www.test.com/js/</a> <br /><a href="http://www.test.com/css/">http://www.test.com/css/</a><br />的请求是不予转发的，对于<a href="http://www.test.com/example/">http://www.test.com/example/</a>的请求，会转发到<a href="http://www.example.com/">http://www.example.com</a>。<br />值得注意的就是ProxyPassReverse的配置了，这是反向代理。<br />为什么要在这里加上这样的配置？我们来看个例子：<br />&nbsp;在没有加这样的反向代理设置的情况下，访问<a href="http://www.test.com/example/a">http://www.test.com/example/a</a>，<br />&nbsp;如果<a href="http://www.example.com/">www.example.com</a>对请求进行了redirect至<a href="http://www.example.com/b">http://www.example.com/b</a>，<br />&nbsp;那么，客户端就会绕过反向代理，进而访问<a href="http://www.test.com/example/b">http://www.test.com/example/b</a>。<br />&nbsp;如果设置了反向代理，则会在转交HTTP重定向应答到客户端之前调整它为<a href="http://www.test.com/example/a/b">http://www.test.com/example/a/b</a><br />&nbsp;即是在原请求之后追加上了redirect的路径。<br />更多更详细的关于mod_proxy的描述可以参见手册：<br /><a href="http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_proxy.html">http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_proxy.html</a> </p> <p><br />2 配置 tomcat <br />2.1 配置 server 的关闭 <br />我们需要在一台机器上跑两个不同的 tomcat ，需要修改不同的 tomcat 的关闭口，避免出现端口被占用的情况。<br />其中tomcat6-a用默认值，不修改。<br />tomcat6-b修改。在tomcat6-b/conf下的 server.xml 中找到 server, 将： <br />&lt;Server port="8005" shutdown="SHUTDOWN"&gt; <br />改为 <br />&lt;Server port="9005" shutdown="SHUTDOWN"&gt; </p> <p>2.2 配置 Engine <br />把原来的配置注释掉，把下面一句去掉注释。并标明jvmRoute="jvm2"<br />&lt;Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm2"&gt;</p> <p>以下是原来的配置。<br />&lt;Engine name="Catalina" defaultHost="localhost"&gt;<br />&nbsp;<br />2.3. 配置 Connector <br />原来的默认配置。 </p> <p>&lt;Connector port="8080" protocol="HTTP/1.1" <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionTimeout="20000" <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirectPort="8443" /&gt;</p> <p>&lt;!-- Define an AJP 1.3 Connector on port 8009 --&gt; <br />&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt; </p> <p>将tomcal6-b 中的 protocol="HTTP/1.1" 的 Connector 端口改为 8081 避免冲突。tomcat6-a 中的保持不变。<br />protocol="AJP/1.3" 的 Connector 是apache和tomcat链接的关键，前台apache就是通过AJP协议与tomcat进行通信的，以完成负载均衡的作用。<br />也可以用HTTP协议。大家注意它们是如何连接通信的，（port="8009"）就是连接的接口了。 </p> <p>把tomcat6-b的&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt; 中的port改成 9009 <br />&lt;proxy balancer://cluster&gt; <br />#与 tomcat6-a 对应，route与&lt;Engine jvmRoute="jvm1"&gt;对应。 <br />BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=jvm1 <br />#与 tomcat6-b 对应，route与&lt;Engine jvmRoute="jvm2"&gt;对应。 <br />BalancerMember ajp://127.0.0.1:9009 loadfactor=1 route=jvm2 <br />&lt;/proxy&gt; </p> <p>中的端口对应，<br />tomcat6-a 的ajp端口port:8009<br />tomcat6-b 的ajp端口port:9009<br />一定要与上面的一致。</p> <p>2.5.配置Cluster(两个tomcat中都要修改) <br />原来的配置。 <br />&lt;Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/&gt; <br />修改为以下的代码：&lt;Receiver port=&#8221;XX&#8221;/&gt;port也要保证唯一性。 </p> <p>&lt;Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"? channelSendOptions="6"&gt; <br />&nbsp;&lt;Manager className="org.apache.catalina.ha.session.BackupManager" <br />&nbsp;&nbsp;expireSessionsOnShutdown="false" <br />&nbsp;&nbsp;notifyListenersOnReplication="true" <br />&nbsp;&nbsp;mapSendOptions="6"/&gt; <br />&nbsp;&lt;!-- <br />&nbsp;&lt;Manager className="org.apache.catalina.ha.session.DeltaManager" <br />&nbsp;&nbsp;expireSessionsOnShutdown="false" <br />&nbsp;&nbsp;notifyListenersOnReplication="true"/&gt; <br />&nbsp;--&gt; <br />&nbsp;&lt;Channel className="org.apache.catalina.tribes.group.GroupChannel"&gt; <br />&nbsp;&nbsp;&lt;Membership className="org.apache.catalina.tribes.membership.McastService" <br />&nbsp;&nbsp;&nbsp;address="228.0.0.4" <br />&nbsp;&nbsp;&nbsp;port="45564" <br />&nbsp;&nbsp;&nbsp;frequency="500" <br />&nbsp;&nbsp;&nbsp;dropTime="3000"/&gt; <br />&nbsp;&nbsp;&lt;Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" <br />&nbsp;&nbsp;&nbsp;address="auto" <br />&nbsp;&nbsp;&nbsp;port="5001" <br />&nbsp;&nbsp;&nbsp;selectorTimeout="100" <br />&nbsp;&nbsp;&nbsp;maxThreads="6"/&gt; <br />&nbsp;&nbsp;&lt;Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"&gt; <br />&nbsp;&nbsp;&nbsp;&lt;Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/&gt; <br />&nbsp;&nbsp;&lt;/Sender&gt; <br />&nbsp;&nbsp;&lt;Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/&gt; <br />&nbsp;&nbsp;&lt;Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/&gt; <br />&nbsp;&nbsp;&lt;Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/&gt; <br />&nbsp;&lt;/Channel&gt; <br />&nbsp;&lt;Valve className="org.apache.catalina.ha.tcp.ReplicationValve" <br />&nbsp;&nbsp;filter=".*/.gif;.*/.js;.*/.jpg;.*/.png;.*/.htm;.*/.html;.*/.css;.*/.txt;"/&gt; <br />&nbsp;&lt;Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" <br />&nbsp;&nbsp;tempDir="/tmp/war-temp/" <br />&nbsp;&nbsp;deployDir="/tmp/war-deploy/" <br />&nbsp;&nbsp;watchDir="/tmp/war-listen/" <br />&nbsp;&nbsp;watchEnabled="false"/&gt; <br />&nbsp;&lt;ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/&gt; <br />&lt;/Cluster&gt; </p> <p>这个设置是主要用以tomcat的集群。<br />tomcat集群各节点通过建立tcp链接来完成Session的拷贝，拷贝有同步和异步两种模式。<br />在同步模式下，对客户端的响应必须在Session拷贝到其他节点完成后进行；异步模式无需等待Session拷贝完成就可响应。<br />异步模式更高效，但是同步模式可靠性更高。同步异步模式由channelSendOptions参数控制，默认值是8，为异步模式，4是同步模式。<br />在异步模式下，可以通过加上拷贝确认（Acknowledge）来提高可靠性，此时channelSendOptions设为10。</p> <p>Manager用来在节点间拷贝Session，默认使用DeltaManager，DeltaManager采用的一种all-to-all的工作方式，<br />即集群中的节点会把Session数据向所有其他节点拷贝，而不管其他节点是否部署了当前应用。<br />当集群中的节点数量很多并且部署着不同应用时，可以使用BackupManager，BackManager仅向部署了当前应用的节点拷贝Session。<br />但是到目前为止BackupManager并未经过大规模测试，可靠性不及DeltaManager。</p> <p>四、启动服务，测试tomcat自带的例子 <br />1、测试apache和tomcat协作。 <br />先在每个tomcat中的/webapps/ROOT下的index.jsp下面加上以下的测试代码部分：<br />(X代表不同的tomcat的输出不同的信息)，把index.html删除，以免影响测试效果。<br />在最后面的加上.即&lt;/table&gt;&lt;/body&gt;之间。 <br />&lt;% <br />&nbsp;System.out.println("tomcat6 A|B deal with request"); <br />%&gt; <br />然后再通过<a href="http://127.0.0.1/">http://127.0.0.1</a>来访问一下，就会出现大家熟悉的猫猫。 <br />然后再通过分别访问 <br /><a href="http://127.0.0.1:8080/">http://127.0.0.1:8080</a><br /><a href="http://127.0.0.1:8081/">http://127.0.0.1:8081</a></p> <p><br />它们访问的内容和上面的http:// 127.0.0.1是一样的。 <br />这样就说明apache和TOMCAT整合成功！ <br />2、测试均衡器 <br />如果在 extra/httpd-vhosts.conf 中配置 没有设置 lbmethod=bytraffic，将使用默认的 byrequests ，控制分配的一共有三种方式，还有一种是 bybusyness 。<br />通过<a href="http://127.0.0.1/">http://127.0.0.1</a>多次访问，<br />如 果使用的是 byrequests 的分配方式，要想看到真正的效果，必须用一些压力测试工具，可用微软Microsoft Web  Application Stress Tool进行简单压力测试，不然你靠不停刷新是体现不出来的，你只会在一个tomcat的控制台有输出结果。<br />只用用压力测试工具模拟大量用户同时访问，你会发现四个tomcat控制台均有打出控制信息，说明均衡器工作正常。 <br />而如果配置为 bytraffic 并且tomcat6-a 和 tomcat6-b 设置了 loadfactor=1，则请求会均匀的分配给不同的tomcat，很容易测试出来。<br />如果想对此感兴趣，请查看apache 的文档并尝试修改<br />httpd.conf<br />----------------------<br />ProxyRequests Off <br />&lt;proxy balancer://cluster&gt; <br />BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=jvm1<br />BalancerMember ajp://127.0.0.1:9009 loadfactor=1 route=jvm2 <br />&lt;/proxy&gt; <br />----------------------<br />&nbsp;中的 loadfactor&nbsp; 参数和<br />extra/httpd-vhosts.conf <br />----------------------<br />&lt;VirtualHost *:80&gt; <br />&nbsp;ServerAdmin adminname <br />&nbsp;ServerName localhost <br />&nbsp;ServerAlias localhost <br />&nbsp;ProxyPass / balancer://cluster/ stickysession=jsessionid nofailover=On lbmethod=bytraffic<br />&nbsp;ProxyPassReverse / balancer://cluster/ <br />&lt;/VirtualHost&gt; <br />----------------------<br />中的 lbmethod 参数</p> <p><br />注意：如果apache 中出现如下错误<br />Encountered too many errors accepting  client connections. Possible causes: dynamic address renewal, or  incompatible VPN or firewall software. Try using the  Win32DisableAcceptEx directive.</p> <p>编辑httpd.conf 加入<br />Win32DisableAcceptEx ##加入这行<br />重启apache就解决了。</p> <p>如果修改后还是不行，任然有错误记录，<br />cmd下<br />netsh winsock reset</p> 因为这个错误可能与winsock有关，有网友也出现了这个问题，他认为是金山毒霸或者升级精灵修改了WINSOCK导致的。我没有安装但是系统经常自动更新，别的软件也有,可能会有冲突。<br />使用此条命令恢复Winsock后，重启电脑后这个问题就会解决了。</div><img src ="http://www.blogjava.net/gdufo/aggbug/379786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2012-06-02 08:55 <a href="http://www.blogjava.net/gdufo/archive/2012/06/02/379786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat6.0负载均衡策略 _ 1</title><link>http://www.blogjava.net/gdufo/archive/2012/06/02/379785.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Sat, 02 Jun 2012 00:54:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2012/06/02/379785.html</guid><description><![CDATA[<div>http://www.cnblogs.com/shiyangxt/archive/2009/02/26/1398902.html</div><br /><div><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开学以后，连续几天休息不好，总是犯困，也许这就是&#8220;春困秋乏&#8221;的症状吧。最近老师提出了负载均衡功能的需求，以减轻</p> <p>网站的高峰期的服务器负担，现在学校的硬件设施还是蛮好的，有三，四台服务器可以提供使用，也很大程度的上方便了我做一些测试。</p> <p>因为这个子项目，假期三个同学已经基本完工，所以我也只能出点微薄之力，把这个负载均衡搞定，具体用不用我不管，起码是我的一个</p> <p>小功能。</p> <p>&nbsp;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其实无论是分布式，数据缓存，还是负载均衡，无非就是改善网站的性能瓶颈，在网站源码不做优化的情况下，负载均衡可以说</p> <p>是最直接的手段了。其实抛开这个名词，放开了说，就是希望用户能够分流，也就是说把所有用户的访问压力分散到多台服务器上，也可以</p> <p>分散到多个tomcat里，如果一台服务器装多个tomcat，那么即使是负载均衡，性能也提高不了太多，不过可以提高稳定性，即容错性。</p> <p>当其中一个主tomcat当掉，其他的tomcat也可以补上，因为tomcat之间实现了Session共享。待tomcat服务器修复后再次启动，就会</p> <p>自动拷贝所有session数据，然后加入集群。这样就可以不间断的提供服务。如果要真正从本质上提升性能，必须要分布到多台服务器。</p> <p>同样tomcat也可以做到。网上相关资料比较多，可以很方便的查到，但是质量不算高。我希望可以通过这篇随笔，系统的总结。本文的</p> <p>例子是同一台服务器上运行两个tomcat，做两个tomcat之间的负载均衡。其实多台服务器各配置一个tomcat也可以，而且那样的话，可以使用</p> <p>安装版的tomcat，而不用是下文中的免安装的tomcat，而且tomcat端口配置也就不用修改了。下文也会提到。</p> <p>&nbsp;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tomcat的负载均衡需要apache服务器的加入来实现。在进行配置之前请先卸载调已安装的tomcat，然后检查apache的版本。</p> <p>我这次配置使用的是apache-tomcat-6.0.18免安装版本，我亲自测试后推断安装版的tomcat在同一台机子上会不能启动两个以上，可能是</p> <p>因为安装版的tomcat侵入了系统，导致即使在server.xml里修改了配置，还是会引起冲突。所以我使用tomcat免安装版。</p> <p>apache使用的是apache_2.2.11-win32-x86-no_ssl.msi。如果版本低于2.2负载均衡的配置要有所不同，因为这个2.2.11和2.2.8版本</p> <p>集成了jk2等负载均衡工具，所以配置要简单许多。别的版本我没有具体测试，有待考究。这两个软件可以到官方网站下载。</p> <p>&nbsp;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把Apache安装为运行在80端口的Windows服务，安装成功后在系统服务列表中可以看到Apache2.2服务。服务启动后在浏览器中</p> <p>输入http://localhost进行测试，如果能看到一个"It works!"的页面就代表Apache已经正常工作了。把tomcat解压到任意目录，赋值一个另命名。</p> <p>起名和路径对配置没有影响。但要保证端口不要冲突，如果装有Oracle或IIS的用户需要修改或关闭相关接口的服务。当然jdk的配置也是</p> <p>必须的，这个不再过多叙述。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先，在Apache安装目录下找到conf/httpd.conf文件,去掉以下文本前的注释符（#）以便让Apache在启动时自动加载代理（proxy）</p> <p>模块。</p> <p>&nbsp;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;LoadModule proxy_module modules/mod_proxy.so<br /> &nbsp;&nbsp;&nbsp;&nbsp; LoadModule proxy_ajp_module modules/mod_proxy_ajp.so<br /> &nbsp;&nbsp;&nbsp;&nbsp; LoadModule proxy_balancer_module modules/mod_proxy_balancer.so<br /> &nbsp;&nbsp;&nbsp;&nbsp; LoadModule proxy_connect_module modules/mod_proxy_connect.so<br /> &nbsp;&nbsp;&nbsp;&nbsp; LoadModule proxy_ftp_module modules/mod_proxy_ftp.so<br /> &nbsp;&nbsp;&nbsp;&nbsp; LoadModule proxy_http_module modules/mod_proxy_http.so</p> <p>&nbsp;</p> <p>向下拉动文档找到&lt;IfModule dir_module&gt;节点，在DirectoryIndex index.html后加上index.jsp，这一步只是为了待会配置完tomcat后能看到小</p> <p>猫首页，可以不做。继续下拉文档找到Include conf/extra/httpd-vhosts.conf，去掉前面的注释符。</p> <p>&nbsp; </p> <p style="margin-bottom: 0cm">然后打开conf/extra/httpd-vhosts.conf，配置虚拟站点，在最下面加上</p> <p>&nbsp;</p> <div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div><span style="color: #0000ff">&lt;</span><span style="color: #800000">VirtualHost&nbsp;</span><span style="color: #ff0000">*:80</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerAdmin&nbsp;管理员邮箱<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerName&nbsp;localhost<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerAlias&nbsp;localhost&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProxyPass&nbsp;/&nbsp;balancer://sy/&nbsp;stickysession=jsessionid&nbsp;nofailover=On&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProxyPassReverse&nbsp;/&nbsp;balancer://sy/&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ErrorLog&nbsp;"logs/sy-error.log"<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomLog&nbsp;"logs/sy-access.log"&nbsp;common<br /> </span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">VirtualHost</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> <br /> </span><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div></div> <p>&nbsp;</p> <p>然后回到httpd.conf，在文档最下面加上</p> <p>&nbsp;</p> <div><span style="color: #000000">ProxyRequests&nbsp;Off&nbsp;<br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">proxy&nbsp;</span><span style="color: #ff0000">balancer://sy</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BalancerMember&nbsp;ajp://127.0.0.1:8009&nbsp;loadfactor=1&nbsp;route=jvm1<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BalancerMember&nbsp;ajp://127.0.0.1:9009&nbsp;loadfactor=1&nbsp;route=jvm2<br /> </span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">proxy</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span></div> <p>&nbsp;</p> <p>ProxyRequests Off 是告诉Apache需要使用反向代理，ip地址和端口唯一确定了tomcat节点和配置的ajp接受端口。loadfactor是负载因子，</p> <p>Apache会按负载因子的比例向后端tomcat节点转发请求，负载因子越大，对应的tomcat服务器就会处理越多的请求，如两个tomcat都</p> <p>是1，Apache就按1：1的比例转发，如果是2和1就按2：1的比例转发。这样就可以使配置更灵活，例如可以给性能好的服务器增加处理</p> <p>工作的比例，如果采取多台服务器，只需要修改ip地址和端口就可以了。route参数对应后续tomcat配置中的引擎路径（jvmRoute）。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果仅仅为了配置一个可用的集群，Tomcat的配置将会非常简单。分别打开两个tomcat的server.xml配置文件，其中一台可以采用默认</p> <p>的设置，只需要修改两个地方，而另一个要有较大改动以避免与前一台冲突。如果两台不在同一台服务器上运行，对于端口就不需做改动。首先是</p> <p>配置关闭端口，找到&lt;Server port="8005" shutdown="SHUTDOWN"&gt;，第一台不变，把第二台改为9005。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面配置Connector的端口，找到non-SSL HTTP/1.1 Connector，即tomcat单独工作时的默认Connector，保留第一台默认配置，在8080端</p> <p>口侦听，而把第二台设置为在9080端口侦听。往下找到AJP 1.3 Connector，&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt;，这是</p> <p>tomcat接收从Apache过来的ajp连接请求时使用的端口，保留第一台默认设置，把第二台端口改为9009。第一台tomcat的server.xml中找到</p> <p>&lt;Engine name="Catalina" defaultHost="localhost"&gt;，去掉这段或改为注释，把上方紧挨的&lt;Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"&gt;</p> <p>注释符去掉，对于第二台，去掉注释符并把jvm1改为jvm2。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;向下找到&lt;Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/&gt;，去掉注释，这里的配置是为了可以在集群中的所有tomcat节点</p> <p>间共享会话（Session）。如果仅仅为了获得一个可用的tomcat集群，Cluster只需要这么配置就可以了。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只需要简单的几步就配置完成，然后可以测试一下是否配置成功。引用网上的一个测试方法，就是在webapps目录下新建test目录，在test目</p> <p>录下新建test.jsp文件，代码我稍作改动如下：</p> <p>&nbsp;</p> <div><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@&nbsp;page&nbsp;contentType</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">text/html;&nbsp;charset=GBK</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br /> </span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@&nbsp;page&nbsp;import</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">java.util.*</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">shiyang</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> 服务信息:<br /> </span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5"><br /> out.println(request.getLocalAddr()&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">+</span>&nbsp;<span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&nbsp;:&nbsp;</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;request.getLocalPort()</span><span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&lt;br/&gt;</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br /> </span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5"><br /> out.println(</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&lt;br&gt;&nbsp;ID&nbsp;</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;session.getId()</span><span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&lt;br/&gt;</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);&nbsp;<br /> </span><span style="color: #0000ff; background-color: #f5f5f5">String</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;dataName&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;request.getParameter(</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">dataName</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br /> <br /> </span><span style="color: #0000ff; background-color: #f5f5f5">if</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;(dataName&nbsp;!</span><span style="color: #000000; background-color: #f5f5f5">=</span>&nbsp;<span style="color: #0000ff; background-color: #f5f5f5">null</span>&nbsp;<span style="color: #000000; background-color: #f5f5f5">&amp;&amp;</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;dataName.length()&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">&gt;</span>&nbsp;<span style="color: #800080; background-color: #f5f5f5">0</span><span style="color: #000000; background-color: #f5f5f5">)&nbsp;{<br /> </span><span style="color: #0000ff; background-color: #f5f5f5">String</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;dataValue&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;request.getParameter(</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">dataValue</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br /> session.setAttribute(dataName,&nbsp;dataValue);<br /> }<br /> <br /> out.print(</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&lt;b&gt;Session&nbsp;列表&lt;/b&gt;&lt;br/&gt;</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br /> Enumeration&nbsp;e&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;session.getAttributeNames();<br /> <br /> </span><span style="color: #0000ff; background-color: #f5f5f5">while</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;(e.hasMoreElements())&nbsp;{<br /> </span><span style="color: #0000ff; background-color: #f5f5f5">String</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;name&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;(</span><span style="color: #0000ff; background-color: #f5f5f5">String</span><span style="color: #000000; background-color: #f5f5f5">)e.nextElement();<br /> </span><span style="color: #0000ff; background-color: #f5f5f5">String</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;value&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;session.getAttribute(name).toString();<br /> out.println(&nbsp;name&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">+</span>&nbsp;<span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&nbsp;=&nbsp;</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;value</span><span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&lt;br/&gt;</span><span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">);<br /> System.out.println(&nbsp;name&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">+</span>&nbsp;<span style="color: #800000; background-color: #f5f5f5">"</span><span style="color: #800000; background-color: #f5f5f5">&nbsp;=&nbsp;</span><span style="color: #800000; background-color: #f5f5f5">"</span>&nbsp;<span style="color: #000000; background-color: #f5f5f5">+</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;value);<br /> }<br /> </span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">form&nbsp;</span><span style="color: #ff0000">action</span><span style="color: #0000ff">="test.jsp"</span><span style="color: #ff0000">&nbsp;method</span><span style="color: #0000ff">="POST"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> 名称:</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">input&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=text&nbsp;</span><span style="color: #ff0000">size</span><span style="color: #0000ff">=20&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="dataName"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">br</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /> 值:</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">input&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=text&nbsp;</span><span style="color: #ff0000">size</span><span style="color: #0000ff">=20&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="dataValue"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">br</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;</span><span style="color: #800000">input&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=submit&nbsp;</span><span style="color: #ff0000">value</span><span style="color: #0000ff">="提交"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">form</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span><div><a title="复制代码"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" /></a></div></div> <p>&nbsp; </p> <p>在test目录下继续新建WEB-INF目录和web.xml，在&lt;web-app&gt;节点下加入&lt;distributable /&gt;，这一步非常重要，是为了通知tomcat服务器，</p> <p>当前应用需要在集群中的所有节点间实现Session共享。如果tomcat中的所有应用都需要Session共享，也可以把conf/context.xml中的</p> <p>&lt;Context&gt;改为&lt;Context distributable="true"&gt;，这样就不需对所有应用的web.xml再进行单独配置。测试代码完成！</p> <p>&nbsp;</p> <p>先启动Apache服务，在先后启动两台tomcat，分别点startup.bat批处理。如果一切顺利的话，就会启动成功。再次访问<a href="http://localhost/">http://localhost</a>，</p> <p>可以看到小猫页面。访问<a href="http://localhost/test/test.jsp">http://localhost/test/test.jsp</a>。可以看到包括服务器地址，端口，session等信息在内的页面。</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后你可以测试一下容错功能，关闭一个tomcat，看看服务是否正常，然后重启tomcat，关掉另一台tomcat，看看</p> <p>是否也可以继续提供服务。当然你也可以配置多台tomcat，但是原理都一样。</p> <p>&nbsp;OK，讲到这里。</p></div><img src ="http://www.blogjava.net/gdufo/aggbug/379785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2012-06-02 08:54 <a href="http://www.blogjava.net/gdufo/archive/2012/06/02/379785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jmeter测试zkoss</title><link>http://www.blogjava.net/gdufo/archive/2012/05/31/379700.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Thu, 31 May 2012 15:35:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2012/05/31/379700.html</guid><description><![CDATA[<div>http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example</div><div><div id="toctitle"><h2>Contents</h2> [<a id="togglelink">hide</a>]</div> <ul><li tocsection-1"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Preface">1 Preface</a></li><li tocsection-2"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Test_plan">2 Test plan</a> <ul><li tocsection-3"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Setup">2.1 Setup</a></li><li tocsection-4"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Test_Scenario">2.2 Test Scenario</a></li></ul> </li><li tocsection-5"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Before_we_start">3 Before we start</a></li><li tocsection-6"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Configuring_ZK">4 Configuring ZK</a></li><li tocsection-7"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Preparing_Testing_Scripts">5 Preparing Testing Scripts</a> <ul><li tocsection-8"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Load_CSV_file_as_the_variable_of_the_user_name_and_password">5.1 Load CSV file as the variable of the  user name and password</a></li><li tocsection-9"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Set_account_.26_password_as_variables">5.2 Set account &amp; password as variables</a></li><li tocsection-10"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Generate_new_desktop_ID_for_redirecting_to_a_new_page">5.3 Generate new desktop ID for redirecting to a new page</a></li><li tocsection-11"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Specify_parameter">5.4 Specify parameter</a></li><li tocsection-12"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Add_the_listeners_for_creating_reports">5.5 Add the listeners for creating reports</a></li></ul> </li><li tocsection-13"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Running_the_test">6 Running the test</a></li><li tocsection-14"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Trouble-shooting_.26_Tips">7 Trouble-shooting &amp; Tips</a></li><li tocsection-15"=""><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Downloads">8 Downloads</a></li><li><a href="http://books.zkoss.org/wiki/Small_Talks/2012/May/Perform_stress_test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Comments">9 Comments</a></li></ul>  <h1> <span id="Preface">Preface</span></h1> <p>Dennis Chen has shared a small talk illustrating how you can <a href="http://books.zkoss.org/index.php?title=Small_Talks/2012/January/Execute_a_Loading_or_Performance_Test_on_ZK_using_JMeter"  text"="" rel="nofollow">execute a loading test with ZK applications using JMeter</a>.  Now, in this small talk we will take a real application as an example  to demonstrate in detail how you can actually apply the ideas  illustrated in Dennis&#8217; article to perform a stress test. </p> <h1> <span id="Test_plan">Test plan</span></h1> <p>We will be using the "shopping cart" example from <a href="http://books.zkoss.org/wiki/ZK_Essentials"  text"="" rel="nofollow">ZK Essentials</a> as the template application to perform the stress test. </p> <h4> <span id="Setup">Setup</span></h4> <ul><li>ZK 5.0.11 </li><li>zk testing demo ( a demo based on the shopping cart sample) </li><li>Jmeter 2.5.1 </li></ul> <h4> <span id="Test_Scenario">Test Scenario</span></h4> <ol><li>User enters his user name and password for authentication </li><li>Login successfully to the shopping site, redirect to index.zul </li><li>User selects an item and drag to the shopping cart </li><li>User checks out  </li></ol> <p>Since this is a stress test, we can apply 50, 100, 150,... concurrent  users to perform the test scenario simultaneously. In our example we  have created a max of 300 accounts, which allows you to perform the test  with as many as 300 concurrent users. </p> <h1> <span id="Before_we_start">Before we start</span></h1> <p>As mentioned above we will be using the "shopping cart" example from  ZK Essentials as the template application. However there is only one set  of login/password in the current shopping cart implementation which is  not sufficient for multiple users. To support multiple users, we have  modified the shopping cart example to generate multiple accounts, so  that each user will be logged in using a different account. This is done  as follows, and it will be triggered as you click "createUserBtn" in  login.zul: </p><p><strong>1. prepare a CSV file that includes a list of user names and passwords:</strong> </p><p><a href="http://books.zkoss.org/wiki/File:Csv.png"><img alt="Csv.png" src="http://books.zkoss.org/images/thumb/f/f3/Csv.png/300px-Csv.png" height="458" width="300" /></a> </p><p><strong>2. Add the following code to LoginViewCtrl.java</strong> </p> <div><div id="highlighter_597589"  java"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div><div number22="" index21=""  alt1"="">22</div></td><td><div><div number1="" index0=""  alt2"=""><code keyword"="">public</code> <code keyword"="">void</code> <code plain"="">onClick$createUserBtn() {</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">Map map = userinfo();</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">Session session = StoreHibernateUtil.openSession();</code></div><div number4="" index3=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">Transaction t = session.beginTransaction();</code></div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code>&nbsp;</div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">Iterator entries = map.entrySet().iterator();</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">int</code> <code plain"="">i = </code><code value"="">0</code><code plain"="">;</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">while</code> <code plain"="">(entries.hasNext()) {</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">i ++;</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">Map.Entry entry = (Map.Entry) entries.next();</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">String name = (String)entry.getKey();</code></div><div number12="" index11=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">String pwd = (String)entry.getValue();</code></div><div number13="" index12=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">User user = </code><code keyword"="">new</code> <code plain"="">User(i, name, pwd, </code><code string"="">"user"</code><code plain"="">);</code></div><div number14="" index13=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">session.save(user);</code></div><div number15="" index14=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">if</code> <code plain"="">(i&nbsp;% </code><code value"="">20</code> <code plain"="">== </code><code value"="">0</code><code plain"="">) { </code></div><div number16="" index15=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">session.flush();</code></div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">session.clear();</code></div><div number18="" index17=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number19="" index18=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number20="" index19=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">t.commit();</code></div><div number21="" index20=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">session.close();</code></div><div number22="" index21=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <h1> <span id="Configuring_ZK">Configuring ZK</span></h1> <ul><li>Set <a href="http://www.zkoss.org/javadoc/latest/zk/org/zkoss/zk/ui/sys/IdGenerator.html"  text"="" rel="nofollow">IdGenerator</a> for your ZK app </li></ul> <p>As illustrated in <a href="http://books.zkoss.org/index.php?title=Small_Talks/2012/January/Execute_a_Loading_or_Performance_Test_on_ZK_using_JMeter"  text"="" rel="nofollow">Dennis&#8217; small talk</a>,  you need to define IdGenerator to fix the desktop IDs and component IDs  so that we can record and play the testing script. The IdGenerator is  implemented as follows: </p> <div><div id="highlighter_285917"  java"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div><div number22="" index21=""  alt1"="">22</div><div number23="" index22=""  alt2"="">23</div><div number24="" index23=""  alt1"="">24</div><div number25="" index24=""  alt2"="">25</div><div number26="" index25=""  alt1"="">26</div><div number27="" index26=""  alt2"="">27</div><div number28="" index27=""  alt1"="">28</div></td><td><div><div number1="" index0=""  alt2"=""><code keyword"="">public</code> <code keyword"="">class</code> <code plain"="">MyIdgenerator </code><code keyword"="">implements</code> <code plain"="">IdGenerator {</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">private</code> <code keyword"="">static</code> <code plain"="">ThreadLocal&lt;HttpServletResponse&gt; response = </code><code keyword"="">new</code> <code plain"="">ThreadLocal&lt;HttpServletResponse&gt;();</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">private</code> <code keyword"="">static</code> <code plain"="">AtomicInteger ai = </code><code keyword"="">new</code> <code plain"="">AtomicInteger();</code></div><div number4="" index3=""  alt1"="">&nbsp;</div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">public</code> <code plain"="">String nextComponentUuid(Desktop desktop, Component comp) {</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">String number;</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">if</code> <code plain"="">((number = (String) desktop.getAttribute(</code><code string"="">"Id_Num"</code><code plain"="">)) == </code><code keyword"="">null</code><code plain"="">) {</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">number = </code><code string"="">"0"</code><code plain"="">;</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">desktop.setAttribute(</code><code string"="">"Id_Num"</code><code plain"="">, number);</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">int</code> <code plain"="">i = Integer.parseInt(number);</code></div><div number12="" index11=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">i++;</code><code comments"="">// Start from 1</code></div><div number13="" index12=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">desktop.setAttribute(</code><code string"="">"Id_Num"</code><code plain"="">, String.valueOf(i));</code></div><div number14="" index13=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code string"="">"t_"</code> <code plain"="">+ i;</code></div><div number15="" index14=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number16="" index15=""  alt1"="">&nbsp;</div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">public</code> <code plain"="">String nextDesktopId(Desktop desktop) {</code></div><div number18="" index17=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">HttpServletRequest req = (HttpServletRequest)Executions.getCurrent().getNativeRequest();</code></div><div number19="" index18=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">String dtid = req.getParameter(</code><code string"="">"tdtid"</code><code plain"="">);</code></div><div number20="" index19=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">if</code><code plain"="">(dtid!=</code><code keyword"="">null</code><code plain"="">){</code></div><div number21="" index20=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number22="" index21=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code plain"="">dtid==</code><code keyword"="">null</code><code plain"="">?</code><code keyword"="">null</code><code plain"="">:dtid;</code></div><div number23="" index22=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number24="" index23=""  alt1"="">&nbsp;</div><div number25="" index24=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">public</code> <code plain"="">String nextPageUuid(Page page) {</code></div><div number26="" index25=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code keyword"="">null</code><code plain"="">;</code></div><div number27="" index26=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number28="" index27=""  alt1"=""><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <ul><li>Define your IdGenerator in zk.xml </li></ul> <p>Then, define your IdGenerator in zk.xml, for example, </p> <div><div id="highlighter_867587"  xml"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">&lt;</code><code keyword"="">system-config</code><code plain"="">&gt;</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">id-generator-class</code><code plain"="">&gt;foo.MyIdgenerator&lt;/</code><code keyword"="">id-generator-class</code><code plain"="">&gt;</code></div><div number3="" index2=""  alt2"=""><code plain"="">&lt;/</code><code keyword"="">system-config</code><code plain"="">&gt;</code></div></div></td></tr></tbody></table></div></div> <h1> <span id="Preparing_Testing_Scripts">Preparing Testing Scripts</span></h1> <p>Now we are ready to record the scripts. We will be recording 6 HTTP  requests as illustrated in the image below. What we need to do is to  configure the parameters of these 6 requests based on the application  that we wish to test. </p><p><a href="http://books.zkoss.org/wiki/File:All.png"><img alt="All.png" src="http://books.zkoss.org/images/thumb/4/4f/All.png/300px-All.png" height="340" width="300" /></a> </p> <h3> <span id="Load_CSV_file_as_the_variable_of_the_user_name_and_password">Load CSV file as the variable of the  user name and password</span></h3> <ul><li><strong>Add a  CSV Data Set Config</strong> </li></ul> <p>First we need to add a CSV Data Set Config here. The element will  iterate the csv data set to simulate muti-users login into the  application. Please specify a fully qualified name to the Filename field  (ex: C:\mycsv\users.csv ), and specify the variable name to the  Variable Names field for later use. </p><p><a href="http://books.zkoss.org/wiki/File:Csv_data_set.png"><img alt="Csv data set.png" src="http://books.zkoss.org/images/thumb/4/4f/Csv_data_set.png/700px-Csv_data_set.png" height="498" width="700" /></a> </p> <ul><li><strong>Add BSF PostProcessor</strong> </li></ul> <p>Then we need to ask jmeter to generate the accounts and passwords  automatically based on our CSV file. What we need to do is to add a BSF  PostProcessor element, set the language to beanshell, and define: </p><p><br /> var username = vars.get("username"); </p><p>var password = vars.get("password"); </p><p>vars.put("user","{\"value\":\""+username+"\",\"start\":2}"); </p><p>vars.put("pwd","{\"value\":\""+password+"\",\"start\":2}"); </p><p><br /> This script will get the username and password variables generated by  CSV Data Set Config element, and combine the result and some text as a  parameter which will be used as user names and passwords later. </p><p><a href="http://books.zkoss.org/wiki/File:BSF_PostProcessor.png"><img alt="BSF PostProcessor.png" src="http://books.zkoss.org/images/thumb/8/84/BSF_PostProcessor.png/700px-BSF_PostProcessor.png" height="385" width="700" /></a> </p> <h3> <span id="Set_account_.26_password_as_variables">Set account &amp; password as variables</span></h3> <p>With these settings ready, we can now set the parameter dtid as  ${dtid} and use EL to replace a fixed account and password in the first  ajax request (i.e. the login request). For example if we send zk/zk as user name and password, then we will be  seeing  </p><p><em>data_3: {"value":"zk","start":2}</em> //for username </p><p><em>data_4: {"value":"zk","start":2}</em> //for password </p><p>in the recorded jmeter&#8217;s request. Then, we use ${user} and ${pwd}  to replace {"value":"zk","start":2} for handling the accounts and  passwords dynamically. </p><p><a href="http://books.zkoss.org/wiki/File:Submit.png"><img alt="Submit.png" src="http://books.zkoss.org/images/thumb/d/dc/Submit.png/400px-Submit.png" height="304" width="400" /></a> </p> <h3> <span id="Generate_new_desktop_ID_for_redirecting_to_a_new_page">Generate new desktop ID for redirecting to a new page</span></h3> <p>After an user logged into the system, he will be redirected to  index.zul. Since the URL is changed, the desktop and it&#8217;s id will also  be changed, we need to retrieve the desktop id again using  ${__intSum(${dtid},1,dtid)}. </p> <h3> <span id="Specify_parameter">Specify parameter</span></h3> <p>The last 3 http requests are for adding products to the shopping  cart, check out, and close the browser tab. What we need to do is just  to modify their tdtid to ${__intSum(${dtid},1,dtid). </p><p><a href="http://books.zkoss.org/wiki/File:DTID.png"><img alt="DTID.png" src="http://books.zkoss.org/images/4/48/DTID.png" height="494" width="900" /></a> </p> <h3> <span id="Add_the_listeners_for_creating_reports">Add the listeners for creating reports</span></h3> <p>There are many different elements that allows you to generate  different kinds of reports, such as Aggregate Report and Graph Results.  You can add these listeners to Thread Group or HTTP request depending on  the report you wish to generate. </p><p><a href="http://books.zkoss.org/wiki/File:Listener1.png"><img alt="Listener1.png" src="http://books.zkoss.org/images/4/4f/Listener1.png" height="250" width="400" /></a> </p><p>Now we have completed all the settings and have saved these configurations as test.jmx. </p> <h1> <span id="Running_the_test">Running the test</span></h1> <p>Now we are ready to start the application and to run the test. </p> <ol><li><strong>Generate accounts</strong></li><p>Start your web server, and access login.zul. Click <strong>createUserBtn</strong> for creating multiple accounts. </p><p><a href="http://books.zkoss.org/wiki/File:CreateAccounts.png"><img alt="CreateAccounts.png" src="http://books.zkoss.org/images/thumb/8/8d/CreateAccounts.png/400px-CreateAccounts.png" height="273" width="400" /></a> </p><li><strong>Run the testing script</strong></li><ol type="a"><li>Open jmeter&#8217;s menu, File &gt; Open , and load test.jmx.</li><li>Specify your IP and port, for example we use localhost/8080 as ip and port number</li><p><a href="http://books.zkoss.org/wiki/File:Http_request_default.png"><img alt="Http request default.png" src="http://books.zkoss.org/images/thumb/5/50/Http_request_default.png/800px-Http_request_default.png" height="245" width="800" /></a> </p><li>In Thread Group ( the root  element), set the number of concurrent users to test.</li><p><a href="http://books.zkoss.org/wiki/File:Set_number_of_Users_.png"><img alt="Set number of Users .png" src="http://books.zkoss.org/images/thumb/4/42/Set_number_of_Users_.png/400px-Set_number_of_Users_.png" height="341" width="400" /></a> </p><li>Perform Run &gt; Start to run the test.</li><p>You can then observe the average response time, 90% line response  time, median response time and other results by accessing the Aggregate  Report . </p><p><a href="http://books.zkoss.org/wiki/File:Aggregate_report.png"><img alt="Aggregate report.png" src="http://books.zkoss.org/images/thumb/8/8a/Aggregate_report.png/700px-Aggregate_report.png" height="337" width="700" /></a> </p></ol></ol> <h1> <span id="Trouble-shooting_.26_Tips">Trouble-shooting &amp; Tips</span></h1> <ol><li><strong>Tips: Performing repeating tests</strong></li><p>If you have finished a round of test (for example 0~50) you should  restart your server before performing another round of test. This is  because after you finish a round of test, there will be an extra item  listed in each user&#8217;s page because they all ordered an item. This extra  item is displayed at the bottom of the page (see the image on the  right). As there is a DOM change due to this extra item, components&#8217; IDs  and orders are also changed thus different from the script you recorded  earlier. To solve this problem, just restart your server before  performing another round of test. </p><p><a href="http://books.zkoss.org/wiki/File:Without_order.png"><img alt="Without order.png" src="http://books.zkoss.org/images/thumb/2/2c/Without_order.png/400px-Without_order.png" height="242" width="400" /></a> <a href="http://books.zkoss.org/wiki/File:One_order.png"><img alt="One order.png" src="http://books.zkoss.org/images/thumb/7/72/One_order.png/400px-One_order.png" height="218" width="400" /></a> </p><li><strong>Trouble-shooting: Erred response</strong></li><p><a href="http://books.zkoss.org/wiki/File:Nothing_response.png"><img alt="Nothing response.png" src="http://books.zkoss.org/images/thumb/8/8f/Nothing_response.png/700px-Nothing_response.png" height="299" width="700" /></a> </p><p>If you encounter the Response data error shown as the image above, it is most likely that you did not implement <strong>IdGenerator</strong> correctly. Please refer to <a href="http://books.zkoss.org/wiki/Small_Talks/2011/December/Execute_a_Loading_or_Performance_Test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Configuring_ZK"  text"="" rel="nofollow">Configuring ZK section</a> to implement UUID. </p><li><strong>Trouble-shooting: Timeout error</strong></li><p><a href="http://books.zkoss.org/wiki/File:Timeout.png"><img alt="Timeout.png" src="http://books.zkoss.org/images/thumb/8/87/Timeout.png/700px-Timeout.png" height="316" width="700" /></a> </p><p>Timeout errors occur when the desktop id in the Ajax request is  no longer available at the server side. This normally happens when the  URL is changed. If this happens, you need to retrieve desktop ID again.   Please refer to <a href="http://books.zkoss.org/wiki/Small_Talks/2011/December/Execute_a_Loading_or_Performance_Test_on_ZK_using_JMeter-take_Shopping_Cart_as_an_example#Generate_new_desktop_ID_for_redirect_to_a_new_page"  text"="" rel="nofollow">Testing Scripts section</a> to implement Desktop ID. </p><p>Timeout may also relate to the max allowed desktops. In ZK there  is a setting called &#8220;max-desktops-per-session&#8221; which defines the max  concurrent desktops for each session. The more browser tabs an user  opens the more desktops will be saved on the session. If the number  exceeds the max allowed desktops then some desktops will be dropped with  the timeout error. </p><p>By default the number is 15 which means an user can open as many  as 15 tabs in a same browser at the same time. If you have configured it  to a smaller number for saving the memory, and in your use case the  users will be opening up multiple tabs then you should double check  whether this is the reason causing the timeout error. To change this  setting, use: </p><div><div id="highlighter_323723"  xml"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">&lt;</code><code keyword"="">session-config</code><code plain"="">&gt;</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">max-desktops-per-session</code><code plain"="">&gt;1&lt;/</code><code keyword"="">max-desktops-per-session</code><code plain"="">&gt;</code></div><div number3="" index2=""  alt2"=""><code plain"="">&lt;/</code><code keyword"="">session-config</code><code plain"="">&gt;</code></div></div></td></tr></tbody></table></div></div><li><strong>Tips: close browser tab for saving memory</strong></li><p>ZK stores desktops in sessions, when user closes the browser tab ZK will send the rmDesktop command to remove the desktop. We can simulate this behavior to save memory when performing a stress test. This is done in the last http request defined in <strong>test.jmx</strong>. You can refer to the image below: </p><p><a href="http://books.zkoss.org/wiki/File:RmDesktop.png"><img alt="RmDesktop.png" src="http://books.zkoss.org/images/7/70/RmDesktop.png" height="521" width="850" /></a> </p></ol> <h1> <span id="Downloads">Downloads</span></h1> <p>users.csv - <a href="http://sourceforge.net/projects/zkforge/files/Small%20Talks/Performance%20Test%20on%20ZK/users.csv/download"  text"="" rel="nofollow">users.csv</a> (Please place the csv file under C:/mycsv/) </p><p>zk testing demo &#8211; <a href="http://sourceforge.net/projects/zkforge/files/Small%20Talks/Performance%20Test%20on%20ZK/shoppingcart_jmtest.war/download"  text"="" rel="nofollow">the modified shopping cart application used in this small talk</a> </p><p>jmeter 2.5.1 &#8211; <a href="http://jmeter.apache.org/download_jmeter.cgi"  free"="" rel="nofollow">http://jmeter.apache.org/download_jmeter.cgi</a> </p><p>test.jmx &#8211; <a href="http://sourceforge.net/projects/zkforge/files/Small%20Talks/Performance%20Test%20on%20ZK/test.jmx/download"  text"="" rel="nofollow">test.jmx</a> </p><p><br /> </p></div><img src ="http://www.blogjava.net/gdufo/aggbug/379700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2012-05-31 23:35 <a href="http://www.blogjava.net/gdufo/archive/2012/05/31/379700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5.5配置-多域名绑定和虚拟目录 </title><link>http://www.blogjava.net/gdufo/archive/2009/01/06/250021.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Tue, 06 Jan 2009 00:30:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2009/01/06/250021.html</guid><wfw:comment>http://www.blogjava.net/gdufo/comments/250021.html</wfw:comment><comments>http://www.blogjava.net/gdufo/archive/2009/01/06/250021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gdufo/comments/commentRss/250021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gdufo/services/trackbacks/250021.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Tomcat5.5配置-多域名绑定和虚拟目录 &nbsp;&nbsp;<a href='http://www.blogjava.net/gdufo/archive/2009/01/06/250021.html'>阅读全文</a><img src ="http://www.blogjava.net/gdufo/aggbug/250021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2009-01-06 08:30 <a href="http://www.blogjava.net/gdufo/archive/2009/01/06/250021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat管理界面常用设置 -- 不解压war文件</title><link>http://www.blogjava.net/gdufo/archive/2008/07/02/212193.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Wed, 02 Jul 2008 12:17:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2008/07/02/212193.html</guid><description><![CDATA[转：http://blog.csdn.net/cm4ever/archive/2004/10/24/148930.aspx<br />
<br />
<p>当 <br />
1. war文件内的WEB-INF/classes目录下的所有class文件<br />
2. war文件内的/WEB-INF/lib目录下的所有jar文件<br />
3. war文件内的/WEB-INF目录下的web.xml文件<br />
4. war文件内的环境配置文件<br />
上述四项中的任一项改变后自动重载。这样就无须手工重新deploy，节省调试时间。<br />
<br />
1.登陆管理界面<br />
<a href="http://localhost:8080/admin">http://localhost:8080/admin</a></p>
<p>密码和用户名在你安装的时候设定的，如果忘记(或没有)的话，去改tomcat\conf\tomcat-users.xml，添加admin和 manager两个role，一个用户，该用户的role为admin和manager就可以了，按原有的xml复制修改就可以。<br />
<br />
2.设置步骤<br />
&nbsp; 2.1 点击左边框架中Service菜单项左边的小圆，展开列表&nbsp;<br />
&nbsp; 2.2 点击左边框架中Host (localhost)菜单项，右边框架出现设置页<br />
&nbsp; 2.3 把右边框架中Unpack WARs右边的下拉列表改为false<br />
&nbsp; 2.4 点击右边框架中右上角save按钮&nbsp;<br />
&nbsp; 2.5 点击顶部框架Commit Changes按钮<br />
<br />
注意：<span style="color: red"><strong>要保证文件不是只读的</strong></span></p>
<br />
<br />
<img src ="http://www.blogjava.net/gdufo/aggbug/212193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2008-07-02 20:17 <a href="http://www.blogjava.net/gdufo/archive/2008/07/02/212193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不能访问Tomcat5.5的admin页面 </title><link>http://www.blogjava.net/gdufo/archive/2008/07/02/212189.html</link><dc:creator>gdufo</dc:creator><author>gdufo</author><pubDate>Wed, 02 Jul 2008 12:00:00 GMT</pubDate><guid>http://www.blogjava.net/gdufo/archive/2008/07/02/212189.html</guid><description><![CDATA[转<br />
<br />
Tomcat 5可以通过以运行在网页浏览器的配置应用程序非常方便地进行服务器的配置。这个应用程序称为Tomcat
Administration Web Application。然而，Tomcat 5.5 以后的binary 核心安装版不再提供Tomcat
Administration Web Application。要安装后者，需要单独下载和安装。Tomcat
并没有为Administration Web Application提供一种自动整合的安装程序。本文将讲述安装和配置的详细过程。<br />
<br />
第一步，确认你的Tomcat 中是否已安装了Administration Web Application。首先确定Tomcat Service 正在运行。然后在浏览器中，键入 <a href="http://localhost:8080/admin"><u><font color="#800080">http://localhost:8080/admin</font></u></a>，如果看到Tomcat Web Server Administration Tool 的页面，说明Administration Web Application 已安装好了。你可以省点时间，不必读下文了。如果看到的是<br />
<strong>Tomcat's administration web application is no longer installed by default. Download and install the "admin" package to use it. </strong><br />
那么这篇文章就算你看对了，就是专门为你写的。<br />
<br />
第二步，下载admin package。说实话，很多人居然找不到在哪里下载。这不怪你们。Apache Tomcat
的下载页面的指示不是很清楚，当然技术文档也不甚详尽。但是人家已经给你提供了功能强大的open source
软件，你还能抱怨什么呢？要怪就怪的工夫没下到，功夫不够深。<br />
<br />
仔细看，<a href="http://tomcat.apache.org/download-55.cgi"><font color="#800080"><u>http://tomcat.apache.org/download-55.cgi</u></font></a> ， 在下载页面的Binary Distributions栏下的第四大项，Administration Web Application 即是。<br />
<br />
第三步，当解压下载的Administration Web Application 文件，比如放在c:\tom中，你会发现解压后的文件为 c:\tom\apache-tomcat-5.5.17。 这时键入 <a href="http://localhost:8080/admin"><u><font color="#800080">http://localhost:8080/admin</font></u></a> 去检验admin，会发现Tomcat什么都没有改变。因为解压的admin文件还没有配置到Tomcat 的系统中。下面的步骤告诉你如何将admin文件配置到Tomcat 的服务器中。<br />
<br />
第四步，将 c:\tom\apache-tomcat-5.5.17\conf\Catalina\localhost\admin.xml的<br />
admin.xml 文件拷贝到c:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost. 的文件夹中。注意一定要放在正确的路径的文件夹中。<br />
<br />
第五步，将c:\tom\apache-tomcat-5.5.17\server\webapps中的admin整个文件夹拷贝到c:\Program
Files\Apache SoftwareFoundation\Tomcat5.5\<strong><span style="color: red;">server</span></strong>\webapps 文件夹中。<br />
<br />
第六步，用具有编辑功能的notepad等打开 c:\Program Files\Apache Software
Foundation\Tomcat 5.5\conf\中的tomcat-users.xml
文件。在&lt;/tomcat-user&gt;最后一行之前，加入下列一行<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">user&nbsp;</span><span style="color: #ff0000;">username</span><span style="color: #0000ff;">="admin"</span><span style="color: #ff0000;">&nbsp;password</span><span style="color: #0000ff;">="tomcat"</span><span style="color: #ff0000;">&nbsp;roles</span><span style="color: #0000ff;">="admin,manager"</span><span style="color: #0000ff;">/&gt;</span></div>
<br />
注意username/password可以是你喜欢的任意组合，但roles=&#8221;admin&#8221; 不可随意改动。<br />
<br />
第七步，重启Tomcat Server，然后打开<a href="http://127.0.0.1/"><u><font color="#0000ff">http://127.0.0.1</font></u></a>：8080/进入manager里面把admin服务启动起来，然后再进入admin模块里，在web浏览器中键入 <a href="http://localhost:8080/admin"><u><font color="#800080">http://localhost:8080/admin</font></u></a>， 这时你如果能看到 Tomcat Server Web Administration Tool 的login界面， 就大功告成。若是还看不到上述页面，可检查浏览器的代理服务器的设定，使之能够接受localhost。
<p>还打不开就用下面的终极绝招！</p>
<div>目录: E:\Tomcat5.5\conf\web.xml<br />
&lt;!-- listings Should directory listings be produced if there --&gt;<br />
&lt;!-- is no welcome file in this directory? [false] --&gt;<br />
&lt;!-- WARNING: Listings for directories with many --&gt;<br />
&lt;!-- entries can be slow and may consume --&gt;<br />
&lt;!-- significant proportions of server resources. --&gt;<br />
&lt;!-- --&gt;<br />
.....<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;default&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;<br />
org.apache.catalina.servlets.DefaultServlet<br />
&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;debug&lt;/param-name&gt;<br />
&lt;param-value&gt;0&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;listings&lt;/param-name&gt;<br />
&lt;param-value&gt;true&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
......<br />
false --&gt; true<br />
这样就可以浏览了，不过整个Tomcat都是可以浏览，有点危险。<br />
其他就按你自己的配:<br />
目录:E:\Tomcat5.5\conf\Catalina\localhost\jspweb.xml<br />
&lt;?xml version='1.0' encoding='utf-8'?&gt;<br />
&lt;Context docBase="/c:/jspweb/" path="/jspweb"&gt;<br />
&lt;/Context&gt;<br />
因该和5.0一样了,不过你绝对是浪费5.5的安全特性.....</div>
<div>目录: E:\Tomcat5.5\conf\web.xml<br />
&lt;!-- listings Should directory listings be produced if there --&gt;<br />
&lt;!-- is no welcome file in this directory? [false] --&gt;<br />
&lt;!-- WARNING: Listings for directories with many --&gt;<br />
&lt;!-- entries can be slow and may consume --&gt;<br />
&lt;!-- significant proportions of server resources. --&gt;<br />
&lt;!-- --&gt;<br />
.....<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;default&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;<br />
org.apache.catalina.servlets.DefaultServlet<br />
&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;debug&lt;/param-name&gt;<br />
&lt;param-value&gt;0&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;listings&lt;/param-name&gt;<br />
&lt;param-value&gt;true&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
......<br />
false --&gt; true<br />
这样就可以浏览了，不过整个Tomcat都是可以浏览，有点危险。<br />
其他就按你自己的配:<br />
目录:E:\Tomcat5.5\conf\Catalina\localhost\jspweb.xml<br />
&lt;?xml version='1.0' encoding='utf-8'?&gt;<br />
&lt;Context docBase="/c:/jspweb/" path="/jspweb"&gt;<br />
&lt;/Context&gt;<br />
因该和5.0一样了,不过你绝对是浪费5.5的安全特性.....</div>
<p>目录: E:\Tomcat5.5\conf\web.xml<br />
&lt;!-- listings Should directory listings be produced if there --&gt;<br />
&lt;!-- is no welcome file in this directory? [false] --&gt;<br />
&lt;!-- WARNING: Listings for directories with many --&gt;<br />
&lt;!-- entries can be slow and may consume --&gt;<br />
&lt;!-- significant proportions of server resources. --&gt;<br />
&lt;!-- --&gt;<br />
.....<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;default&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;<br />
org.apache.catalina.servlets.DefaultServlet<br />
&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;debug&lt;/param-name&gt;<br />
&lt;param-value&gt;0&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;listings&lt;/param-name&gt;<br />
&lt;param-value&gt;true&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
......<br />
false --&gt; true<br />
这样就可以浏览了，不过整个Tomcat都是可以浏览，有点危险。<br />
其他就按你自己的配:<br />
目录:E:\Tomcat5.5\conf\Catalina\localhost\jspweb.xml<br />
&lt;?xml version='1.0' encoding='utf-8'?&gt;<br />
&lt;Context docBase="/c:/jspweb/" path="/jspweb"&gt;<br />
&lt;/Context&gt;<br />
因该和5.0一样了,不过你绝对是浪费5.5的安全特性.....</p>
<img src ="http://www.blogjava.net/gdufo/aggbug/212189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gdufo/" target="_blank">gdufo</a> 2008-07-02 20:00 <a href="http://www.blogjava.net/gdufo/archive/2008/07/02/212189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>