JAVA WEB高并发解决方案文档格式.docx
《JAVA WEB高并发解决方案文档格式.docx》由会员分享,可在线阅读,更多相关《JAVA WEB高并发解决方案文档格式.docx(13页珍藏版)》请在冰点文库上搜索。
![JAVA WEB高并发解决方案文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/9/209bf978-4f85-4578-8d24-3cecd6fa6432/209bf978-4f85-4578-8d24-3cecd6fa64321.gif)
4、不要使用持久性链接(不要用pconnect),相反,使用sqlrelay这种第三方的数据库链接池,或者干脆自己做,因为php4中mysql的链接池经常出问题。
二:
高并发高负载网站的系统架构之HTML静态化
其实大家都知道,效率最高、消耗最小的就是纯静态化最有效的方法。
但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求高并发。
网站HTML静态化解决方案
当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:
HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填充JSP--响应请求
HTML静态化之后:
HTTP请求---Web服务器---Servlet--HTML--响应请求
静态访求如下
Servlet:
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
if(request.getParameter("
chapterId"
)!
=null){
StringchapterFileName="
bookChapterRead_"
+request.getParameter("
)+"
.html"
;
StringchapterFilePath=getServletContext().getRealPath("
/"
)+chapterFileName;
FilechapterFile=newFile(chapterFilePath);
if(chapterFile.exists()){response.sendRedirect(chapterFileName);
return;
}//如果有这个文件就告诉浏览器转向
INovelChapterBiznovelChapterBiz=newNovelChapterBizImpl();
NovelChapternovelChapter=novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("
)));
//章节信息
intlastPageId=novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(),novelChapter.getId());
intnextPageId=novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(),novelChapter.getId());
request.setAttribute("
novelChapter"
novelChapter);
lastPageId"
lastPageId);
nextPageId"
nextPageId);
newCreateStaticHTMLPage().createStaticHTMLPage(request,response,getServletContext(),
chapterFileName,chapterFilePath,"
/bookRead.jsp"
);
}
}
生成HTML静态页面的类:
packagecom.jb.y2t034.thefifth.web.servlet;
importjava.io.ByteArrayOutputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjavax.servlet.RequestDispatcher;
importjavax.servlet.ServletContext;
importjavax.servlet.ServletException;
importjavax.servlet.ServletOutputStream;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpServletResponseWrapper;
/**
*创建HTML静态页面
*功能:
创建HTML静态页面
*时间:
2009年1011日
*地点:
home
*@authormavk
*
*/
publicclassCreateStaticHTMLPage{
/**
*生成静态HTML页面的方法
*@paramrequest请求对象
*@paramresponse响应对象
*@paramservletContextServlet上下文
*@paramfileName文件名称
*@paramfileFullPath文件完整路径
*@paramjspPath需要生成静态文件的JSP路径(相对即可)
*@throwsIOException
*@throwsServletException
*/
publicvoidcreateStaticHTMLPage(HttpServletRequestrequest,HttpServletResponseresponse,ServletContextservletContext,StringfileName,StringfileFullPath,StringjspPath)throwsServletException,IOException{
response.setContentType("
text/html;
charset=gb2312"
//设置HTML结果流编码(即HTML文件编码)
RequestDispatcherrd=servletContext.getRequestDispatcher(jspPath);
//得到JSP资源
finalByteArrayOutputStreambyteArrayOutputStream=newByteArrayOutputStream();
//用于从ServletOutputStream中接收资源
finalServletOutputStreamservletOuputStream=newServletOutputStream(){//用于从HttpServletResponse中接收资源
publicvoidwrite(byte[]b,intoff,intlen){
byteArrayOutputStream.write(b,off,len);
publicvoidwrite(intb){
byteArrayOutputStream.write(b);
};
finalPrintWriterprintWriter=newPrintWriter(newOutputStreamWriter(byteArrayOutputStream));
//把转换字节流转换成字符流
HttpServletResponsehttpServletResponse=newHttpServletResponseWrapper(response){//用于从response获取结果流资源(重写了两个方法)
publicServletOutputStreamgetOutputStream(){
returnservletOuputStream;
publicPrintWritergetWriter(){
returnprintWriter;
rd.include(request,httpServletResponse);
//发送结果流
printWriter.flush();
//刷新缓冲区,把缓冲区的数据输出
FileOutputStreamfileOutputStream=newFileOutputStream(fileFullPath);
byteArrayOutputStream.writeTo(fileOutputStream);
//把byteArrayOuputStream中的资源全部写入到fileOuputStream中
fileOutputStream.close();
//关闭输出流,并释放相关资源
response.sendRedirect(fileName);
//发送指定文件流到客户端
三:
高并发高负载类网站关注点之缓存、负载均衡、存储
缓存是另一个大问题,我一般用memcached来做缓存集群,一般来说部署10台左右就差不多(10g内存池)。
需要注意一点,千万不能用使用
swap,最好关闭linux的swap。
负载均衡/加速
可能上面说缓存的时候,有人第一想的是页面静态化,所谓的静态html,我认为这是常识,不属于要点了。
页面的静态化随之带来的是静态服务的
负载均衡和加速。
我认为Lighttped+Squid是最好的方式了。
LVS<
------->
lighttped====>
squid(s)====lighttpd
上面是我经常用的。
注意,我没有用apache,除非特定的需求,否则我不部署apache,因为我一般用php-fastcgi配合lighttpd,
性能比apache+mod_php要强很多。
squid的使用可以解决文件的同步等等问题,但是需要注意,你要很好的监控缓存的命中率,尽可能的提高的90%以上。
squid和lighttped也有很多的话题要讨论,这里不赘述。
存储
存储也是一个大问题,一种是小文件的存储,比如图片这类。
另一种是大文件的存储,比如搜索引擎的索引,一般单文件都超过2g以上。
小文件的存储最简单的方法是结合lighttpd来进行分布。
或者干脆使用Redhat的GFS,优点是应用透明,缺点是费用较高。
我是指
你购买盘阵的问题。
我的项目中,存储量是2-10Tb,我采用了分布式存储。
这里要解决文件的复制和冗余。
这样每个文件有不同的冗余,这方面可以参考google的gfs的论文。
大文件的存储,可以参考nutch的方案,现在已经独立为hadoop子项目。
(你可以googleit)
其他:
此外,passport等也是考虑的,不过都属于比较简单的了。
四:
高并发高负载网站的系统架构之图片服务器分离
大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。
这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。
利用Apache实现图片服务器的分离
缘由:
起步阶段的应用,都可能部署在一台服务器上(费用上的原因)
第一个优先分离的,肯定是数据库和应用服务器。
第二个分离的,会是什么呢?
各有各的考虑,我所在的项目组重点考虑的节约带宽,服务器性能再好,带宽再高,并发来了,也容易撑不住。
因此,我这篇文章的重点在这里。
这里重点是介绍实践,不一定符合所有情况,供看者参考吧,
环境介绍:
WEB应用服务器:
4CPU双核2G,内存4G
部署:
Win2003/ApacheHttpServer2.1/Tomcat6
数据库服务器:
Win2003/MSSQL2000
步骤:
步骤一:
增加2台配置为:
2CPU双核2G,内存2G普通服务器,做资源服务器
Tomcat6,跑了一个图片上传的简单应用,(记得指定web.xml的<
distributable/>
),并指定域名为res1.***.com,res2.***.com,采用ajp协议
步骤二:
修改Apachehttpd.conf配置
原来应用的文件上传功能网址为:
1、/fileupload.html
2、/otherupload.html
在httpd.conf中增加如下配置
<
VirtualHost*:
80>
ServerAdminwebmaster@***.com
ProxyPass/fileupload.htmlbalancer:
//rescluster/fileuploadlbmethod=byrequestsstickysession=JSESSIONIDnofailover=Offtimeout=5maxattempts=3
ProxyPass/otherupload.htmlbalancer:
//rescluster/otherupload.htmllbmethod=byrequestsstickysession=JSESSIONIDnofailover=Offtimeout=5maxattempts=3
#<
!
--负载均衡-->
<
Proxybalancer:
//rescluster/>
BalancerMemberajp:
//res1.***.com:
8009smax=5max=500ttl=120retry=300loadfactor=100route=tomcat1
//res2.***.com:
8009smax=5max=500ttl=120retry=300loadfactor=100route=tomcat2
/Proxy>
/VirtualHost>
步骤三,修改业务逻辑:
所有上传文件在数据库中均采用全url的方式保存,例如产品图片路径存成:
http:
//res1.***.com/upload/20090101/product120302005.jpg
现在,你可以高枕无忧了,带宽不够时,增加个几十台图片服务器,只需要稍微修改一下apache的配置文件,即可。
五:
高并发高负载网站的系统架构之数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。
我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。
sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
集群软件的分类:
一般来讲,集群软件根据侧重的方向和试图解决的问题,分为三大类:
高性能集群(Highperformancecluster,HPC)、负载均衡集群(Loadbalancecluster,LBC),高可用性集群(Highavailabilitycluster,HAC)。
高性能集群(Highperformancecluster,HPC),它是利用一个集群中的多台机器共同完成同一件任务,使得完成任务的速度和可靠性都远远高于单机运行的效果。
弥补了单机性能上的不足。
该集群在天气预报、环境监控等数据量大,计算复杂的环境中应用比较多;
负载均衡集群(Loadbalancecluster,LBC),它是利用一个集群中的多台单机,完成许多并行的小的工作。
一般情况下,如果一个应用使用的人多了,那么用户请求的响应时间就会增大,机器的性能也会受到影响,如果使用负载均衡集群,那么集群中任意一台机器都能响应用户的请求,这样集群就会在用户发出服务请求之后,选择当时负载最小,能够提供最好的服务的这台机器来接受请求并相应,这样就可用用集群来增加系统的可用性和稳定性。
这类集群在网站中使用较多;
高可用性集群(Highavailabilitycluster,HAC),它是利用集群中系统的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务,等待故障机的维修和返回。
最大限度的保证集群中服务的可用性。
这类系统一般在银行,电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。
2数据库集群的现状
数据库集群是将计算机集群技术引入到数据库中来实现的,尽管各厂商宣称自己的架构如何的完美,但是始终不能改变Oracle当先,大家追逐的事实,在集群的解决方案上OracleRAC还是领先于包括微软在内的其它数据库厂商,它能满足客户高可用性、高性能、数据库负载均衡和方便扩展的需求。
Oracle’sRealApplicationCluster(RAC)
MicrosoftSQLClusterServer(MSCS)
IBM’sDB2UDBHighAvailabilityCluster(UDB)
SybaseASE