二:高并发高负载网站的系统架构之HTML静态化其实大家都知道,效率最高、消耗最小的就是纯静态化 http://www.ablanxue.com/shtml/201207/776.shtml的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是 最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点 的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限 管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛 中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这 部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求高并发。
网站HTML静态化解决方案
当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:
HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填充JSP--响应请求
HTML静态化之后:
HTTP请求---Web服务器---Servlet--HTML--响应请求
静态访求如下
Servlet:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(request.getParameter("chapterId") != null){
String chapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";
String chapterFilePath = getServletContext().getRealPath("/") + chapterFileName;
File chapterFile = new File(chapterFilePath);
if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有这个文件就告诉浏览器转向
INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();
NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));//章节信息
int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
request.setAttribute("novelChapter", novelChapter);
request.setAttribute("lastPageId", lastPageId);
request.setAttribute("nextPageId", nextPageId);
new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(),
chapterFileName, chapterFilePath, "/bookRead.jsp");
}
}
生成HTML静态页面的类:
package com.jb.y2t034.thefifth.web.servlet;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
* 创建HTML静态页面
* 功能:创建HTML静态页面
* 时间:2009年1011日
* 地点:home
* @author mavk
*
*/
public class CreateStaticHTMLPage {
/**
* 生成静态HTML页面的方法
* @param request 请求对象
* @param response 响应对象
* @param servletContext Servlet上下文
* @param fileName 文件名称
* @param fileFullPath 文件完整路径
* @param jspPath 需要生成静态文件的JSP路径(相对即可)
* @throws IOException
* @throws ServletException
*/
public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException{
response.setContentType("text/html;charset=gb2312");//设置HTML结果流编码(即HTML文件编码)
RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//得到JSP资源
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//用于从ServletOutputStream中接收资源
final ServletOutputStream servletOuputStream = new ServletOutputStream(){//用于从HttpServletResponse中接收资源
public void write(byte[] b, int off,int len){
byteArrayOutputStream.write(b, off, len);
}
public void write(int b){
byteArrayOutputStream.write(b);
}
};
final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//把转换字节流转换成字符流
HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用于从response获取结果流资源(重写了两个方法)
public ServletOutputStream getOutputStream(){
return servletOuputStream;
}
public PrintWriter getWriter(){
return printWriter;
}
};
rd.include(request, httpServletResponse);//发送结果流
printWriter.flush();//刷新缓冲区,把缓冲区的数据输出
FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath);
byteArrayOutputStream.writeTo(fileOutputStream);//把byteArrayOuputStream中的资源全部写入到fileOuputStream中
fileOutputStream.close();//关闭输出流,并释放相关资源
response.sendRedirect(fileName);//发送指定文件流到客户端
}
}
|