系统架构 优化js的 优化web页面加载速度

2 篇文章 0 订阅
1 篇文章 0 订阅

系统架构

1、客户层

      js, css, data的结合

      js数据模版

     html模版


      js加载效率的提升, 因为在无法避免js的数量的增多, 体积的增大的情况下。 如何有效的加载js就显的尤为重要。采用以下方法

      a、动态加载js, 不说了, 直接上代码:

           

[javascript]  view plain copy
  1. Skip.getJSActionByAjax1 = function (rootObject, url) {    
  2.     var myAjax = new Ajax.Request(url, {  
  3.         method : "get",       
  4.         asynchronous : false,  
  5.         onSuccess : function(request) {  
  6.             var text = request.responseText;  
  7.             //alert(text);  
  8.             //Skip.includeJsText(rootObject,text);  
  9.             Skip.includeJsSrc( rootObject, url);   
  10.               
  11.         },  
  12.         onFailure : function(request) {  
  13.             alert("出错了!" + "\n" + request + "\n" + request);              
  14.             return result;  
  15.         }  
  16.     });   
  17. }    

[javascript]  view plain copy
  1. //导入文件  
  2. Skip.includeJsSrc =function (rootObject, fileUrl){   
  3.         if ( rootObject != null ){   
  4.              var oScript = document.createElement( "script" );   
  5.              oScript.type = "text/javascript";   
  6.              oScript.src = fileUrl;   
  7.              rootObject.appendChild(oScript);   
  8.        }   
  9.       }  

【注明:这里用到了prototype.js】

[javascript]  view plain copy
  1. var myjslist= new Array();  
  2. //执行时间的方法  
  3. function dyloadjs(fileName, funcJs,showReVal,e,fieldName2,funcName2){  
  4.    //alert(fileName);  
  5.    var find = true;  
  6.    for(var i=0;i<myjslist.length;i++)  
  7.    {  
  8.        if(myjslist[i]==fileName) {  
  9.          find = false;  
  10.          break;  
  11.        }     
  12.    }  
  13.    if(find) {  
  14.        myjslist.push(fileName);  
  15.        var rootObject=document.getElementById("myjs");  
  16.        Skip.getJSActionByAjax1(rootObject,fileName);    
  17.        Skip.getJSActionByAjax1(rootObject,fileName);   
  18.      //Skip.includeJsSrc( rootObject, fileName);  
  19.     }    
  20.     //TODO   
  21.     //调用js函数, 运行  
  22. }  


【注明,以上的方法是要求同步加载的, 因为不能采用回调的方式执行,并且对执行的顺序要求非常的高。而且以前代码量很大, 很难修改。

                这个地方有个问题   getJSActionByAjax1 方法被调用了2次, 

              因为在ie8下面, 如果不调用2次, 就没有效果, 始终方法找不到,ie9下面就没有问题,

              chrome, safiri等高档浏览器, nnd, 加载js就不是阻塞的, 所以, 这种方式无效, 因为没有等js加载完

             就开始执行下面的方法了。  】

        采用了这个办法, 可以有效的控制js的加载的顺序, 有图有真相:

       

        js的加载按照预期的方式进行, 把js的加载的事情分割到了不同的时间和区域, 这样可以有效的改善用户体验

        但是仔细看上图, 可以清楚的发现js每个都加载了3次, 是因为上面的方法被调用了2次ajax请求, ajax成功以后还有一次是include js src的请求, 

        但是为啥不是4次, 这个地方有写疑问,难道ie自己发现已经script头有了, 就不在重复加载了?

        这个地方滋生了2个问题

           1、如何有效的js的请求次数从3次变成1次呢, 好像这个不太可能。最主要直接create script dom节点的话, 不能阻塞加载的线程, 所以这个

                 问题暂时放一下 

           2、换个思路, 能不能减少ajax的请求时间呢?  答案是完全可以的。如果这样的话, 后面的时间都是0的话,完全可以弥补次数多的遗憾, 还有什么

                 比耗费0时间效率更高呢。 

      b、设定js的过期时间expires 属性, (这个应该是见效最明显的办法了)  , tomcat加配置简单易用, 以tomcat7为例:

     

[html]  view plain copy
  1. <filter>  
  2.  <filter-name>ExpiresFilter</filter-name>  
  3.  <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>  
  4.  <init-param>  
  5.     <param-name>ExpiresByType image</param-name>  
  6.     <param-value>access plus 10 minutes</param-value>  
  7.  </init-param>  
  8.  <init-param>  
  9.     <param-name>ExpiresByType text/css</param-name>  
  10.     <param-value>access plus 10 minutes</param-value>  
  11.  </init-param>  
  12.  <init-param>  
  13.     <param-name>ExpiresByType application/javascript</param-name>  
  14.     <param-value>access plus 10 weeks</param-value>  
  15.  </init-param>  
  16. </filter>  
  17. ...  
  18. <filter-mapping>  
  19.  <filter-name>ExpiresFilter</filter-name>  
  20.  <url-pattern>/*</url-pattern>  
  21.  <dispatcher>REQUEST</dispatcher>  
  22. </filter-mapping>  

配置后效果图, 很好很强大。



    

呵呵, 后面的js的加载时间都变成了0, 哇塞, 这个很好很强大。 对于一些比较稳定的, 少修改的系统来说, 这个参数配置绝对是超值。


同时注意到这个: 

[html]  view plain copy
  1. org.apache.catalina.filters.ExpiresFilter  

是不是可以重载这个类, 实现自己具体那些文件需要这种处理。 


总结: 通过以上2步骤的配置, js的加载基本上通过分时、 分阶段的加载的话。可以有效的改善用户体验。 特别对一些网速比较慢的情况。

     

2、 web层

    负载均衡:

    使用nginx做负载均衡

     nginx的配置信息如下及字段说明:

[plain]  view plain copy
  1. #运行nginx所在的用户名和用户组  
  2. #user  nobody;  
  3.   
  4. #启动进程数  
  5. worker_processes  2;  
  6.   
  7. #设置全局错误日志存放路径和日志级别  
  8. #error_log  logs/error.log  debug;  
  9. #error_log  logs/error.log  info;  
  10. error_log  logs/error.log  notice;  
  11. #error_log  logs/error.log  warn;  
  12. #error_log  logs/error.log  error;  
  13. #error_log  logs/error.log  crit;  
  14.   
  15. #pid        logs/nginx.pid;  
  16.   
  17. #设定 nginx 进程可以打开的最大文件描述符数量  
  18. worker_rlimit_nofile 65535;  
  19. #工作模式及连接数上限  
  20. events {  
  21.     worker_connections  65535;  
  22. }  
  23.   
  24. http {  
  25.     #设定mime类型  
  26.     include       mime.types;  
  27.     #设置默认的Content-Type,http head中如果没有设置的情况下才会使用  
  28.     default_type  application/octet-stream;  
  29.   
  30.     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
  31.     #                  '$status $body_bytes_sent "$http_referer" '  
  32.     #                  '"$http_user_agent" "$http_x_forwarded_for"';  
  33.   
  34.     #禁止访问日志,启用的话时间长了文件会很大,而且我们暂时不会启用自动脚本清理日志  
  35.     #access_log  logs/access.log  main;  
  36.     access_log off;  
  37.   
  38.     # 启用sendfile()函数,大部分情况下提高复制文件的速度  
  39.     sendfile        on;  
  40.     # 配合 sendfile 使用  
  41.     tcp_nopush     on;  
  42.   
  43.     #keepalive_timeout  0;  
  44.     # 客户端到服务器端的连接持续有效时间  
  45.     keepalive_timeout  65;  
  46.   
  47.     # gzip 相关设置  
  48.     gzip  on;  
  49.     gzip_min_length    1k;  
  50.     gzip_buffers       4 16k;  
  51.     gzip_http_version  1.0;  
  52.     gzip_comp_level    6;  
  53.     gzip_types         text/plain text/json text/css text/javascript text/xml application/x-javascript application/xml;  
  54.     gzip_vary          on;  
  55.   
  56.     # 设置可以在 proxy_pass 中使用的一组代理服务器  
  57.     upstream tomcat{  
  58.         # max_fails 是检查服务器失败次数,当失败次数达到设定值时停用该服务,0表示关闭检查  
  59.         # server 可以设置多个  
  60.         server localhost:8888 max_fails=0;  
  61.     }  
  62.   
  63.     # 虚拟主机配置  
  64.     server {  
  65.         # nginx 监听的端口  
  66.         listen       8080;  
  67.         # 根据客户端请求 header 中的 host 域名匹配响应的虚拟主机  
  68.         server_name  localhost;  
  69.   
  70.   
  71.         #============静态文件配置============  
  72.   
  73.         # location 匹配 URI,可以使用字符串,也可以使用正则表达.使用正则表达式时必须使用 ~* 或者 ~ 前缀  
  74.         # ~* 前缀表示不区分大小写匹配  
  75.         # ~ 前缀表示区分大小写匹配  
  76.         # ^~ 前缀表示匹配到字符串后不再取检查正则表达式  
  77.         # = 前缀表示精确匹配URI 例如"location = /test"只能匹配"/test",而"test123"则不能被匹配  
  78.         location ~* /web/(.*)\.(gif|png|jpg|jpeg|bmp|swf)$ {  
  79.             # rewrite 重写url,去掉web等tomcat的webapp名称,为下面的root路径做准备  
  80.             rewrite ^/web/(.*)$ /$1 break;  
  81.   
  82.             # 指定请求的文档根目录.  
  83.             # 例如 location /i/ {root /home/www/;}时,请求的 URI 是 "/aaa/bb.gif",  
  84.             # 则会返回 "/home/www/aaa/bb.gif" 的内容.  
  85.             # 即 root 指向的目录内的结构必须和 URI 相同,这与下面的 alias 不一样  
  86.             # 并且使用相对路径定位的时候,不是nginx.conf文件所在的路径,  
  87.             # 而是编译时指定的prefix路径,或者运行是手动指定的路径,alias定位也是一样  
  88.             root "../Web/";  
  89.               
  90.             # 设置 http head 中 "Expires"和"Cache-Control" 的值,负数时"Cache-Control"的值为no-cache  
  91.             # off 表示不修改"Expires"和"Cache-Control"的值  
  92.             expires 30d;  
  93.         }  
  94.   
  95.           
  96.   
  97.         #============临时文件路径跳转============  
  98.   
  99.           
  100.   
  101.         #error_page  404              /404.html;  
  102.   
  103.         # 50X错误所显示的错误页面  
  104.         error_page   500 502 503 504  /50x.html;  
  105.         location = /50x.html {  
  106.             root   html;  
  107.         }  
  108.   
  109.         #禁止访问WEB-INF文件夹  
  110.         location ~ /(WEB-INF)/{  
  111.             deny all;  
  112.         }  
  113.   
  114.         # 其他都跳转到tomcat  
  115.         location / {  
  116.             # 设置代理服务器  
  117.             proxy_pass http://tomcat;  
  118.   
  119.             # 设置代理的 http 头中的 host 值为远程连接原本的 host 值  
  120.             proxy_set_header HOST $http_host;  
  121.   
  122.             # 设置代理跟后端服务器连接的超时时间.  
  123.             # 该时间不是服务器返回页面的事件,而是发起握手等候响应的超时时间.  
  124.             # 开发人员调试 java 端程序时可以适当的调长时间,  
  125.             # 不然调试时间太长 nginx 会以为后端服务器挂掉而返回500错误.  
  126.             # 生产环境中应该设置比较短的时间,不然当后端服务器关闭或者挂掉后 nginx 还在等候,  
  127.             # 导致客户端页面在长时间的等待而不是返回错误页面  
  128.             proxy_connect_timeout 5s;  
  129.   
  130.             # 关闭对被代理的服务器的应答缓冲  
  131.             proxy_buffering off;  
  132.   
  133.             # 客户端允许上传的最大文件大小  
  134.             client_max_body_size 500m;  
  135.   
  136.             # 超时必须设置一秒以上,不然IE下载文件会报错  
  137.             expires 1s;  
  138.         }  
  139.   
  140.   
  141.         # 这两个路径404时不记录日志  
  142.         location = /robots.txt  { access_log off; log_not_found off; }  
  143.         location = /favicon.ico { access_log off; log_not_found off; }    
  144.     }  
  145. }  

     

    web服务优化调优--tomcat,

   并发数--tomcat

3、业务层

    缓存数据

4、数据库层

    数据库连接池, 性能监控, 调优

   》c3p0的监控

      tomcat通过配置jmx可以监控  (资料来源于网络)  

[plain]  view plain copy
  1. Step1: 配置Tomcat支持JMX  
  2. 在$CATALINA_HOME/bin中找到catalina.sh或者catalina.bat文件,在该文件中添加jmx的配置  
  3. 以catalina.bat为例:  
  4. set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote  
  5. set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.port=9999  
  6. set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.authenticate=false  
  7. set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.ssl=false  
  8. 表示jmx开放端口是9999  
  9. 配置完以后重启tomcat服务。  
  10. Step2:使用Jconsole监控  
  11. 编写脚本monitor.bat  
  12. 内容是  
  13. jconsole -J-Djava.class.path=%JAVA_HOME%/lib/jconsole.jar;%JAVA_HOME%/lib/tools.jar;c3p0-0.9.1.jar  
  14. Step3:查看结果  
  15. 在jconsole的对话框中输入<hostname>:<port>进入Mbean查看c3p0的信息。  
  16. 如果jconsole连接不上<hostname>:<port>,而telnet可以连接上<hostname>:<port>,那么需要确认在服务器中执行hostname -i看结果是不是你使用<hostname>,如果不是的话要修改/etc/hosts内容。  



注明:如果是本机监控的的话, 其实只要直接启动Jconsole,监控tomcat就ok了。 c3p0默认就是jmx方式


》用jsp编程的方式监控jmx(来自网络, 这个好像c3p0的例子)

[html]  view plain copy
  1. <%@ page contentType="text/html;charset=GBK"%>      
  2. <%@ page import="java.sql.*"%>      
  3. <%@ page import="javax.sql.*"%>    
  4. <%@ page import="javax.naming.*"%>    
  5. <%@ page import="com.mchange.v2.c3p0.*"%>      
  6. <%!    
  7.     int numConnections=0;    
  8.     int numBusyConnections=0;    
  9.     int numIdleConnections=0;    
  10.     int numUnclosedOrphanedConnections=0;    
  11. %>    
  12. <%           
  13.     InitialContext ictx = new InitialContext();    
  14.         DataSource ds=null;    
  15.     PooledDataSource pds=null;    
  16.     try {      
  17.     ictx = new InitialContext();    
  18.         ds = (DataSource) ictx.lookup("java:comp/env/jdbc/igrp" );      
  19.        
  20.     if ( ds instanceof PooledDataSource) {       
  21.         pds = (PooledDataSource) ds;     
  22.         String clear=request.getParameter("clear");    
  23.         
  24.         if("1".equals(clear)){    
  25.             pds.hardReset();    
  26.         }    
  27.         numConnectionspds.getNumConnectionsDefaultUser();       
  28.         numBusyConnectionspds.getNumBusyConnectionsDefaultUser();    
  29.         numIdleConnectionspds.getNumIdleConnectionsDefaultUser();     
  30.         numUnclosedOrphanedConnectionspds.getNumUnclosedOrphanedConnectionsDefaultUser();     
  31.     }     
  32.     else     
  33.         System.err.println("Not a c3p0 PooledDataSource!");      
  34.     } catch (Exception ex) {      
  35.         ex.printStackTrace();    
  36.     }      
  37.         
  38. %>      
  39. <body align="center">    
  40.     <table border="1" align="center">    
  41.         <tr>    
  42.             <td>总的连接数</td>    
  43.             <td><%=numConnections%></td>    
  44.         </tr>    
  45.         <tr>    
  46.             <td>正在运行状态的连接数</td>    
  47.             <td><%=numBusyConnections%></td>    
  48.         </tr>    
  49.         <tr>    
  50.             <td>空闲连接数</td>    
  51.             <td><%=numIdleConnections%></td>    
  52.         </tr>    
  53.         <tr>    
  54.             <td>都是checkoutconnection,但他们已经不在池中管理了.当他们checkin时候,将被destory</td>    
  55.             <td><%=numUnclosedOrphanedConnections%></td>    
  56.         </tr>    
  57.     </table>    
  58.     
  59.     <form action="c3p0.jsp" method="post">    
  60.         <input type="hidden" id="clear" name="clear" value="1"/>    
  61.         <input type="submit" value="清空连接池"/>    
  62.     </form>    
  63. </body>    



     

5、系统测试

6、系统监控、问题扑捉、 调优

   验证稳定

   验证效率

  系统监控

    linux: jmap

    window: 


工具:LR,apache, httpwatch



1、sql语句监控的系统, 包括语句执行的频度, 时间等等, 页面打开时间, 系统的健康程度, 系统运行时间、总访问次数、各种业务的分类统计数据

                                            访问次数, 访问时间范围、 java内存消耗, cpu占用等等。


2、用户行为收集的东东, 用户打开页面的统计, 用户页面停留时间, 页面数据大小 , 可以知道用户操作的习惯, 为系统以后的升级做出更好的修正提供必要的信息


系统监控的



附录:


tomcat并发设置

在tomcat配置文件server.xml中的<Connector ... />配置中,和连接数相关的参数有: 
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10 
maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75 
acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100 
enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false 
connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 

其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。


  1. <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"  
  2.                connectionTimeout="20000"  
  3.                redirectPort="8443" />  


JVM设置 
堆的尺寸 
-Xmssize in bytes 
    设定Java堆的初始尺寸,缺省尺寸是2097152 (2MB)。这个值必须是1024个字节(1KB)的倍数,且比它大。(-server选项把缺省尺寸增加到32M。) 
-Xmnsize in bytes 
    为Eden对象设定初始Java堆的大小,缺省值为640K。(-server选项把缺省尺寸增加到2M。) 
-Xmxsize in bytes 
    设定Java堆的最大尺寸,缺省值为64M,(-server选项把缺省尺寸增加到128M。) 最大的堆尺寸达到将近2GB(2048MB)。 

请注意:很多垃圾收集器的选项依赖于堆大小的设定。请在微调垃圾收集器使用内存空间的方式之前,确认是否已经正确设定了堆的尺寸。 

垃圾收集:内存的使用 
-XX:MinHeapFreeRatio=percentage as a whole number 
    修改垃圾回收之后堆中可用内存的最小百分比,缺省值是40。如果垃圾回收后至少还有40%的堆内存没有被释放,则系统将增加堆的尺寸。 
-XX:MaxHeapFreeRatio=percentage as a whole number 
    改变垃圾回收之后和堆内存缩小之前可用堆内存的最大百分比,缺省值为70。这意味着如果在垃圾回收之后还有大于70%的堆内存,则系统就会减少堆的尺寸。 
-XX:NewSize=size in bytes 
    为已分配内存的对象中的Eden代设置缺省的内存尺寸。它的缺省值是640K。(-server选项把缺省尺寸增加到2M。) 
-XX:MaxNewSize=size in bytes 
    允许您改变初期对象空间的上限,新建对象所需的内存就是从这个空间中分配来的,这个选项的缺省值是640K。(-server选项把缺省尺寸增加到2M。) 
-XX:NewRatio=value 
    改变新旧空间的尺寸比例,这个比例的缺省值是8,意思是新空间的尺寸是旧空间的1/8。 
-XX:SurvivorRatio=number 
    改变Eden对象空间和残存空间的尺寸比例,这个比例的缺省值是10,意思是Eden对象空间的尺寸比残存空间大survivorRatio+2倍。 
-XX:TargetSurvivorRatio=percentage 
    设定您所期望的空间提取后被使用的残存空间的百分比,缺省值是50。 
-XX:MaxPermSize=size in MB 
    长久代(permanent generation)的尺寸,缺省值为32(32MB)。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值