现在的位置: 首页 > 综合 > 正文

基于S2SH的电子商务网站系统性能优化

2012年08月09日 ⁄ 综合 ⁄ 共 7845字 ⁄ 字号 评论关闭

对于经常逛网页的人来说最受不了的事情就是访问的网页加载太慢,除去网络的原因网站的系统性能对加载的快慢非常重要,

网上有个统计:

        每慢500ms  Google访问量降低20%

        慢400ms Yahoo 访问量降低5-9%

         慢100ms Amazon销售额降低1%

对于商务网站来说用户的多少就表示着网站的命运 所以对网站的系统性能的优化格外重要;

假如当网站在一段时间内有10w个用户访问网站的一个商品时, 网站就会和数据库交互10w次  数据库也只是一个应用而已 它存在数据库瓶颈问题 数据库每次只能同时保持大概2000个连接数 所以对于这些访问者来说只有20%的人能很快访问到网页,50%的人在较慢的一段时间内还是能访问到网页的,但剩下的30%的访问者就会收到连接超时的异常

对于这种由于访问数据库的次数太多的解决方案有:

A.页面情态化成html

页面情态化就是将原来的本应该每次都要访问数据库再生成情态html文件返回,而现在就是只生成一次html下次再访问服务器只要访问该html文件就行不用再访问数据库了,对于这个技术对系统的性能提升很大,但是这个技术只能用于不怎么变化的模块:例如像商品的详细介绍页面:

像这种的页面的信息一周甚至一个月都不会变化,将类似这种模块情态化最合适

实现这个技术的方法是使用模版技术:Velocity 或 freemarket 

    这两种技术都出现了10多年了freemarket比velocity出现的晚几年 声称比velocity功能强大  现在的struts2也使用了freemarket 但是velocity扩展性更好 我这使用的是velocity

基本语法:

1、"#"用来标识Velocity的脚本语句,包括#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;
如:
#if($info.imgs)
<img src="$info.imgs" border=0>
#else
<img src="noPhoto.jpg">
#end

2、"$"用来标识一个对象(或理解为变量);
如:$i、$msg、$TagUtil.options(...)等。

3、"{}"用来明确标识Velocity变量;
比如在页面中,页面中有一个$someonename,此时,Velocity将把someonename作为变量名,若我们程序是想在someone这个变量的后面紧接着显示name字符,则上面的标签应该改成${someone}name。

4、"!"用来强制把不存在的变量显示为空白。
如当页面中包含$msg,如果msg对象有值,将显示msg的值,如果不存在msg对象同,则在页面中将显示$msg字符。这是我们不希望的,为了把不存在的变量或变量值为null的对象显示为空白,则只需要在变量名前加一个“!”号即可。
如:$!msg

使用方法:

1.在http://velocity.apache.com下载velocity-*.rar 解压

可以将velocity-*-dep.jar放带WEB-INF的lib目录下即可 也可以使用velocity-*.jar但是这时要将co'm'mons-connections-*.jar和commons-lang-*.jar和oro-*.jar也加入lib目录下

2.配置velocity的一些属性:

我使用的是在filter中加入相应的配置如:

 1 try{
 2             Properties prop = new Properties();
 3             prop.put("runtime.log", config.getServletContext().getRealPath("/WEB-INF/log/velocity.log"));
 4             prop.put("file.resource.loader.path", config.getServletContext().getRealPath("/WEB-INF/vm"));
 5             prop.put("input.encoding", "GB18030");
 6             prop.put("output.encoding", "GB18030");
 7             Velocity.init(prop);
 8         }catch( Exception e ){
 9             e.printStackTrace();
10         }

file.resource.loader.path   配置的是模版所在的位置 input.encoding ,output.encoding 配置的是相应的输入输出的编码要跟你模版中的编码一样 

3.编写模版生成的代码:我使用的是在商品添加或修改时就生成该商品的html情态文件

 
 

这样就能完成向/WEB-INF/vm/product/productview.html这个模版中写入数据
现在来看下模版文件怎么接受数据的吧:

 1 <form action="/shopping/cart" method="post" name="cart">
 2 <INPUT TYPE="hidden" NAME="productid" value="${product.id}" />
 3 <div id="browse_left">
 4  
 5                          <div class="right_left">
 6                          <div class="right_right">                                    
 7                                     <div class="right_title"><b>${product.name}</b></div>
 8                                     <div class="right_desc">
 9                                             <ul>
10                                                 <li class="li2">商品编号:${product.id}<font color="#CC0000">(电话订购专用)</font></li>
11                                                 #if($!{product.brand}) <li>品牌:$product.brand.name</li> #end                                                                                                                                        </ul>
12                                     </div>
13                                     <div class="right_desc">
14                                             #if($product.productStyles.size()==1)
15                                             <INPUT TYPE="hidden" NAME="styleid" value="$product.productStyles.iterator().next().id" />
16                                             <li>颜色:红色</li>
17                                             #else
18                                              <li>颜色:<SELECT name="styleid">#foreach($color in $product.productStyles)
19                                                 <option value="$color.id">$color.name</option>
20                                               #end </SELECT></li>
21                                             #end                                          
22                                     </div>
23                                     <ul>
24                                         <li>市场价:<s>${product.marketprice}</s><font color='#ff6f02'>本站价:<b>${product.sellprice} 元</b></font> 节省:<font color='#ff6f02'>${product.savedPrice}</font></li>
25                                           
26                                     </ul>                                    
27                             </div>
28 </div>
29                             <div id="browse_right"><div id="sy_biankuang">
30                                         <div class="sy_xinpintuijian_font">本站尚未开张</div>
31                                         <div class="sy_dianhua" style="line-height:150%"><font color="#FF0000">
32                                             全国:010-6466 3070</font><br/>MSN在线客服:*****@sohu.com<br/>    
33                                         <font color="#3A8FAF">QQ在线客服:895957140</font></div>
34                             </div></div>
35 </form>

 

${product.name}这样的标签就是显示传过来的product对象的name属性值
 
重启tomcat服务器后添加一个商品这样关于product的一个情态html文件就生成在根目录下的/WEB-INF/html/product/product的类别id/下面
 
B.缓存技术
 
对于页面情态化它只适用于不怎么变化的模块 而像

这样

这样的商品检索页面由于分类不同排序不同所生成的页面用统计就知道太多了不适合使用页面情态化,那么就可以使用缓存技术了
 
缓存技术有两种:页面缓存和二级缓存
页面缓存的缺点就是不能实时更新,但是性能比二级缓存要好
 
页面缓存的实现:使用oscache
1.下载相应的包

2.将oscache.proprities文件拷贝到项目的src目录下:里面有一些属性可以配置一下

2.如果你只是缓存一部分网页那么只要使用部分缓存:

部分缓存只要像用标签一样
3.全局缓存:就是将整个页面都缓存起来
使用方法:只要在web.xml中加入一个filter即可
<filter>
            <filter-name>CacheFilter</filter-name>
            <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
            <init-param>
                <param-name>time</param-name>
                <param-value>7200</param-value>
            </init-param>
            <init-param>
                <param-name>scope</param-name>
                <param-value>application</param-value>
            </init-param>
    </filter>
    <filter-mapping>
            <filter-name>CacheFilter</filter-name>
            <url-pattern>/product/list/*</url-pattern>
    </filter-mapping>

 

加人这个filter后所有url中以/product/list/开头的连接即所有的商品列表都将放入缓存中它的key就是相应的URL默认的缓存时间是7200s即2小时 默认的存在范围是Application范围
4.注意的是当添加或修改商品时由于有缓存那么更新信息并不能马上更新在页面上  那么我们应该在更新了的时候更新缓存只要使用上面提到的flush属性就行

 
B.二级缓存:重点是它能实时更新 

 
由于我没使用二级缓存使用也不知道效果怎样
 
C.数据源 :在spring的beans.xm的连接池里面放一些连接对象
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
        <!-- 初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3  -->
        <property name="initialPoolSize" value="1"/>
        <!-- 连接池中保留的最小连接数。 -->
        <property name="minPoolSize" value="1"/>    
        <!-- 连接池中保留的最大连接数。Default: 15  -->
        <property name="maxPoolSize" value="300"/>
        <!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0  -->
        <property name="maxIdleTime" value="60"/>    
        <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3  -->
        <property name="acquireIncrement" value="5"/>    
        <!-- 每60秒检查所有连接池中的空闲连接。Default: 0  -->
        <property name="idleConnectionTestPeriod" value="60"/>
    </bean>

 

这里用的是c3p0作为数据源 要加入c3p0的jar包
 
D.SSI
经过上面的优化性能上就能提高很多 SSI只能提高一点点 因为 SSI 指令执行 Tomcat 外部的 JVM 能释放Tomcat自己的JVM的压力

配置过程:

1). 先保证 Tomcat 可以运行,即能够正常启动

2).  5.x 版本)服务器根目录下边 $TOMCAT_HOME( 或者 $CATALINA_HOME)/server/lib/ 目录下边有一个文件:

servlets-ssi.renametojar ,将这个文件名更名为一个 jar 后缀,当然最方便的方法是直接改掉文件后缀,按照 Tomcat 扫描jar 路径类的原理来讲,直接更名为 jar 应该也是可以的,不过我没尝试过,一般网上最常用的方法是改成: servlets-ssi.jar。( 6.x 版本)服务器不需要去寻找 jar 文件了,直接进入下一步操作都可以。

3). 找到文件: $TOMCAT_HOME( 或者 $CATALINA_HOME)/conf/web.xml ,这里面不需要我们自己写入 SSI Servlet SSI Filter 的配置,首先我们要选择使用哪种方式来配置:

Servlet 配置:

  在这个文件里面,找到以下注释代码段,将注释代码段去掉:

Servlet 配置——

<!--

    <servlet>

        <servlet-name>ssi</servlet-name>

        <servlet-class>

          org.apache.catalina.ssi.SSIServlet

        </servlet-class>

        <init-param>

          <param-name>buffered</param-name>

          <param-value>1</param-value>

        </init-param>

        <init-param>

          <param-name>debug</param-name>

          <param-value>0</param-value>

        </init-param>

        <init-param>

          <param-name>expires</param-name>

          <param-value>666</param-value>

        </init-param>

        <init-param>

          <param-name>isVirtualWebappRelative</param-name>

          <param-value>0</param-value>

        </init-param>

        <load-on-startup>4</load-on-startup>

    </servlet>

-->

 

ServletMapping 配置——

<!--

    <servlet-mapping>

        <servlet-name>ssi</servlet-name>

        <url-pattern>*.shtml</url-pattern>

    </servlet-mapping>

-->

 

Filter 配置:

Filter 的相关配置——

<!--

    <filter>

        <filter-name>ssi</filter-name>

        <filter-class>

          org.apache.catalina.ssi.SSIFilter

        </filter-class>

        <init-param>

          <param-name>contentType</param-name>

          <param-value>text/x-server-parsed-html(;.*)?</param-value>

        </init-param>

        <init-param>

          <param-name>debug</param-name>

          <param-value>0</param-value>

        </init-param>

        <init-param>

          <param-name>expires</param-name>

          <param-value>666</param-value>

        </init-param>

        <init-param>

          <param-name>isVirtualWebappRelative</param-name>

          <param-value>0</param-value>

        </init-param>

    </filter>

-->

 

FilterMapping 相关配置——

<!--

    <filter-mapping>

        <filter-name>ssi</filter-name>

        <url-pattern>*.shtml</url-pattern>

    </filter-mapping>

-->

 

只是 Filter 配置里面还需要取消另外一个注释,下边的 MIME TYPE 的服务器支持相关注释

<!--

    <mime-mapping>

        <extension>shtml</extension>

        <mime-type>text/x-server-parsed-html</mime-type>

    </mime-mapping>

-->

 

   上边的注释取消过后,配置就基本好了,在 Tomcat 5.x 的版本中配置的时候,到这个地步就结束了,但是在 Tomcat 6.x 版本中可能还会出现下边的异常:

   java.lang.SecurityException: Filter of class org.apache.catalina.ssi. SSIFilter (SSIServlet) is privileged and cannot be loaded by this web application

4). 所以正对这点 6.x 还有一个步骤,在 $TOMCAT_HOME( 或者 $CATALINA_HOME)/conf/context.xml 文件中在<Context> 结点添加一个属性 privileged="true" ,然后再启动就不会抛出上边的异常了。

5). 若要解决乱码问题,根据上边文档需要修改 SSI 中的启动参数:添加如下代码:

<init-param>

        <param-name> inputEncoding </param-name>

         <param-value> utf-8 </param-value>

</init-param>

<init-param>

        <param-name> outputEncoding </param-name>

        <param-value> utf-8 </param-value>

</init-param>

 

6)使用方式:
在html文件中就可以加入<!--#include virtual="/WEB-INF/page/share/Head.jsp" -->这样的标签了
 
 

抱歉!评论已关闭.