记一次系统登录缓慢的优化

最近遇到一个系统登录缓慢的问题。一开始想到的就是删掉一些不需要的逻辑,把js放到底部,<script>标签使用defer属性,以及SQL的优化,建索引等数据库的优化,但是效果还是不是很明显。于是继续对一些看似不必要的逻辑统统删掉,但是总是怕删掉一些逻辑后因为测试不充分造成bug,开始投鼠忌器。光这样下去也不是办法,应该找到最耗时的地方,于是用httpwatch查看从登录到进入使用页面整个过程的详细情况。在一系列的操作中发现有个操作非常耗时,达到4~5秒这样,需要查表,然后循环操作,还要在页面循环组装数据,相当费时。整个页面分为几个iframe,当全部的iframe都加在完成之后,等待页面的遮蔽层才消失显示操作页面。最初的想法是,重要的页面先展示,不让用户在等待页面等待太久,这样用户长时间没有跳转到使用页面就会烦躁。于是就把下面的if条件去掉。

if (document.frames("top_frame").readyState == "complete") {
  document.getElementById("loading").style.display = "none";
}
但是我的思路看起来太简单了,这个iframe里面有个用户常使用的地方,如果不等它加载完就退出等待页面这一块区域还是一片空白,用户不能使用。于是干脆把耗时的地方使用异步来加载。首先第一次加载的时候先返回页面,后台不做什么操作,立即返回页面。然后等整个页面都加在后10秒再用ajax去进行耗时的操作。
window.onload = function() {
  setInterval(10000, lazyLoadData());
}

function lazyLoadData() {
  $.ajax({
     //异步请求
  });
}
顺便把页面组装数据的操作移到后台一并完成,然后返回json到页面展示,改造后数度比之前快了大概3~4秒。但是整个登录过程相对其他系统来说确实还是慢了一点。接着就上网搜搜一些解决方案。无意中看到一个facebook对页面加载数据优化的解决方案,据说这个方案耗时半年把数据提高了一倍,从5秒编程2.5秒,这个技术较bigpipe,直译过来就叫大管道,挺形象的,呵呵。原理大概看了下,分为单线程和多线程两种模式,单线程模式最终的耗时和没使用bigpipe几乎一样,但是它将页面分块,加载完一块就展示一个块,用户体验比没使用之前好一些。我着重看了下多线程模式的,将一个页面分割为多个块之后,每块并发地向服务器取资源,也是加载完就展示,整个页面加载时间取决于最耗时的那一块,这样串行的步骤编程并行的了,速度当然就快多了。我找了个例子,是用struts2标签实现的。之前也用过struts标签,所以也就当复习一下,呵呵。

标签是这样的:

<b:multiThread pageLetNum="6" bigPipeJSPath="js/bigpipeMulti.js">
</b:multiThread>
在tld文件中这样定义multiThread标签的:

<tag>
		<name>multiThread</name>
		<tag-class>com.bigpipe.tag.MultiThreadTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>pageLetNum</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<name>bigPipeJSPath</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
</tag>
在MultiThreadTag.java的getBean方法中

	@Override
	public Component getBean(ValueStack vs, HttpServletRequest arg1,
			HttpServletResponse arg2) {
		CountDownLatch end = new CountDownLatch(Integer.parseInt(pageLetNum));   
		arg1.setAttribute(COUNT_DOWN, end);
		return new MultiThread(vs, arg1, arg2);
	}
在MultiThread.java中的start方法和end方法

@Override
	public boolean start(Writer writer) {
		boolean start = super.start(writer);
		try {
			writer.write("<script type='text/javascript' src='" + bigPipeJSPath
					+ "'></script>");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return start;
	}

	@Override
	public boolean end(Writer writer, String body) {
		boolean end = super.end(writer, body);
		CountDownLatch c = (CountDownLatch)request.getAttribute(MultiThreadTag.COUNT_DOWN);
		try {
			c.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return end;
	}
虽然有个例子了,但是这个例子只是实现了一个模拟耗时页面的多线程模式的bigpipe的实现,具体用在我的系统中还是要做一些改动的,还在修改中,但是bigpipe这个思路应该还是能很大程度上提高登录速度的。






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值