1、java处理高并发高负载类网站的优化方法java处理高并发高负载类网站的优化方法 一:高并发高负载类网站关注点之数据库没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作。我推荐的是M-M-Slaves方式,2个主Mysql,多个Slaves,需要注意的是,虽然有2个Master,但是同时只有1个是Active,我们可以在一定时候
2、切换。之所以用2个M,是保证M不会又成为系统的SPOF。Slaves可以进一步负载均衡,可以结合LVS,从而将select操作适当的平衡到不同的slaves上。以上架构可以抗衡到一定量的负载,但是随着用户进一步增加,你的用户表数据超过1千万,这时那个M变成了SPOF。你不能任意扩充Slaves,否则复制同步的开销将直线上升,怎么办?我的方法是表分区,从业务层面上进行分区。最简单的,以用户数据为例。根据一定的切分方式,比如id,切分到不同的数据库集群去。全局数据库用于meta数据的查询。缺点是每次查询,会增加一次,比如你要查一个用户nightsailer,你首先要到全局数据库群找到nightsa
3、iler对应的cluster id,然后再到指定的cluster找到nightsailer的实际数据。每个cluster可以用m-m方式,或者m-m-slaves方式。这是一个可以扩展的结构,随着负载的增加,你可以简单的增加新的mysql cluster进去。需要注意的是:1、禁用全部auto_increment的字段2、id需要采用通用的算法集中分配3、要具有比较好的方法来监控mysql主机的负载和服务的运行状态。如果你有30台以上的mysql数据库在跑就明白我的意思了。4、不要使用持久性链接(不要用pconnect),相反,使用sqlrelay这种第三方的数据库链接池,或者干脆自己做,因为
4、php4中mysql的链接池经常出问题。二:高并发高负载网站的系统架构之HTML静态化 其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是 最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点 的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限 管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必
5、不可少的。除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛 中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这 部分内容进行后台更新的时候进行静态化,这样避免了大量的
6、数据库访问请求高并发。网站HTML静态化解决方案 当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:HTTP请求-Web服务器-Servlet-业务逻辑处理-访问数据-填充JSP-响应请求HTML静态化之后:HTTP请求-Web服务器-Servlet-HTML-响应请求静态访求如下Servlet:java view plaincopyprint?1. public void doGet(HttpServletRequest request, HttpServletResponse response) 2. throws ServletException, I
7、OException 3. if(request.getParameter(chapterId) != null) 4. String chapterFileName = bookChapterRead_+request.getParameter(chapterId)+.html; 5. String chapterFilePath = getServletContext().getRealPath(/) + chapterFileName; 6. File chapterFile = new File(chapterFilePath); 7. if(chapterFile.exists()r
8、esponse.sendRedirect(chapterFileName);return;/如果有这个文件就告诉浏览器转向 8. INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl(); 9. NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter(chapterId);/章节信息 10. int lastPageId = novelChapterBiz.searchLastC
9、HapterId(novelChapter.getNovelId().getId(), novelChapter.getId(); 11. int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId(); 12. request.setAttribute(novelChapter, novelChapter); 13. request.setAttribute(lastPageId, lastPageId); 14. request.setA
10、ttribute(nextPageId, nextPageId); 15. new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(), 16. chapterFileName, chapterFilePath, /bookRead.jsp); 17. 18. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
11、 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(chap
12、terFileName);return;/如果有这个文件就告诉浏览器转向 INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl(); NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter(chapterId);/章节信息 int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().
13、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 CreateStaticH
14、TMLPage().createStaticHTMLPage(request, response, getServletContext(), chapterFileName, chapterFilePath, /bookRead.jsp); 生成HTML静态页面的类: java view plaincopyprint?1. package com.jb.y2t034.thefifth.web.servlet; 2. import java.io.ByteArrayOutputStream; 3. import java.io.FileOutputStream; 4. import java.i
15、o.IOException; 5. import java.io.OutputStreamWriter; 6. import java.io.PrintWriter; 7. import javax.servlet.RequestDispatcher; 8. import javax.servlet.ServletContext; 9. import javax.servlet.ServletException; 10. import javax.servlet.ServletOutputStream; 11. import javax.servlet.http.HttpServletRequ
16、est; 12. import javax.servlet.http.HttpServletResponse; 13. import javax.servlet.http.HttpServletResponseWrapper; 14. /* 15. * 创建HTML静态页面 16. * 功能:创建HTML静态页面 17. * 时间:2009年1011日 18. * 地点:home 19. * author mavk 20. * 21. */ 22. public class CreateStaticHTMLPage 23. /* 24. * 生成静态HTML页面的方法 25. * param
17、request 请求对象 26. * param response 响应对象 27. * param servletContext Servlet上下文 28. * param fileName 文件名称 29. * param fileFullPath 文件完整路径 30. * param jspPath 需要生成静态文件的JSP路径(相对即可) 31. * throws IOException 32. * throws ServletException 33. */ 34. public void createStaticHTMLPage(HttpServletRequest reques
18、t, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException 35. response.setContentType(text/html;charset=gb2312);/设置HTML结果流编码(即HTML文件编码) 36. RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath)
19、;/得到JSP资源 37. final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();/用于从ServletOutputStream中接收资源 38. final ServletOutputStream servletOuputStream = new ServletOutputStream()/用于从HttpServletResponse中接收资源 39. public void write(byte b, int off,int len) 40. byteArrayOutputStream
20、.write(b, off, len); 41. 42. public void write(int b) 43. byteArrayOutputStream.write(b); 44. 45. ; 46. final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream);/把转换字节流转换成字符流 47. HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response)/用
21、于从response获取结果流资源(重写了两个方法) 48. public ServletOutputStream getOutputStream() 49. return servletOuputStream; 50. 51. public PrintWriter getWriter() 52. return printWriter; 53. 54. ; 55. rd.include(request, httpServletResponse);/发送结果流 56. printWriter.flush();/刷新缓冲区,把缓冲区的数据输出 57. FileOutputStream fileOu
22、tputStream = new FileOutputStream(fileFullPath); 58. byteArrayOutputStream.writeTo(fileOutputStream);/把byteArrayOuputStream中的资源全部写入到fileOuputStream中 59. fileOutputStream.close();/关闭输出流,并释放相关资源 60. response.sendRedirect(fileName);/发送指定文件流到客户端 61. 62. package com.jb.y2t034.thefifth.web.servlet; import
23、 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.Servlet
24、OutputStream; 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 r
25、equest 请求对象 * param response 响应对象 * param servletContext Servlet上下文 * param fileName 文件名称 * param fileFullPath 文件完整路径 * param jspPath 需要生成静态文件的JSP路径(相对即可) * throws IOException * throws ServletException */ public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,Servl
26、etContext 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 byteArr
27、ayOutputStream = 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) byteArrayOutput
28、Stream.write(b); ; final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream);/把转换字节流转换成字符流 HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response)/用于从response获取结果流资源(重写了两个方法) public ServletOutputStream getOutputStream() return servletOup
29、utStream; public PrintWriter getWriter() return printWriter; ; rd.include(request, httpServletResponse);/发送结果流 printWriter.flush();/刷新缓冲区,把缓冲区的数据输出 FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath); byteArrayOutputStream.writeTo(fileOutputStream);/把byteArrayOuputStream中的资源全部写入到f
30、ileOuputStream中 fileOutputStream.close();/关闭输出流,并释放相关资源 response.sendRedirect(fileName);/发送指定文件流到客户端 三:高并发高负载类网站关注点之缓存、负载均衡、存储缓存是另一个大问题,我一般用memcached来做缓存集群,一般来说部署10台左右就差不多(10g内存池)。需要注意一点,千万不能用使用swap,最好关闭linux的swap。负载均衡/加速可能上面说缓存的时候,有人第一想的是页面静态化,所谓的静态html,我认为这是常识,不属于要点了。页面的静态化随之带来的是静态服务的负载均衡和加速。我认为Li
31、ghttped+Squid是最好的方式了。LVS lighttped=squid(s) =lighttpd上面是我经常用的。注意,我没有用apache,除非特定的需求,否则我不部署apache,因为我一般用php-fastcgi配合lighttpd,性能比apache+mod_php要强很多。squid的使用可以解决文件的同步等等问题,但是需要注意,你要很好的监控缓存的命中率,尽可能的提高的90%以上。squid和lighttped也有很多的话题要讨论,这里不赘述。存储存储也是一个大问题,一种是小文件的存储,比如图片这类。另一种是大文件的存储,比如搜索引擎的索引,一般单文件都超过2g以上。小文件的存储最简单的方法是结合lighttpd来进行分布。或者干
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1