压缩网页载入时间:Web页面并行化的几点考虑

原创
开发 前端
缩短网页载入时间是建立网站时所必须要考虑的问题。为进一步缩短网页载入时间,将数据库访问并行是一个十分有效的方法。本文介绍Web页面并行化中需要考虑的几个问题,以及Java的实现方式。

【51CTO精选译文】建立网站时,最常见的需求是将网页载入时间最小化,例如,一般对主要页面的载入时间要求控制在0.5秒以内,当然网页载入时间是与许多因素关联的,如网络,缓存,Web服务器,脚本语言/代码,数据库访问等。当然我想要讨论在创建Web页面时对数据库的访问,我指的是动态Web页面,如使用PHP,Java/J2EE,Ruby和Asp(.NET)等创建的动态Web页面。

一个非常常见的编程风格是使用脚本段,如:

  1. < html> 
  2. < body> 
  3.     Time now is < %= new java.util.Date() %> 
  4. < /body> 
  5. < /html> 

使用当前时间的文本代替上面的“< %= new java.util.Date() %>”。

如果我制作了一个动态内容站点,比如使用Wordpress建立一个博客站点,需要生成多个动态内容,如最新的帖子,热门标签,帖子评论等,同样也会生成对数据库的访问,主要是查询数据库,我想这里不用再多说什么,大家都能理解了。

问题

在生成一些“重量级”的网页时,如在线报纸和书店,可能会涉及到多个查询,如你是否已经登录?我们是否有建议推给你?最新的主题是什么?你以前的兴趣是什么?你有朋友在线吗?你在网站上会产生什么内容?

我最近审查一个网站,每个页面产生的查询次数都大于500,我个人认为这是一个非常高的数目了,但这些查询确实都是需要的,问题是网页载入时间花了2秒。

经过调整,重写和使用索引后,页面载入时间下降到0.6秒,但这还不够快,问题是所有数据库访问都是串行的,它们需要并行起来。Web页面并行化的需求由此诞生。

MySQL为一个查询计算只能使用一个线程,但I/O却是支持多线程的,这就导致在标准的Linux发行版上,对于一个给定的Web页面,只有一个CPU可以使用。模板引擎是一个接一个地解析脚本段的,按顺序执行的,在Java中,一个JSP页面被重写为一个普通的Java Servlet类,脚本段成为主要的代码,HTML代码成为打印标准的输出,因此获得是线性执行代码。

即便是再先进的框架,其标准的方法还是线性的,例如,使用Spring框架,你有Java对象和控制器负责Web页面,可以避免在动态Web页面中使用脚本,只需要那些控制器提供的数据,因此如果使用Spring + Velocity,一个Web页面看起来就会是:

  1. < html> 
  2. < body> 
  3.     Login time as recorded in DB is: ${user.loginTime}  
  4. < /body> 
  5. < /html> 

在预建user对象时调用getLoginTime()方法进行转换,但这个方法是如何工作的呢?

它会缓慢地初始化以便访问数据库得到答案吗?

在某些init()方法期间控制器会设置值吗?

控制器会设置值以响应Web页面的请求参数,并逐一解析它们吗?

上面的一切都是线性或是串行执行的。

压缩网页载入时间:如何并行?

Web页面并行化不是一件容易的事情,需要理解多线程编程,程序员需要了解竞争环境、死锁和资源缺乏问题等,不过这些在动态网页中一般不会成问题,有些编程语言对多线程编程提供了良好的支持,Java就是这样一门语言。

假设我需要产生一个10个查询来响应Web页面的请求,如使用Java,我们可以像下面这样编写代码:

  1. CountDownLatch doneSignal = new CountDownLatch(10);  
  2.  
  3. Runnable task1 = new Runnable() {  
  4.     public void run()  
  5.     {  
  6.         user.setLoginTime(this.jdbcTemplate.queryForInt("SELECT ... FROM ..."));  
  7.         doneSignal.countDown();  
  8.     }  
  9. } ;  
  10.  
  11. Runnable task2 = new Runnable() {  
  12.     public void run()  
  13.     {  
  14.         headlines = getSimpleJdbcTemplate().query("SELECT * FROM headline WHERE...",  
  15.             new ParameterizedRowMapper< Headline>() {  
  16.                 public Headline mapRow(ResultSet rs, int rowNum)  
  17.                 {  
  18.                     Headline headline = new Headline();  
  19.                     headline.setTitle(rs.getString("title");  
  20.                     headline.setUrl(rs.getString("url");  
  21.                     ...  
  22.                 }  
  23.             }  
  24.         doneSignal.countDown();  
  25.     }  
  26. } ;  
  27.  
  28. ...  
  29.  
  30. Runnable task10 = new Runnable() {  
  31.     ...  
  32.     doneSignal.countDown();  
  33. }  
  34. Executor executor = Executors.newFixedThreadPool(numberOfAvailableProcessors);  
  35. executor.execute(task1);  
  36. ...  
  37. executor.execute(task10);  
  38.  
  39. doneSignal.await();  
  40.  
  41. // Now fill in the Model  

上面的代码其实相对较简单,可读性也比较好,它的意思是:

◆让我们创建10个任务,但不执行它们,仅仅是制定命令;

◆每项任务完成后,让CountDownLatch知道它已经完成(但记住我们还没有执行它);

◆我们创建或使用一个线程池,使用n个线程,n可以与我们的处理器数量进行关联;

◆我们要求线程池处理所有的线程,在处理过程中,要么是同时运行它们,要么有些是顺序执行,依赖于有多少线程可使用;

◆我们请求CountDownLatch进行阻塞,直到这10个任务都通知已经完成了;

接着执行下一批任务。

Spring有一个内置的TaskExecutor机制提供与上面说的线程池类似的解决方案。

我大多数时候都是使用的C/C++/Java,我不知道在PHP,Ruby,ASP.NET或其它语言该如何实现,上面的代码肯定不能拿去直接使用,我希望看到框架能够提供解决这个问题的方案,以便对于一般的Web开发都可以用上Web页面并行技术。

原文:The DB problem inherent to dynamic web pages

作者:Shlomi Noach

【推荐阅读】

  1. Web性能之战打响 开发者面临复杂度挑战
  2. Google专家:JavaScript是网站性能的致命克星
  3. Google面向开发者推出网页加速工具Page Speed
  4. 缓存设计详解:低成本的高性能Web应用解决方案
  5. 高性能Web应用的六个好习惯
责任编辑:yangsai 来源: 51CTO.com
相关推荐

2009-10-10 10:44:15

ASP.NET页面缓存

2018-10-29 09:24:41

Web图片压缩网页加速

2009-04-20 15:20:36

JSON网站布局实际模块

2010-04-26 10:31:13

Aix系统安全

2018-10-18 09:34:16

高并发异步化并行化

2017-09-19 14:28:06

Web开发网站

2013-02-26 14:07:52

SQL Server虚拟化

2021-06-07 15:01:18

银行数字化转型数据安全

2009-08-13 09:01:00

ASP.NET开发Web标准

2023-10-07 10:42:44

微软微软商店应用

2010-04-27 11:42:24

虚拟化

2012-03-07 17:00:22

响应式Web

2018-09-04 10:57:50

MySQLMariaDB数据库

2015-09-18 10:57:45

Web网页性

2018-06-05 11:28:30

同有科技

2011-04-27 10:57:29

高性能web开发

2021-06-02 11:10:09

PythonWeb可视化

2011-04-07 16:23:09

Web网页设计编码

2021-10-08 10:26:07

文件存储数据存储存储

2011-05-18 09:44:39

虚拟化服务器安全
点赞
收藏

51CTO技术栈公众号