您的位置:首页 > 运维架构 > 网站架构

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

2013-03-14 09:02 525 查看
系统架构

1、客户层

js, css, data的结合

js数据模版

html模版

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

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

[javascript] view
plaincopy

Skip.getJSActionByAjax1 = function (rootObject, url) {

var myAjax = new Ajax.Request(url, {

method : "get",

asynchronous : false,

onSuccess : function(request) {

var text = request.responseText;

//alert(text);

//Skip.includeJsText(rootObject,text);

Skip.includeJsSrc( rootObject, url);

},

onFailure : function(request) {

alert("出错了!" + "\n" + request + "\n" + request);

return result;

}

});

}

[javascript] view
plaincopy

//导入文件

Skip.includeJsSrc =function (rootObject, fileUrl){

if ( rootObject != null ){

var oScript = document.createElement( "script" );

oScript.type = "text/javascript";

oScript.src = fileUrl;

rootObject.appendChild(oScript);

}

}

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

[javascript] view
plaincopy

var myjslist= new Array();

//执行时间的方法

function dyloadjs(fileName, funcJs,showReVal,e,fieldName2,funcName2){

//alert(fileName);

var find = true;

for(var i=0;i<myjslist.length;i++)

{

if(myjslist[i]==fileName) {

find = false;

break;

}

}

if(find) {

myjslist.push(fileName);

var rootObject=document.getElementById("myjs");

Skip.getJSActionByAjax1(rootObject,fileName);

Skip.getJSActionByAjax1(rootObject,fileName);

//Skip.includeJsSrc( rootObject, fileName);

}

//TODO

//调用js函数, 运行

}

【注明,以上的方法是要求同步加载的, 因为不能采用回调的方式执行,并且对执行的顺序要求非常的高。而且以前代码量很大, 很难修改。
这个地方有个问题 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
plaincopy

<filter>

<filter-name>ExpiresFilter</filter-name>

<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>

<init-param>

<param-name>ExpiresByType image</param-name>

<param-value>access plus 10 minutes</param-value>

</init-param>

<init-param>

<param-name>ExpiresByType text/css</param-name>

<param-value>access plus 10 minutes</param-value>

</init-param>

<init-param>

<param-name>ExpiresByType application/javascript</param-name>

<param-value>access plus 10 weeks</param-value>

</init-param>

</filter>

...

<filter-mapping>

<filter-name>ExpiresFilter</filter-name>

<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>

</filter-mapping>

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



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

同时注意到这个:

[html] view
plaincopy

org.apache.catalina.filters.ExpiresFilter

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

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

2、 web层

负载均衡:

使用nginx做负载均衡

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

[plain] view
plaincopy

#运行nginx所在的用户名和用户组

#user nobody;

#启动进程数

worker_processes 2;

#设置全局错误日志存放路径和日志级别

#error_log logs/error.log debug;

#error_log logs/error.log info;

error_log logs/error.log notice;

#error_log logs/error.log warn;

#error_log logs/error.log error;

#error_log logs/error.log crit;

#pid logs/nginx.pid;

#设定 nginx 进程可以打开的最大文件描述符数量

worker_rlimit_nofile 65535;

#工作模式及连接数上限

events {

worker_connections 65535;

}

http {

#设定mime类型

include mime.types;

#设置默认的Content-Type,http head中如果没有设置的情况下才会使用

default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '

# '$status $body_bytes_sent "$http_referer" '

# '"$http_user_agent" "$http_x_forwarded_for"';

#禁止访问日志,启用的话时间长了文件会很大,而且我们暂时不会启用自动脚本清理日志

#access_log logs/access.log main;

access_log off;

# 启用sendfile()函数,大部分情况下提高复制文件的速度

sendfile on;

# 配合 sendfile 使用

tcp_nopush on;

#keepalive_timeout 0;

# 客户端到服务器端的连接持续有效时间

keepalive_timeout 65;

# gzip 相关设置

gzip on;

gzip_min_length 1k;

gzip_buffers 4 16k;

gzip_http_version 1.0;

gzip_comp_level 6;

gzip_types text/plain text/json text/css text/javascript text/xml application/x-javascript application/xml;

gzip_vary on;

# 设置可以在 proxy_pass 中使用的一组代理服务器

upstream tomcat{

# max_fails 是检查服务器失败次数,当失败次数达到设定值时停用该服务,0表示关闭检查

# server 可以设置多个

server localhost:8888 max_fails=0;

}

# 虚拟主机配置

server {

# nginx 监听的端口

listen 8080;

# 根据客户端请求 header 中的 host 域名匹配响应的虚拟主机

server_name localhost;

#============静态文件配置============

# location 匹配 URI,可以使用字符串,也可以使用正则表达.使用正则表达式时必须使用 ~* 或者 ~ 前缀

# ~* 前缀表示不区分大小写匹配

# ~ 前缀表示区分大小写匹配

# ^~ 前缀表示匹配到字符串后不再取检查正则表达式

# = 前缀表示精确匹配URI 例如"location = /test"只能匹配"/test",而"test123"则不能被匹配

location ~* /web/(.*)\.(gif|png|jpg|jpeg|bmp|swf)$ {

# rewrite 重写url,去掉web等tomcat的webapp名称,为下面的root路径做准备

rewrite ^/web/(.*)$ /$1 break;

# 指定请求的文档根目录.

# 例如 location /i/ {root /home/www/;}时,请求的 URI 是 "/aaa/bb.gif",

# 则会返回 "/home/www/aaa/bb.gif" 的内容.

# 即 root 指向的目录内的结构必须和 URI 相同,这与下面的 alias 不一样

# 并且使用相对路径定位的时候,不是nginx.conf文件所在的路径,

# 而是编译时指定的prefix路径,或者运行是手动指定的路径,alias定位也是一样

root "../Web/";

# 设置 http head 中 "Expires"和"Cache-Control" 的值,负数时"Cache-Control"的值为no-cache

# off 表示不修改"Expires"和"Cache-Control"的值

expires 30d;

}

#============临时文件路径跳转============

#error_page 404 /404.html;

# 50X错误所显示的错误页面

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

#禁止访问WEB-INF文件夹

location ~ /(WEB-INF)/{

deny all;

}

# 其他都跳转到tomcat

location / {

# 设置代理服务器

proxy_pass http://tomcat;
# 设置代理的 http 头中的 host 值为远程连接原本的 host 值

proxy_set_header HOST $http_host;

# 设置代理跟后端服务器连接的超时时间.

# 该时间不是服务器返回页面的事件,而是发起握手等候响应的超时时间.

# 开发人员调试 java 端程序时可以适当的调长时间,

# 不然调试时间太长 nginx 会以为后端服务器挂掉而返回500错误.

# 生产环境中应该设置比较短的时间,不然当后端服务器关闭或者挂掉后 nginx 还在等候,

# 导致客户端页面在长时间的等待而不是返回错误页面

proxy_connect_timeout 5s;

# 关闭对被代理的服务器的应答缓冲

proxy_buffering off;

# 客户端允许上传的最大文件大小

client_max_body_size 500m;

# 超时必须设置一秒以上,不然IE下载文件会报错

expires 1s;

}

# 这两个路径404时不记录日志

location = /robots.txt { access_log off; log_not_found off; }

location = /favicon.ico { access_log off; log_not_found off; }

}

}

web服务优化调优--tomcat,

并发数--tomcat

3、业务层

缓存数据

4、数据库层

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

》c3p0的监控

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

[plain] view
plaincopy

Step1: 配置Tomcat支持JMX

在$CATALINA_HOME/bin中找到catalina.sh或者catalina.bat文件,在该文件中添加jmx的配置

以catalina.bat为例:

set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote

set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.port=9999

set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.authenticate=false

set CATALINA_OPTS=%CATALINA_OPTS% -Dcom.sun.management.jmxremote.ssl=false

表示jmx开放端口是9999

配置完以后重启tomcat服务。

Step2:使用Jconsole监控

编写脚本monitor.bat

内容是

jconsole -J-Djava.class.path=%JAVA_HOME%/lib/jconsole.jar;%JAVA_HOME%/lib/tools.jar;c3p0-0.9.1.jar

Step3:查看结果

在jconsole的对话框中输入<hostname>:<port>进入Mbean查看c3p0的信息。

如果jconsole连接不上<hostname>:<port>,而telnet可以连接上<hostname>:<port>,那么需要确认在服务器中执行hostname -i看结果是不是你使用<hostname>,如果不是的话要修改/etc/hosts内容。

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

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

[html] view
plaincopy

<%@ page contentType="text/html;charset=GBK"%>

<%@ page import="java.sql.*"%>

<%@ page import="javax.sql.*"%>

<%@ page import="javax.naming.*"%>

<%@ page import="com.mchange.v2.c3p0.*"%>

<%!

int numConnections=0;

int numBusyConnections=0;

int numIdleConnections=0;

int numUnclosedOrphanedConnections=0;

%>

<%

InitialContext ictx = new InitialContext();

DataSource ds=null;

PooledDataSource pds=null;

try {

ictx = new InitialContext();

ds = (DataSource) ictx.lookup("java:comp/env/jdbc/igrp" );

if ( ds instanceof PooledDataSource) {

pds = (PooledDataSource) ds;

String clear=request.getParameter("clear");

if("1".equals(clear)){

pds.hardReset();

}

numConnections= pds.getNumConnectionsDefaultUser();

numBusyConnections= pds.getNumBusyConnectionsDefaultUser();

numIdleConnections= pds.getNumIdleConnectionsDefaultUser();

numUnclosedOrphanedConnections= pds.getNumUnclosedOrphanedConnectionsDefaultUser();

}

else

System.err.println("Not a c3p0 PooledDataSource!");

} catch (Exception ex) {

ex.printStackTrace();

}

%>

<body align="center">

<table border="1" align="center">

<tr>

<td>总的连接数</td>

<td><%=numConnections%></td>

</tr>

<tr>

<td>正在运行状态的连接数</td>

<td><%=numBusyConnections%></td>

</tr>

<tr>

<td>空闲连接数</td>

<td><%=numIdleConnections%></td>

</tr>

<tr>

<td>都是checkoutconnection,但他们已经不在池中管理了.当他们checkin时候,将被destory</td>

<td><%=numUnclosedOrphanedConnections%></td>

</tr>

</table>

<form action="c3p0.jsp" method="post">

<input type="hidden" id="clear" name="clear" value="1"/>

<input type="submit" value="清空连接池"/>

</form>

</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。如果要加大并发连接数,应同时加大这两个参数。

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"

connectionTimeout="20000"

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)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存 优化 溢出