最近自己做了一个做网络广告的网站叫全方位商机平台的 项目,由于网站首页上板块划分很多,不同板块的数据库查询方式不同,首页内容量巨大,如果按照一般的动态jsp页面的话那么数据库查询将是巨大的开销,会 导致首页访问速度的下降。于是考虑将这个首页全部静态化。参考地址:http://www.31pt.com/。首页的速度是非常快的。
整个网站才用struts2 + spring + hibernate + freemarker + urlrewrite完成。首页纯静态化,频道及其他页面通过urlrewrite伪静态。现在废话少说。我先给出首页jsp body源代码:
- Java code
-
<body>
<div id="wrap">
<!--头部开始-->
<jsp:include page="/html/top.html" flush="true"></jsp:include>
<!--头部结束-->
<!--导航开始-->
<jsp:include page="/html/channel.html" flush="true"></jsp:include>
<!--导航结束-->
<jsp:include page="/html/center.html" flush="true"></jsp:include>
<!--友情连接开始-->
<jsp:include page="/html/index_link.html" flush="true"></jsp:include>
<!--友情结束-->
<!--底部开始-->
<jsp:include page="/html/bottom.html" flush="true"></jsp:include>
<!--底部结束-->
</div>
</body>
整个网站首页的基本结构是通过jsp的include标签将所有通过freemarker生成的静态页面组织起来。后台控制各个部分的静态页生成。这样做 将首页进行了拆分,便于了静态页面的维护,当我们需要生成“友情链接”部分的时候就只生成友情链接部分,而不需要将整个页面都从新生成一次。
以下是我生成静态页最核心的方法,使用freemarker。
- Java code
-
/**
* 生成静态页面主方法
* @param context ServletContext
* @param data 一个Map的数据结果集
* @param templatePath ftl模版路径
* @param targetHtmlPath 生成静态页面的路径
*/
public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){
Configuration freemarkerCfg = new Configuration();
//加载模版
freemarkerCfg.setServletContextForTemplateLoading(context, "/");
freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
try {
//指定模版路径
Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");
template.setEncoding("UTF-8");
//静态页面路径
String htmlPath = context.getRealPath("/html")+"/"+targetHtmlPath;
File htmlFile = new File(htmlPath);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));
//处理模版
template.process(data, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
其实很简单,只要Google一下就有很多这方面的代码。我也是Google的代码然后自己再根据实际情况修改。简单说明一下参数:
ServletContext :这个不用说了吧。做java web的应该都知道,只不过struts2中这样获取ServletActionContext.getServletContext()
Map <String,Object> data : 模版的数据来源。freemarker通过一个Map给ftl模版送数据。
现在已友情链接为列子详细介绍静态页面如何生成。其他模块以此类推。
String templatePath : ftl所在的路径。我这里相对于网站的一个相对路径然后通过ServerContext获取绝对路径。
String targetHtmlPath : 最后生成静态页的路径:我这里相对于网站的一个相对路径然后通过ServerContext获取绝对路径。
友情链接根据这段代码 <jsp:include page="/html/index_link.html" flush="true"> </jsp:include>我们需要freemarker生成一个index_link.html文件。友情链接数据来源通过数据库查询获 取。
然后再写一个方法专门生成友情链接静态页面:
- Java code
-
/**
* 生成友情链接的静态页index_link.html
* @param context
* @param data
*/
public static void createIndexFriendLink(ServletContext context,Map<String,Object> data){
crateHTML(context,data,"index_link.ftl","index_link.html");
}
此方法调用上面的createHTML方法。
然后根据以上方法我们就可以再Struts2的action里面从数据库查询数据放入map调用createIndexFriendLink()方法生成静态页了。
这是action中的一个方法:
- Java code
-
/**
* 生成友情链接静态页index_link.html
* @return
*/
public String createLink(){
//权限验证
if(! this.isAccess())
return "error";
try{
//得到友情链接
List links = friendLinkDAO.findAll();
//准备数据
HashMap<String,Object> data = new HashMap<String,Object>();
data.put("links", links);
//调用静态页面方法
HTML.createIndexFriendLink(ServletActionContext.getServletContext(), data);
addActionMessage("静态页面生成成功!");
return "message";
}catch(Exception e){
e.printStackTrace();
return "failure";
}
}
List links = friendLinkDAO.findAll();通过spring注入action的hiberate DAO获取数据给list然后通过以下代码
HashMap <String,Object> data = new HashMap <String,Object>();
data.put("links", links);
准备数据调用createIndexFriendLink()方法。
以下是:ftl模版源码:
- Java code
-
<#if links?size != 0>
<div class="link">
<strong>友情链接:</strong>
<#list links as link>
<a href="${link.linkUrl}" target="_blank" title="${link.linkName}">${link.linkName}</a>
</#list>
</div>
<#else>
<div class="link"></div>
</#if>
这样友情链接静态页就生成了。然后其他静态页依此葫芦画瓢。
总结:虽然静态页访问速度快和其他的好处,但实现起来毕竟还是很麻烦了,维护也是一个麻烦事情。如果您的站点更新速度快那么就需要在你的后台数据更新部分 调用相应的createHTML方法实时的生成静态页面。如果更新速度不慢可以在后台手动更新或者利用操作系统的定时任务功能去执行你的静态页面生成程 序。www.361pt.com这个网站我是才用了这两种方式。
不 知道因为什么原因,当系统的访问量达到了8000IP的时候,tomcat的内存总是会莫名其妙的增加到上限,而且到最后垃圾回收也会非常费力,最后导致 系统停止响应,我调试过各种参数,包括垃圾回收策略,并行回收,修改各内存配置的参数,结果都一样,没办法,绝对对这一访问量最大的部分进行全部静态化。
一、静态化要考虑三个方面的事情,
1 对SEO
能够让搜索引擎更方便的进行信息采集和分类,提升其速度和准确性
2 对用户
不能影响版面的展示,不能为了速度影响了美观和可用性
3 对维护
一些内容可以方便的更换,比如菜单调整,连接调整,广告位的调整等
二、最终采用了如下的方案进行
1 使用freemarker进行静态化
2 将菜单,广告位等以后可能变化的地方,使用JS进行操作。 一些地方采用多个连续的JS,方便以后进行整体调整。
3 通过urlrewrite 将访问转到静态化后的页面
4 通过404的错误处理,对尚未静态化的页面进行处理
5 静态化时,考虑到帖子量在百万级别,为了防止一个文件夹下面有太多文件,决定根据帖子编号的末尾2位数字进行文件夹分组,比如12345 则分配到 45这个子文件夹里面,67890 则分配到90这个文件夹里面。这样就将帖子近似均分到100个文件夹,每个文件夹的帖子在1万个,还可以接受。如果以后帖子再多,我就再考虑分成1000 个文件夹了。这个设置要为以后的扩容留有余地。
三、具体操作
1 根据现有帖子页面制作ftl的模板,里面要考虑js的脚本位置。
2 制作批量生成的程序,为减轻服务器的压力,以某个数据库备份为蓝本,在本地完成这部分帖子的初始化,生成htm文件,然后将静态化好的目录整个打包上传到服务器。
3 启动404的处理,比较新的帖子如果没有被静态化,则由这个程序进行处理
4 帖子管理程序改造,在帖子保存时自动进行静态化
5 启动urlRewrite 其中比较关键的部分是
RewriteRule ^/view-([0-9]*?)([0-9]{2}).htm /laozizhu/$2/$1$2.htm [PT]
里面将帖子编号的最后2位单独分组出来,作为目录名,如果以后帖子多了,可以用最后三位来分组了。只需要再次生成帖子,然后简单的修改这个规则即可,前台访问不受任何影响。
四、效果:
目前网站访问量已经达到每天7w的独立IP,tomcat占用内存不超过300M,系统线程数一直在最低的线上。
五、总结
静态化,还是针对大访问量的最佳方案,不是伪静态化,而是真正的静态化。
网友方案三:
静态化是解决减轻网站压力,提高网站访问速度的常用方案,但在强调交互的We2.0 时代,对静态化提出了更高的要求,静态不仅要能静,还要能动,下面我通过一个项目,谈谈网站静态化后的架构设计方案,同时和大家探讨一下,在开源产品大行其道,言架构必称MemberCache, Nginx,的时代,微软技术在网站架构设计中的运用.
静态化的设计原则和步骤
静态化是解决减轻网站压力,但是静态化也会带来一系列的问题,包括开发上复杂度的增加,维护难度的增加,运用不的当,更可能适得其反,而许多替代方案,比如页面缓存,如果运用得当,也能起到很好的效果,所以在开始之前,必须进行详细的考察,确定是否适合静态化,并制定适合的静态化方式,下面先介绍一下
l 考查读写比:
读写比,准确的说是读写负荷比,是否值得静态化的最终考虑,由于一般写入的压力明显大于读出的压力,如果写入太频繁,或者每次写入消耗的资源太多,都不能达到效果,我觉得读写比例10:1应该是个上限.具体情况需要根据自己的业务逻辑判断
l 确定页面呈现的内容是否适合静态化:
在设计方案时,必须详细考虑每个原型页面,找到页面上展示的信息,和他的更新方式,更新时机,更新频率,一定要注意那些不起眼的信息,他们可能左右你的设计,
比如:我们以CSDN的论坛的任意一篇帖子为例,进行分析
上面的帖子中呈现的内容主要是这样几块,帖子内容,回复内容,发帖人回复人的用户信息
n 帖子内容和回复内容在发帖时更新,发帖后用户可以修改其内容,更新频率高
n 用户信息,用户修改个人信息时可能会发生更改,用户等级增加时也可能发生更改,比如加星,更新频率低
n 回复数将每次回复后都要更改,更新频率高
n 设计时要注意细节,如上图中圈出来的部分,这些部分是怎么修改的,频率有多大,一个都不能放过.
l 确定生成方式:
在上面帖子一例中.每次更改都重新生成页面是不可取的,一篇比回复数多的帖子,需要的数据量是巨大的(每层楼的用户信息,回复内容),任何修改,都需要重新取出数据进行生成是不能允许的.一般除非你的页面基本不用更新,或者更新开销极小,(比如一段嵌入的广告代码)才能采用整体更新的方式,不然就需要我们找到合适的更新页面局部区域的方法:
一般有下面两个方法:
1) 正则修改法:
比如,如果帖子中的回复数,html代码是这样
<label>回复数<var >方案二:
我们把生成的静态文件单独放置,可以看到,前端增加Nginx,作为跳转,把电影,影人资料库的页面转向静态服务器,其他的调用转向动态服务器,这样我们就可以单独为静态服务器进行优化,比如采用更高效的服务器等等.
同时减少了文件分发的次数(甚至可以只分发到本机),提高生成分发的处理能力
更进一步,可以把图片服务分到另外一组机器上,使用独立的域名,比如img.xxx.com,这样可以有效的减少带宽
最终完整架构:
![]()
文件生成分发中心
下图是文件生成分发中心的工作流程图
生成服务对外只有一个输入,就是消息,一个输出:静态文件,内部根据消息,从配置文件中找到对应的生成方法,取出相应的模板,进行数据填充
分发服务主要吧生成服务产生的文件进行分发,分发到前端的N台服务器上,开始考虑得比较复杂,希望分发服务可以跨越协议(本地文件系统,局域网,http协议),跨越多种存储介质(文件系统,数据库),实际最后定下来基本是本地文件系统或者局域网传输
注:上图中文件分发的部分也可以通过定制MogileFS,来实现分布式文件系统
马后炮:
总结起来,静态化除了对架构方面的影响,对开发和测试流程也有影响
对测试提出更高的要求:
因为一旦上线后,某个页面发现问题,即使是文字的修改,也需要重新生成许多页面,所以测试人员必须非常仔细,测试周期也需要延长
开发人员需要掌握模板语言
需要掌握一种模板预言,无论是Xslt还是自己开发的模板语言,都需要花一定的时间掌握
需要给第一次生成腾出足够时间:
如果不是新系统,那么数据迁移和生成的过程就比较痛苦,由于页面众多,第一次生成的过程可能需要以天来计算,在制定上线方案是就需要考虑到这个方面
Nginx作为前端的跳转,根据其他网站的经验,应该可以达到2-3万并发连接,但是使用之后,常常有卡壳的情况发生,具体症状为在浏览器中访问页面时,连接超时,或者一直不响应,此时Nginx连接数并不高,好在还有第一套方案可以备用,让我们有时间去解决这个问题,如果大家对这个问题有什么心得,欢迎交流
我的联系方式
Gtalk:yizhu2005@gmail.com
篇后:
在大型web开发上,我感到微软产品结构(包括微软开源社区的成果)在某些方面还存在一些不足:
高性能服务器选择太少
Linux下可以采用Light HTTPd,Nginx等诸多服务器,这些服务器在很多方面的表现会让Windows下唯一的选择--IIS相形见绌
分布式文件系统
微软及其社区没有比较著名的产品出现,Linux下有MogileFS
微软架构下,文件系统选择太少:
在Linux下我们可以选择诸如Ext3,ReiserFS,而Windows环境下,NTFS是唯一的选择,不过值得称道的是.NTFS的效率和稳定性都相当不错.
开源技术对windows版本的支持态度不积极
诸多在Linux下名声卓著的开源产品,又懒于为Windows提供相应的版本,或者提供的windows版本效果差强人意.使得采用微软服务器的厂商少了很多选择
现在的Web开发已经进入了各种技术大混合,大整合的时代,任何一个厂商都不可能涵盖所有方面,在后端架构和逻辑方面.Net和Java严谨,良好的编程风格,清晰的设计思路,较高的运行效率,以及稳定的配套服务支持,是其最大的优势,对主要擅长微软技术的Web工程师和架构师而言,应该增进对Linux及开源社区的了解,才能根据需求设计出合理的架构
http://iamlibai.blogbus.com/logs/2017870.html