??xml version="1.0" encoding="utf-8" standalone="yes"?>
~?/span>存的思想可以应用在Y件分层的各个层面。它是一U内部机Ӟ对外界而言Q是不可感知的?/span>
数据库本w有~存Q?span style="background: #d9d9d9 none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">持久?/span>也可以缓存。(比如Q?/span>hibernateQ还?/span>1U和2U缓存)
业务?/span>也可以有~存Q但一般来_q是一个过E域Q不会设~存Q?/span>
表现?/span>/数据服务?/span>Q传l?/span>web的表现层Q也可以讄~存Q?/span>jsp cache 是q一层,实现?/span>app server上的~存机制Q?/span>
另外Browser也有~存Q如IEQ这个大家也都知道(实现?/span> web server 上的~存机制Q。越上层的缓存效果越好,底层的~存影响深q?/span>
二、缓存实玎ͼ览器缓存当前访问的JSP动态页?/span>Q?/span>
Q一Q、服务端ҎQ?/span>
Q二Q、客LҎQ?/span>
meta是用来在HTML文中模?/span>HTTP协议的响应头报文?/span>meta 标签用于|页的<headQ与Q?/span>/headQ中Q?/span>meta 标签的用处很多?/span>meta 的属性有两种Q?/span>name?/span>http-equiv?/span>name属性主要用?span style="background: #d9d9d9 none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">描述|页Q对应于contentQ网内容)Q?span style="background: #d9d9d9 none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">以便于搜索引擎机器h查找、分c?/span>Q目前几乎所有的搜烦引擎都用网上机器h自动查找meta值来l网分c)。这其中最重要的是descriptionQ站点在搜烦引擎上的描述Q和keywordsQ分cd键词Q?/span>Q所以应该给每页加一?/span>meta倹{比较常用的有以下几个:
name 属?/span>
1、<meta name="Generator" contect=""Q用以说明生成工P?/span>Microsoft FrontPage 4.0Q等Q?/span>
2、<meta name="KEYWords" contect=""Q向搜烦引擎说明你的|页的关键词Q?/span>
3、<meta name="DEscription" contect=""Q告诉搜索引擎你的站点的主要内容Q?/span>
4、<meta name="Author" contect="你的姓名"Q告诉搜索引擎你的站点的制作的作者;
5、<meta name="Robots" contect="all|none|index|noindex|follow|nofollow"Q?/span>
其中的属性说明如下:
讑֮?/span>allQ文件将被检索,且页面上的链接可以被查询Q?/span>
讑֮?/span>noneQ文件将不被索,且页面上的链接不可以被查询;
讑֮?/span>indexQ文件将被检索;
讑֮?/span>followQ页面上的链接可以被查询Q?/span>
讑֮?/span>noindexQ文件将不被索,但页面上的链接可以被查询Q?/span>
讑֮?/span>nofollowQ文件将不被索,面上的链接可以被查询?/span>
http-equiv属?/span>
1、<meta http-equiv="Content-Type" contect="text/html";charset=gb_2312-80"Q?/span>
?/span>Q?/span>meta http-equiv="Content-Language" contect="zh-CN"Q用以说明主制作所使用的文字以及语aQ又如英文是ISO-8859-1字符集,q有BIG5?/span>utf-8?/span>shift-Jis?/span>Euc?/span>Koi8-2{字W集Q?/span>
2、<meta http-equiv="Refresh" contect="n;url=http://yourlink"Q定时让|页在指定的旉n内,跌{到页?/span>http;//yourlinkQ?/span>
3、<meta http-equiv="Expires" contect="Mon,12 May 2001 00:20:00 GMT"Q可以用于设定网늚到期旉Q一旦过期则必须到服务器上重新调用。需要注意的是必M?/span>GMT旉格式Q?/span>
4、<meta http-equiv="Pragma" contect="no-cache"Q是用于讑֮止览器从本地机的~存中调阅页面内容,讑֮后一旦离开|页无法从Cache中再调出Q?/span>
5、<meta http-equiv="set-cookie" contect="Mon,12 May 2001 00:20:00 GMT"Q?/span>cookie讑֮Q如果网过期,存盘?/span>cookie被删除。需要注意的也是必须使用GMT旉格式Q?/span>
6、<meta http-equiv="Pics-label" contect=""Q网늭U评定,?/span>IE?/span>internet选项中有一内容设|,可以防止览一些受限制的网站,而网站的限制U别是通过meta属性来讄的;
7、<meta http-equiv="windows-Target" contect="_top"Q强刉面在当前H口中以独立面昄Q可以防止自q|页被别人当作一?/span>frame调用;
8、<meta http-equiv="Page-Enter" contect="revealTrans(duration=10,transtion= 50)"Q和Q?/span>meta http-equiv="Page-Exit" contect="revealTrans(duration=20Q?/span>transtion =6)"Q设定进入和d面时的Ҏ效果Q这个功能即FrontPage中的“格式/|页q渡”Q不q所加的面不能够是一?/span>frame面?/span>
三、缓存应?/span>
Q一Q、防?/span>JSP面~存Z防止览器缓存当前访问的JSP动态页面,可以采用如下的方式进行设|:
<%
// 过期日期设|ؓ一个过L?/span>
response.setHeader("Expires", "Sat, 6 May 199512:00:00 GMT");
// 讄 HTTP/1.1 no-cache ?br /> response.setHeader("Cache-Control", "no-store,no-cache,must-revalidate");
// 讄 IE 扩展 HTTP/1.1 no-cache headersQ?用户自己d
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// 讄标准 HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
%>
当然Q每一个页面都包含q些代码会很J琐Q可以通过自定义过滤器QFilterQ的Ҏ来处理相关的面
Q?/span>二)?/span>jsp,html 清除面~存
1.止客户端缓存要?lt;head>中加入类似如下内容:
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 199708:21:57 GMT">
?/span> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
2.在服务器的动态网中止~存Q要加入cM如下脚本
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
Q三Q设|有限时间的~存
int minutes = 10;
Date d = new Date();
String modDate = d.toGMTString();
String expDate = null;
expDate = (new Date(d.getTime() + minutes * 60000)).toGMTString();
response.setHeader("Last-Modified", modDate);
response.setHeader("Expires", expDate);
response.setHeader("Cache-Control", "public"); // HTTP/1.1
response.setHeader("Pragma", "Pragma"); // HTTP/1.0
补充Q?/span>关于.jsp cache的几条徏?/span>:
1.jsp cache最好做在过滤器?/span>,把需要缓冲的面集中在同一个目录下,每次更改只须更改web.xml可以完成缓冲设|?/span>,q样比较方便.
2.Gzip压羃可以页面压~得很小,q_压羃比ؓ1/3,jsp cache?/span>HashMap~冲压羃后的面,肯定比没压羃前更节约内存消?/span>,q且效率更高.关于Gzip可以参考这个开源项?/span>:http://sourceforge.net/projects/pjl-comp-filter
序号 | 说明 |
是否必填 | 允许填写的?/td> | 允许的通配W?span class="Apple-converted-space"> |
1 | U?/td> | ?/td> | 0-59 | , - * / |
2 | ?/td> | ?/td> | 0-59 |
, - * / |
3 | 时 | ?/td> | 0-23 | , - * / |
4 | ?/td> | ?/td> | 1-31 | , - * ? / L W |
5 | ?/td> | ?/td> | 1-12 or JAN-DEC | , - * / |
6 | ?/td> | ?/td> | 1-7 or SUN-SAT | , - * ? / L # |
7 | q?/td> | ?/td> | empty ?1970-2099 | , - * / |
提C?br /> |
'L'?'W'可以一l合使用。如果在日字D上讄"LW",则表C在本月的最后一个工作日触发(一般指发工?img src="/CuteSoft_Client/CuteEditor/images/emteeth.gif" alt="" align="absmiddle" border="0" /> ) |
提C?br /> |
周字D늚讄Q若使用英文字母是不区分大小写的 MON 与mon相同. |
0 0 12 * * ? | 每天12点触?/td> |
0 15 10 ? * * | 每天10?5分触?/td> |
0 15 10 * * ? | 每天10?5分触?/td> |
0 15 10 * * ? * | 每天10?5分触?/td> |
0 15 10 * * ? 2005 | 2005q每?0?5分触?/td> |
0 * 14 * * ? | 每天下午?2点到2?9分每分触?/td> |
0 0/5 14 * * ? | 每天下午?2点到2?9?整点开始,每隔5分触? |
0 0/5 14,18 * * ? | 每天下午?2点到2?9?整点开始,每隔5分触? 每天下午?18点到18?9?整点开始,每隔5分触? |
0 0-5 14 * * ? | 每天下午?2点到2?5分每分触?/td> |
0 10,44 14 ? 3 WED | 3月分每周三下午的 2?0分和2?4分触?/td> |
0 15 10 ? * MON-FRI | 从周一到周五每天上午的10?5分触?/td> |
0 15 10 15 * ? | 每月15号上?0?5分触?/td> |
0 15 10 L * ? | 每月最后一天的10?5分触?/td> |
0 15 10 ? * 6L | 每月最后一周的星期五的10?5分触?/td> |
0 15 10 ? * 6L 2002-2005 | ?002q到2005q每月最后一周的星期五的10?5分触?/td> |
0 15 10 ? * 6#3 | 每月的第三周的星期五开始触?/td> |
0 0 12 1/5 * ? | 每月的第一个中午开始每?天触发一?/td> |
0 11 11 11 11 ? | 每年?1?1?11?1分触?光棍? |
如果你还不知?strong>l线表格怎么?/strong>Q请看下面的代码实现效果Q)
<table cellSpacing=0 cellPadding=0 border=0> <tr> <td bgcolor='black'> <table cellSpacing=1 cellPadding=1 border=0> <tr align=center bgcolor='#ffffff'> <td colspan=2>国家U?lt;/td><td colspan=1>市</td> </tr> <tr bgcolor='#ffffff' align=center> <td>人民日报</td> <td>解放日报</td> <td>新民晚报</td> </tr> </table> </td> </tr> </table>
然后把IE的设|ؓ可以打印背景Q本以ؓ可以大功告成?/p>
l果打印一预览Q头部一?strong>大黑?/strong>Qؓ什么呢Q因为我头部里面的有一个背景,l果占用面Q?/p>
.gTitle
{
width:100%;
height:32px;
line-height:32px;
background-image:url(images/gtitle.gif);
padding-left:130px;
margin-bottom:10px;
}
开始郁闷啦Q在|上搜了半天都没有一个完的解决ҎQ决定自己搞定?/p>
自己琢磨了半天,l于搞定Q)
Css定义如下Q?/p>
noneprintQ?打印旉藏的样式定义
tabPrintQ?nbsp; 要打印的l线表格样式定义
nextPateQ?nbsp; 分页的样式定?/p>
linetdQ?nbsp; 呵呵Q此处最关键Q让你的表格打印?strong>完美?span style="color: #ff0000">~?/span>
面HTML如下Q?nbsp;
记得在thead加上style="display:table-header-group;font-weight:bold"Q这h个页面才会有都表头哟
<div class="noneprint"> <div class="gTitle">>><A href="../Default.aspx" mce_href="Default.aspx">首页</A>>><A href="Default.aspx" mce_href="Default.aspx">门户</A>>>信息理</div> <table cellSpacing="0" cellPadding="2" width="100%" align="center" border="0" ID="Table1"> <tr> <td align="right">标题Q?lt;/td> <td><input name="txtFName" type="text" id="txtFName" style="width:150px;" /></td> <td align="right">所属街道:</td> <td><select name="ddlStreet" id="ddlStreet"> <option selected="selected" value="">-请选择状?</option> </select></td> <td align="right">录入日期Q?lt;/td> <td colSpan="3"><input name="sDate" type="text" id="sDate" onclick="setday(this)" style="width:80px;" />-- <input name="eDate" type="text" id="eDate" onclick="setday(this)" style="width:80px;" /></td> <td><input type="submit" name="btnSearch" value="查询" id="btnSearch" class="Button" /> <input type="button" onclick="window.print()" value="打印" class="Button" ID="Button1" NAME="Button1"></td> </tr> </table> </div> <table class='tabPrint' align="center" width="95%" cellSpacing="0" cellPadding="0" border="0" ID="Table2"> <thead style="display:table-header-group;font-weight:bold" mce_style="display:table-header-group;font-weight:bold"> <tr align="center"> <td rowspan="2">所属街?lt;/td> <td rowspan="2">标题</td> <td rowspan="2">录入日期</td> <td colspan="2">国家U?lt;/td> <td colspan="1">市</td> </tr> <tr align="center"> <td>人民日报</td> <td>解放日报</td> <td>新民晚报</td> </tr> </thead><tbody> <tr align="center"> <td>东新区三街道</td> <td>试</td> <td>02-24-2009</td> <td>√</td> <td>√</td> <td>√</td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sseref</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sseref</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center" class='nextPage'> <td colspan="6" class='linetd'>W??lt;/td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sdsedjiik</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sdsedjiik</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sdsedjiik</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sdsedjiik</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> <tr align="center"> <td>东新区三街道</td> <td>sdsedjiik</td> <td>02-24-2009</td> <td> </td> <td> </td> <td> </td> </tr> </tbody></table>
呵呵Q标CؓU色的地方你可要看仔l哟Q完不完全靠它Q?br />
转自Qhttp://blog.csdn.net/maomaoysq/archive/2009/02/24/3933480.aspx
Q?Q在server没有关闭Qƈ在session对象销毁时间内Q当客户端再ơ来hserver端的servlet或jspӞ会在W?一ơ请求时生成的sessionIdq带在h信息头中q向server端发送, server端收到sessionId后根据此sessionId会去搜烦Q此q程是透明的)server对应的session对象q直接返回这?session对象Q此时不会重新去建立一个新的session对象?/p>
Q?Q当server关闭Q之前生的session对象也就消亡了)Q或 session对象q了光毁时间后Q浏览器H口不关Qƈ在本览器窗口再ơ去hsever端的servlet和jspӞ此时同样会将 sessionIdQserver关闭或session销毁时生成的sessionIdQ发送到server端,serverҎsessionIdL 其对应的session对象Q但此时session对象已经不存在,此时会重新生成一个新的session对象Qƈ生成新的sessionIdq同样将q?个新生成的sessionId以响应报文的形式送到览器内存中?/p>
Q?Q当server没有关闭Qƈsession对象在其销毁时间内Q当h一?jsp面回客L后,关闭此浏览器H口Q此时其内存中的sessionId也就随之销毁,在重新去hsever端的servlet或jspӞ会重?生成一个sessionIdl客L览器,q存在浏览内存中?/p>
web.xml里面可以定义两种参数Q?(1)application范围内的参数Q存攑֜servletcontext中,在web.xml中配|如下:
(2)servlet范围内的参数Q只能在servlet的init()Ҏ中取得,在web.xml中配|如下:
在servlet中可以通过代码分别取用Q?/p>
1.把siyn-pager.jar攑ֈlib下,
2.把siyn-pager.tld攑ֈ/WEB-INF/?
3.修改web.xml文g,dtld配置
h意,我们怿能够在一台机器的多个JVM上运行系l的扩展方式是水qx展方式,而非垂直扩展方式。JVM实例之间的IPC机制是有限的Q两个JVM实例之间无法通过道、共享内存、信号量或指令来q行通讯Q不同的JVMq程之间最有效的通讯方式是socket。简而言之,如果Java EE应用如果扩展到多个JVM实例中运行,那么大多数情况下它也可以扩展到多台服务器上运行?br id="w9.22" />
随着计算来越便宜Q性能来高Q通过低成本的机器群l装为集可以获得超q那些昂늚计算机所具备的计能力。不q,大量的计机也意味着增加了管理的复杂性以及更为复杂的~程模型Q就像服务器节点之间的吞吐量和g时等问题?/p>
Java EE集群是一U成熟的技术,我在TSS上写了一名?#8220;Uncover the Hood of J2EE Clustering”的文章来描述它的内部机制?br id="foim2" />
从失败的目中吸取的教训
采用无共享的集群架构
Figure 3: share nothing cluster
最具备扩展性的架构当属无共享的集群架构。在q样的集中Q每个节点具备完全相同的功能Qƈ且不需要知道其他节点存在与否。负载均衡器(Load Balancer)来完成如何将h分发l这些后台的服务器实例。由于负载均衡器只是做一些简单的工作Q例如分z请求、健h查和保持sessionQ因此负载均衡器很少会成为瓶颈。如果后端的数据库系l或其他的信息系l够的强大Q那么通过增加更多的节点,集群的计能力可以得到线性的增长?br id="jsdn19" />
几乎所有的Java EE提供商在他们的集品中都实CHttpSession的failover功能Q这样即使在某些服务器节点不可用的情况下也仍然能够保证客L的请求中的session信息不丢失,但这点其实是打破了无׃n原则的。ؓ了实现failoverQ同Lsession数据会被两个或多个节点׃nQ在我之前的文章中,我曾l推荐除非是万不得已Q不要用session failover。就像我文章中提到的Q当p|发生Ӟsession failover功能q不能完全避免错误,而且同时q会Ҏ能和可扩展性带来损失?br id="ose02" />
使用可扩展的session复制机制
Z让用戯得更友好的体验,有些时候可能必M用session failover功能Q这里最重要的在于选择可扩展的复制型品或机制。不同的厂商会提供不同的复制Ҏ - 有些采用数据库持久,有些采用中央集中的状态服务器Q而有些则采用节点间内存复制的方式。最具可扩展性的是成对节点的复制(paired node replication)Q这也是现在大部分厂商采用的ҎQ包括BEA Weblogic、JBoss和IBM WebsphereQSun在Glassfish V2以及以上版本也实C成对节点的复制。最不可取的Ҏ是数据库持久session的方式。在我们实验室中曄试q一个采用数据库持久来实?session复制的项目,试l果表明如果session对象频繁更新的话Q节点在三到四个时就会导致数据库崩溃?br id="l8n39" />
采用collocated部v方式来取代分布式
Java EE技术,其是EJBQ天生就是用来做分布式计的。解耦业务功能和重用q程的组件得多层的应用模型得以行。但对于可扩展性而言Q减分布式的层ơ可能是一个好的选择?br id="jsdn27" />
在我们实验室曄以一个政府的目试q这两种方式在同L服务器数量上的部|?- 一U是分布式的Q一U是collocated方式的,如下图所C:
![]() Figure 4: distributed structure |
![]() Figure 5: collocated structure |
l果表明collocated式的部v方式比分布式的方式更具备可扩展性。假设你应用中的一个方法调用了一堆的EJBQ如果每个EJB的调用都需要load balanceQ那么有可能会因为需要分散到不同的服务器上进行调用导致你的应用崩溃,q样的结果就是,你可能做了很多次无谓的跨服务器的调用。来看更p糕的情况,如果你的Ҏ是需要事务的Q那么这个事务就必须跨越多个服务器,而这对于性能是会产生很大的损害的?br id="b_ta3" />
׃n资源和服?/strong>
对于用于支撑q发h的Java EE集群pȝ而言Q其扩展后的性能取决于对于那些不支持U性扩展的׃n资源的操作。数据库服务器、JNDI树、LDAP服务器以及外部的文gpȝ都有可能被集中的节点共享?br id="u6g97" />
管Java EE规范中ƈ不推荐,但ؓ了实现各U目标,通常都会采用外部的I/O操作。例如,在我们实验室试的应用中有用文gpȝ来保存用户上传的文g的应用,或动态的创徏xml配置文g的应用。在集群内,应用服务器节点必L办法来复制这些文件到其他的节点,但这样做是不利于扩展的。随着来多节点的加入,节点间的文g复制会占用所有的|络带宽和消耗大量的CPU资源。在集群中要辑ֈq样的目标,可以采用数据库来替代外部文gQ或采用SAN作ؓ文g的集中存储,另外一个可选的Ҏ是采用高效的分布式文件系l,例如Hadoop DFS(http://wiki.apache.org/hadoop/)?br id="opr53" />
在集环境中׃n服务很常见,q些服务不会部v到集的每个节点Q而是部v在专门的服务器节点上Q例如分布式的日志服务或旉服务。分布式锁管理器 (DLM)来管理集中的应用对q些׃n服务的同步访问,即在网lg时和pȝ处理p|的情况下Q锁理器也必须正常操作。D例来_在我们的实验室中试的一个ERPpȝqCq样的问题,他们写了自己的DLMpȝQ最l发现当集群中持有锁的节点失败时Q他们的lock system会永远的持有锁?br id="nq3v3" />
分布式缓?/strong>
我所到q的几乎所有的Java EE目都采用了对象~存来提升性能Q同h有流行的应用服务器也都提供了不同U别的缓存来加速应用。但有些~存是ؓ单一q行的环境而设计的Qƈ且只能在单JVM实例中正常的q行。由于有些对象的创徏需要耗费大量的资源,我们需要缓存,因此我们l护对象池来~存对象的实例。如果获取维护缓存较之创建对象而言更划,那么我们提升了pȝ的性能。在集群环境中,每个jvm实例l护着自己的缓存,Z保持集群中所有服务器状态的一_q些~存对象需要进行同步。有些时候这L同步机制有可能会比不采用~存的性能q差Q对于整个集的扩展能力而言Q一个可扩展的分布式~存pȝ是非帔R要的?br id="k9:22" />
如今很多分布式缓存相关的开源java产品已经非常行Q在我们实验室中有如下的一些测试:
Memcached是一个高性能的分布式对象~存pȝQ经常被用于降低数据库loadQ同时提升动态web应用的速度。Memcached的奇妙之处在于它的两阶段hash的方法,它通过一个巨大的hash表来查找key = value对,l它一个keyQ就可以set或get数据了。当q行一ơmemcached查询Ӟ首先客户端将会根据整个服务器的列表来对keyq行 hashQ在扑ֈ一台服务器后,客户端就发送请求,服务器端在接收到h后通过对key再做一ơ内部的hashQ从而查扑ֈ实际的数据项。当处理巨大的系l时Q最大的好处是memcached所具备的良好的水^扩展能力。由于客L做了一层hashingQ这使得增加N多的节点到集变得非常的ҎQƈ不会因ؓ节点的互q造成负蝲的增高,也不会因为多播协议而造成|络的洪水效应?br id="hv3g3" />
实际上Memcachedq不是一ƾjava产品Q但它提供了Java client APIQ这也就意味着如果你需要在Java EE应用中用memcached的话Qƈ不需要做多大的改动就可以从cache中通过get获取|或通过put值放入cache中。?memcached是非常简单的Q不q同时也得注意一些事情避免对扩展性和性能造成损失Q?br id="q60s" />
Terracotta(http://www.terracottatech.com/)是一个企业的、开源的、JVMU别的集解x案。JVMU的集群Ҏ意味着可以支撑企业的Java应用部v部v到多JVM上,而且像是运行在同一个JVM中?Terracotta扩展了JVM的内存模型,各虚拟机上的U程通过集群来与其他虚拟Z的线E进行交?Terracotta extends the Java Memory Model of a single JVM to include a cluster of virtual machines such that threads on one virtual machine can interact with threads on another virtual machine as if they were all on the same virtual machine with an unlimited amount of heap.)?br id="nowt2" />
Figure 6: Terracotta JVM clustering
采用Terracotta来实现集应用的~程方式和编写单机应用基本没有什么差别,Terrocottaq没有特别的提供开发者的APIQTerracotta采用字节码织入的方式Q很多AOP软g开发框架中采用的技术,例如AspectJ和AspectWerkzQ来集方式的代码插入到已有的java语言中?br id="j_.43" />
我猜想Terrocotta是通过某种互连的方式或多播协议的方式来实现服务器和客户端JVM实例的通讯的,可能是这个原因导致了在我们实验室试时的效果Q当过20个节ҎTerracotta扩展的ƈ不是很好。(注:q个试l果仅ؓ在我们实验室的测试结果,你的l果可能会不同。)
我之前说q,单线E的d会成为系l可扩展性的瓉。但有些单线E的工作Q例如处理或生成巨大的数据集Q不仅需要多U程或多q程的运行,q会有扩展到多节点运行的需求。例如,在我们实验室试的一个Java EE目有一个场景是q样的:Ҏ他们站点的日志文件分析URL的访问规则,每周产生的这些日志文仉常会超q?20GBQ当采用单线E的Java应用d析时需要耗费四个时Q客h为采用Hadoop Map-Reduce使其能够水^扩展从而解决了q个问题Q如今这个分析URL讉K规则的程序不仅运行在多进E模式下Q同时还q行的在过10个节点上q行Q而完成所有的工作也只需?分钟了?br id="ob432" />
有很多的框架和工具可以帮助Java EE开发h员来让应用支持水qx展。除了HadoopQ很多MPI的Java实现也可以用来将单线E的d水^的扩展到多个节点上ƈ行运行?br id="g8.y2" />
MapReduce由Google的Jeffrey Dean和Sanjay Ghemawat提出Q是一U用于在大型集群环境下处理巨量数据的分布式编E模型。MapReduce׃个步骤来实现 - MapQ对集合中所有的对象q行操作q基于处理返回一pd的结果,ReduceQ通过多线E、进E或独立pȝq行的从两个或多个Map中整理和获取l果。Map()和Reduce()都是可以q行q行的,不过通常来说没必要在同样的系l同L旉q么来做?br id="sezi3" />
Hadoop是一个开源的、点对点的、纯Java实现的MapReduce。它是一个用于将分布式应用部|到大型廉h集群上运行的Lucene-derived框架Q得C全世界范围开源h士的支持以及q泛的应用,Yahoo的Search Webmap、Amazon EC2/S3服务以及Sun的网格引擎都可运行在Hadoop上?br id="hpul" />
单来_通过使用“Hadoop Map-Reduce”Q?URL讉K规则分析"E序可以首先日志文件分解ؓ多个128M的小文gQ然后由Hadoop这些小文g分配C同的Map()上去执行。Map()会分析分配给它的文件ƈ产生临时的结果,Map()产生的所有的临时l果会被排序q分配给不同的Reduce()QReduce()合ƈ所有的临时l果产生最l的l果Q这些Map和Reduce操作都可以由Hadoop框架控制来ƈ行的q行在集中所有的节点上?br id="pt_l3" />
MapReduce对于很多应用而言都是非常有用的,包括分布式检索、分布式排序、web link-graph reversal、term-vector per host、web讉K日志分析、烦引重建、文档集、机器智能学习、statistical machine translation和其他领域?
MPI
MPI是一U语a无关、用于实现ƈ行运行计机间交互的通讯协议Q目前已l有很多Java版本的MPI标准的实玎ͼmpiJava和MPJ是其中的典型。mpiJava ZJNIl定native的MPI库来实现QMPJ?00%Ujava的MPI标准的实现。mpiJava和MPJ和MPI Fortran和C版本提供的API都基本一_例如它们都对外提供了具备同样Ҏ名和参数的Comm class来实现MPI的信息传递?br id="uch26" />
CCJ是一个类似MPI通讯操作的java库。CCJ提供了barrier、broadcast、scatter?gather、all-gather、reduce和all-reduce操作的支持(但不提供点对点的操作Q例如send、receive和send- receiveQ。在底层的通讯协议斚wQCCJq没有自己实玎ͼ而是采用了Java RMIQ这也就使得CCJ可以用来传递复杂的序列化对象,而不仅仅是MPI中的原始数据cd。进一步看QCCJq可以从一lƈ行的processes中获取到复杂的集合对象,例如实现了CCJ的DividableDataObject接口的集合?br id="j.7e7" />
采用不同的方法来获取高扩展能?/strong>
有很多的书会教我们如何以OO的方式来设计灉|架构的系l,如何来服务透明的被客户端用以便维护,如何采用正常的模式来设计数据库schema以便集成。但有些时候ؓ了获取高扩展性,需要采用一些不同的Ҏ?br id="pa9n3" />
Google设计了自q高可扩展的分布式文gpȝQGFSQ,它ƈ不是ZPOSIX API来实现的Q不qGFS对于用户来说q不完全透明。ؓ了用GFSQ你必须采用GFS的API包。Google也设计了自己的高可扩展的分布式数据库pȝQBigtableQ,但它q不遵@ANSI SQL标准Q而且其中的概念和l构和传l的关系数据库几乎完全不同,但最重要的是GFS和Bigtable能够满Google的存储要求、良好的扩展性要求,q且已经被Google的广泛的作ؓ其存储^台而用?br id="m-gg2" />
传统方式下,我们通过使用更大型的、更快和更贵的机器或企业U的集群数据库(例如RACQ来数据库扩展到多节点q行Q但我有一个我们实验室中测试的social networking的网站采用了不同的方式,q个应用允许用户在网站上创徏profiles、blogsQ和朋友׃n照片和音乐,此应用基于Java EE~写Q运行在Tomcat和Mysql上,但不同于我们实验室中试的其他应用,它只是希望在20多台便宜的PC Server上进行测试,其数据模型结构如下:
Figure 7: Users data partitions
q里比较Ҏ的地方子于不同的用h据(例如profile、blogQ可能会存储在不同的数据库实例上Q例如,用户 00001存储在服务器A上,而用?0001存储在服务器C上,分库的规则以一张元信息的表的方式存储在专门的数据库上。当部v在Tomcat?Java EE应用希望获取或更新用户信息时Q首先它会从q张元信息的表中获取到需要去哪台服务器上获取q个用户Q然后再q到实际的服务器上去执行查询或更新操作?/p>
用户数据分区和这U两步时的动作方式可以带来如下的一些好处:
q个pȝ的架构师q么_“我们已经知道q些~点Qƈ且准备好了应对它Q我们甚臛_备好了应对当元信息表的服务器成ؓ瓉的状况,如果出现那样的状冉|们将会把元信息表再次划分Qƈ创徏Z个更高别的元信息表来指向众多的二元信息表服务器实例?#8220;
关于作?/strong>
我一直ؓ一家互联网性质的实验室工作Q这个实验室采用我们公司最新的大型服务器环境ؓ合作伙伴的品和解决Ҏ免费做性能试Q我工作的部分就是帮助他们在强大的CMT和SMP服务器上q行性能调优?br id="oe9t1" />
q些q来Q我已经Z同的解决Ҏ试了数十种java应用。许多的产品都是Z解决同样的领域问题,因此q些产品的功能基本都是类似的Q但在可扩展性上表现的却非常不同Q其中有些不能扩展到64 CPU的服务器上运行,但可以扩展到20台服务器做集运行,有些则只能运行在不超q? CPU的机器上?br />
造成q些差别的原因在于设计品时的架构愿景,所有的具备良好扩展性的java应用从需求需求阶Dc系l设计阶D以及实现阶D都为可扩展性做了考虑Q所以,你所~写的java应用的可扩展能力完全取决于你的愿景?br id="lafd2" />
可扩展性作为系l的属性之一Q是个很隑֮义的名词Q经怼与性能h。当Ӟ可扩展性和性能是有关系的,它的目的是ؓ了达到高性能。但是衡量可扩展性和性能的方法是不一LQ在q篇文章中,我们采用wikipedia中的定义Q?br id="pn932" />
可扩展性是pȝ、网l或q程的可选属性之一Q它表达的含义是可以以一U优雅的方式来处理不断增长的工作Q或者以一U很明白的方式进行扩充。例如:它可以用来表C系l具备随着资源(典型的有g)的增加提升吞吐量的能力?br id="jlay3" />
垂直扩展的意思是l系l中的单节点增加资源Q典型的是给机器增加CPU或内存,垂直扩展为操作系l和应用模块提供了更多可q的资源,因此它得虚拟化的技术(应该是指在一台机器上q行多个虚拟机)能够q行的更加有效?br id="m4lu2" />
水^扩展的意思是指给pȝ增加更多的节点,例如Z个分布式的Y件系l增加新的机器,一个更清晰的例子是一台web服务器增加ؓ三台。随着计算Zh格的不断降低以及性能的不断提升,以往需要依靠超U计机来进行的高性能计算的应用(例如Q地震分析、生物计等Q现在可以采用这U多个低成本的应用来完成。由上百台普通机器构成的集群可以辑ֈ传统的基于RISC处理器的U学计算机所具备的计能力?br id="cq3n3" />
q篇文章的第一部分来讨Z垂直扩展Java应用?br id="yfvm2" />
如何让Java EE应用垂直扩展
很多的Y件设计h员和开发h员都认ؓ功能是品中最重要的因素,而性能和可扩展性是附加的特性和功能完成后才做的工作。他们中大部分h认ؓ可以借助昂贵的硬件来~小性能问题?br id="yfvm11" />
但有时候他们是错的Q上个月Q我们实验室中有一个紧急的目Q合作伙伴提供的产品在他们客h供的CPU的机器上试未达到性能的要求,因此合作伙伴希望在更多CPUQ? CPUQ的机器上测试他们的产品Q但l果却是? CPU的机器上性能反而比4 CPU的机器更差?br id="z9tj3" />
Z么会q样呢?首先Q如果你的系l是多进E或多线E的Qƈ且已l用了CPU的资源,那么在这U情况下增加CPU通常能让应用很好的得到扩展?br id="f.yh2" />
Zjava技术的应用可以很简单的使用U程QJava语言不仅可以用来支持~写多线E的应用Q同时JVM本n在对java应用的执行管理和内存理上采用的也是多线E的方式Q因此通常来说Java应用在多CPU的机器上可以q行的更好,例如Bea weblogic、IBM Websphere、开源的Glassfish和Tomcat{应用服务器Q运行在Java EE应用服务器中的应用可以立MCMT和SMP技术中获取到好处?br id="a97y3" />
但在我的实验室中Q我发现很多的品ƈ不能充分的用CPUQ有些应用在8 CPU的服务器上只能用到不到20%的CPUQ像q类应用即增加CPU也提升不了多的?br id="s.wx3" />
热锁(Hot Lock)是可扩展性的关键障碍
在JavaE序中,用来协调U程的最重要的工具就?synchronizedq个关键字了。由于java所采用的规则,包括~存h和失效,Java语言中的synchronized块通常都会其他q_提供的类似的机制更加的昂c即使程序只是一个运行在单处理器上的单线E程序,一个synchronized的方法调用也会比非同步的Ҏ调用慢?br id="jrop2" />
要检查问题是否ؓ采用synchronized关键字造成的,只需要像JVMq程发送一个QUIT指oQ译者注Q在linux上也可以用kill -3 PID的方式)来获取线E堆栈信息。如果你看到cM下面U程堆栈的信息,那么意味着你的pȝ出现了热锁的问题Q?br id="se053" />
synchronized 关键字强制执行器串行的执行synchronized中的动作。如果很多线E竞争同L同步对象Q那么只有一个线E能够执行同步块Q而其他的U程只能进入blocked状态了Q如果此时没有其他需要执行的U程Q那么处理器p入空闲状态了Q在q种情况下,增加CPU也带来不了多性能提升?br id="o0a-2" />
热锁可能会导致更多线E的切换和系l的调用。当多个U程竞争同一个monitorӞJVM必须l护一个竞争此monitor的线E队列(同样Q这个队列也必须同步Q,q也意味着更多的时间需要花费在JVM或OS的代码执行上Q而更的旉是用在你的程序上的?/p>
要避免热锁现象,以下的徏议能带来一些帮助:
可能的~短同步?/strong>
当你线E中持有锁的旉量~短后,其他U程竞争锁的旉也就变得更短。因此当你需要采用同步块来操作共享的变量Ӟ应该线E安全的代码攑֜同步块的外面Q来看以下代码的例子Q?/p>
Code list 1:
上面的代码片D|Z当更?schema"变量时保护这个共享的变量。但获取attribute值部分的代码是线E安全的。因此我们可以将q部分移臛_步块的外面,让同步块变得更短一些:
Code list 2:
减小锁的_度
当你使用"synchronized"Ӟ有两U粒度可选择Q?Ҏ??块锁"。如果你?synchronized"攑֜Ҏ上,那么也就意味着锁定?this"对象?/p>
Code list 3:
ҎCode list 2中的代码Q这D代码就昑־更糟p些了,因ؓ当调?updateSchema"ҎӞ它锁定了整个
对象Qؓ了获得更好的_度控制Q应该仅仅锁?schema"变量来替代锁定整个对象,q样其他不同的方法就?br /> 以保持ƈ行执行了?br />
避免在staticҎ上加?/strong>
最p糕的状冉|在staticҎ上加"synchronized"Q这样会造成锁定q个class的所有实例对象?br />
当用Java 2D来ؓ报表生成字体对象Ӟ开发h员放了一个native的static锁在"initialize"Ҏ上,不过q是sun JDK 1.4中才会出现的Q在JDK 5.0中,q个static lock消׃?br id="q2z33" />
在Java SE 5.0中用lock free的数据结?/strong>
在Java中,"synchronized"关键字是一个较单、ƈ且相Ҏ说比较好用的协作机制Q不q同时对于管理一个简单的操作Q例如增加统计值或更新一个|来说显得比较重量了,像以下的代码:
Code list 4:
以上的代码只是用来锁定非常简单的操作Q?synchronized"块也是非常的短。但是锁是非帔R量Q当锁被其他U程持有ӞU程会去频繁试获取锁)的,吞吐量会下降Qƈ且同步锁的竞争也是很昂贵的?br id="ns9d3" />
q运的是Q在Java SE 5.0或以上版本,你可以在不用native代码的情况下使用gU同步语义的wait-free、lock-free的算法。几乎所有现代的处理器都h和防止其他处理器ƈ发修改变量的基础设施。这些基设施UCؓ比较q交换,或CAS?br id="kd-s2" />
一个CAS操作包含三个参数 -- 一个内存地址Q期待的旧的g及新的倹{?如果内存地址上的值和所期待的旧的值是同一个的话,处理器将此地址的值更Cؓ新的|否则它就什么都不做Q同时它会返回CAS操作前内存地址上的倹{一个用CAS来实现同步的例子如下Q?/p>
Code list 5:
首先Q我们从地址上读取一个|然后执行几步操作来生新的|例子中只是做?的操作)Q最后用CAS方式来将地址中的旧值改变ؓ新倹{如果在旉片段内地址上的值未改变Q那么CAS操作成功。如果另外的U程同时修改了地址上的|那么CAS操作失败,但会到q个操作p|Qƈ在while循环中进行重试。CAS最好的原因在于它是gU别的实现ƈ且非常轻量Q如?00个线E同时执行这个increment()ҎQ最p糕的情冉|?incrementҎ执行完毕前每个线E最多尝?9ơ?br id="e8l:2" />
在Java SE 5.0和以上版本的java.util.concurrent.atomic包中提供了在单个变量上lock-free和线E安全操作支持的cR这些原子变量的c都提供了比较和交换的原语,它基于各U^C可用的最后的native的方式实玎ͼq个包内提供了九U原子变量,包括QAtomicIntegerQAtomicLongQAtomicReferenceQAtomicBooleanQarray forms of atomic integer、long、referenceQ和atomic marked reference和stamped referencecR?br id="hh.52" />
使用atomic包非常容易,重写上面code list 5的代码片D:
Code list 6:
几乎java.util.concurrent包中所有的c都直接或间接的采用了原子变量来替代synchronized。像
ConcurrentLinkedQueue采用了原子变量来直接实现wait-free法Q而像ConcurrentHashMap则采?br /> ReentrantLock来实现必要的锁,而ReentrantLock则是采用原子变量来维护所有等待锁的线E队列?/pre>在我们实验室中一个最成功的关于lock free法的案例发生在一个金融系l中Q当?Vector"数据l构替换?ConcurrentHashMap"后,在我们的CMT机器Q?核)性能提升了超q?倍?br id="gni13" />
竞争条g也会D可扩展性出现问?/strong>
太多?synchronized"关键字会D可扩展性出现问题。但在某些场合,~少"synchronized"也会Dpȝ无法垂直扩展。缺?synchronized"会生竞争场景,在这U场景下允许两个U程同时修改׃n的资源,q有可能会造成破坏׃n数据Qؓ什么我说它会导致可扩展性出现问题呢Q?br id="avul2" />
来看一个实际的例子。这是一个制作业的ERPpȝQ当在我们最新的一台CMT服务器(2CPU?6核?28芯)上进行性能试Ӟ我们发现CPU的用率过90%Q这非常让h惊讶Q因为很有应用能够在这ƾ机器上扩展的这么好。但我们仅仅兴奋?分钟Q之后我们发现^均响应时间非常的慢,同时吞吐量也降到不可思议的低。那么这些CPU都在q嘛呢?它们不是在忙吗,那么它们到底在忙些什么呢Q通过OS的跟t工P我们发现几乎所有的CPU都在q同一件事-- "HashMap.get()"Q看h所有的CPU都进入了d@环,之后我们在不同数量的CPU的服务器上再试了这个应用,l果表明Q服务器拥有多CPUQ那么生死循环的概率就会越高?br id="up:s2" />
产生q个d@环的Ҏ在于对一个未保护的共享变?-- 一?HashMap"数据l构的操作。当在所有操作的Ҏ上加?synchronized"后,一切恢复了正常。检?HashMap"(Java SE 5.0)的源码,我们发现有潜在的破坏其内部结构最l造成d@环的可能。在下面的代码中Q如果我们得HashMap中的entriesq入循环Q那?e.next()"永远都不会ؓnull?/p>
Code list 7:
public V get(Object key) {
if (key == null) return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}不仅get()Ҏ会这Pput()以及其他对外暴露的方法都会有q个风险Q这jvm的bug吗?应该说不是的Q这个现象很早以前就报告出来了(详细见:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6423457Q。Sun的工E师q不认ؓq是bugQ而是在这L场景下应采用"ConcurrentHashMap"Q在构徏可扩展的pȝ时应这点纳入规范中?br id="vgbz3" />
非阻?IO vs. dIO
Java 1.4中引入的java.nio包,允许开发h员在q行数据处理时获取更好的性能q提供更好的扩展性。NIO提供的非dIO操作允许java应用像其他底层语aQ例如cQ一h作IO。目前已l有很多NIO的框Ӟ例如Apache的Mina、Sun的GrizzlyQ了被广泛的使用在很多的目和品中?br id="z.kv6" />
在最q的5个月内,我们实验室有两个Java EE目试Ҏ了基于传l的dI/O构徏的服务器和非dI/O构徏的服务器上的性能。他们选择了Tomcat 5作ؓZdI/O的服务器QGlassfish作ؓZ非阻塞I/O的服务器?br id="s5ed3" />
首先Q他们测试了一些简单的JSP面和servletsQ得到如下结果:Q在一? CPU的服务器上)
Concurrent Users
|
Average Response Time (ms)
|
|
Tomcat
|
Glassfish
|
|
5
|
30
|
138
|
15
|
35
|
142
|
30
|
37
|
142
|
50
|
41
|
151
|
100
|
65
|
155
|
当在更多的场景进行测试后Q随着NIO的能力逐步的展现出来,他们改变了观点,他们做了以下的测试:
1、比单的JSP、servlet更ؓ复杂的场景,包括EJB、数据库、文件IO、JMS和事务;
2、模拟更多的q发用户Q从1000?0000Q?/p>
3、在不同的硬件环境上q行试Q从2 CPU? CPU?6 CPU?/p>
以下的图为在4 CPU服务器上的测试结果:
|
Figure 1: Throughput in a 4CPU server
传统的阻塞I/O为每个请求分配一个工作线E,q个工作U程负责h的整个过E的处理Q包括从|络dh数据、解析参数、计或调用其他的业务逻辑、编码结果ƈ其q回l请求者,然后q个U程返回到U程池中供其他线E复用。Tomcat 5采用的这U方式在应对完美的网l环境、简单的逻辑以及量的ƈ发用h是非帔R效的?br id="cm9u3" />
但如果请求包括了复杂的逻辑、或需要和外部的系l(例如文gpȝ、数据库或消息服务器Q进行交互时Q工作线E在其处理的大部分时间都会处于等待同步的调用或网l传输返回的状态中Q这个阻塞的U程会被h持有直到h处理完毕Q但操作pȝ需要暂停线E来保证CPU能够处理其他的请求,如果客户端和服务器端的网l状况不太好的话Q网l的延时会导致线E被d更长旉Q在更糟的状况下Q当需要keep-alive的话Q当前的工作U程会在h处理完毕后阻塞很长一D|_在这L情况下,Z更好的用CPUQ就必须增加更多的工作线E了?br id="owzc3" />
Tomcat采用了一个线E池Q每个请求都会被U程池中一个空闲的U程q行处理?maxThreads"表示Tomcat 能创建的处理h的最大线E数。如果我们把"maxThreads"讄的太的话,׃能充分的使用CPU了,更ؓ重要的是Q随着q发用户的增长,会有很多h被服务器抛弃和拒l。在此次试中,我们?maxThreads"讄Z1000Q这对于Tomcat来说有些太大了)Q在q样的设|下Q当q发用户增长到较高数量时QTomcat会创建很多的U程。大量的JavaU程会导致JVM和OS忙于执行和维护这些线E,而不是执行业务逻辑处理Q同Ӟ太多的线E也会消耗更多的JVM heap内存Q每个线E堆栈需要占用一些内存)Qƈ且会D更ؓ频繁的gc?br id="hzd92" />
Glassfish不需要这么多的线E,在非dIO中,一个工作线Eƈ不会l定C个特定的h上,如果h被某些原因所dQ那么这个线E将被其他的h复用。在q样的方式下QGlassfish可以用几十个工作U程来处理几千的q发用户。通过限制U程资源Q非dIO拥有了更好的可扩展性,q也是Tomcat 6采用非阻塞IO的原因了?br id="crca2" />
|
Figure 2: scalability test result
单线EQ务问?br id="dh7x" />
几个月前我们实验室测试了一个基于Java EE的ERPpȝQ它其中的一个测试场景是Z产生非常复杂的分析报告,我们在不同的服务器上试了这个应用场景,发现竟然是在最便宜的AMD PC服务器上拥有最好的性能。这台AMD的服务器只有两个2.8HZ的CPU以及4G的内存,但它的性能竟然过了昂늚拥有8 CPU?2G内存的SPARC服务器?br id="cc-t2" />
原因在于这个场景是个单U程的Q务,它同时只能被一个用戯行(q发的多用户执行在这个案例中毫无意义Q,因此当运行时它只使用了一个CPUQ这Ld是没法扩展到多个处理器的Q在大多数时候,q种场景下的性能仅取决于CPU的运行速度?br id="d6vc2" />
q行是解册个问题的Ҏ。ؓ了让一个单U程的Q务ƈ行执行,你需要按序扑ևq个操作的过E中从某U程度上来讲不依赖的操作Q然后采用多U程从而实现ƈ行。在上面的案例中Q客户重新定义了"分析报告产生"的Q务,改ؓ先生成月度报告,之后Z产生的这?2个月的月度报告来生成分析报告Q由于最l用户ƈ不需?#8220;月度报告”Q因此这?#8220;月度报告”只是临时产生的结果,?月度报告"是可以ƈ行生成的Q然后用于快速的产生最后的分析报告Q在q样的方式下Q这个应用场景可以很好的扩展? CPU的SPARC服务器上q行Qƈ且在性能上比在AMD Server?0%多?br id="bjdu3" />
重新调整架构和重写代码的解决Ҏ是一个耗时q且Ҏ出现错误的工作。在我们实验室中的一个项目中采用了JOMP来ؓ其单U程的Q务获得ƈ行性。JOMP是一个基于线E的SMPq行~程的Java API。就像OpenMPQJOMP也是Ҏ~译指示来插入ƈ行运行的代码片段到常规的E序中。在JavaE序中,JOMP 通过//ompq样的指C方式来表示需要ƈ行运行的部分。JOMPE序通过q行一个预~译器来处理q些//omp的指Cƈ生成最l的java代码Q这?java代码再被正常的编译和执行。JOMP支持OpenMP的大部分Ҏ,包括׃n的ƈ行@环和q行片段Q共享变量,thread local变量以及reduction变量。以下的代码为JOMPE序的示例:
Code list 8:
像大部分的q行~译器,JOMP也是x于loop-level和集合的q行q算Q研I如何同时执行不同的q代。ؓ了ƈ行化Q两个P代之间不能生Q何的数据依赖Q这也就是说Q不能依赖于其他M一个执行后产生的计结果。要~写一个JOMPE序q不是容易的事。首先,你必ȝl用OpenMP的指C,同时q得熟悉JVM对于q些指示的内存模型映,最后你需要知道在你的业务逻辑代码的正的地方攄正确的指C?br id="f0_v2" />
另外一个选择是采用Parallel Java。Parallel JavaQ就像JOMP一P也支持OpenMP的大部分Ҏ;但又不同于JOMPQPJ的ƈ行结构部分是通过在代码中调用PJ的类来实玎ͼ而不是通过插入预编译的指示Q因此,"Parallel Java"不需要另外的预编译过E。Parallel Java不仅对于在多CPU上ƈ行有效,对于多节点的扩展能力上也同样有效。以下的代码?Parallel Java"E序的示例:
Code list 9:
扩展使用更多的内?/strong>
内存是应用的重要资源。够的内存对于M应用而言都是关键的,其是数据库pȝ和其他I/O操作频繁的系l。更多的内存意味着更大的共享内存空间以及更大的数据~冲Q这也就使得应用能够更多的从内存中读取数据而不是缓慢的盘中读取?br id="h_:l6" />
Java gc程序员从繁琐的内存分配和回收中解脱了出来,从而得程序员能够更加高效的编写代码。但gc不好的地方在于当gcq行Ӟ几乎所有工作的U程都会被挂赗另外,在gc环境下,E序员缺调度CPU来回攉些不再用的对象的控制能力。对于那些几乎实时的pȝ而言Q例如电信系l和股票交易pȝQ这Ugq和~少控制的现象是很大的风险?br id="h_:l12" />
回到Java应用在予更多的内存时是否可以扩展的问题上,{案是有些时候是的。太的内存会导致gc频繁的执行,_的内存则保证JVMp更多的时间来执行业务逻辑Q而不是进行gc?br id="uxk62" />
但它q不一定是q样的,在我们实验室中出现的真实例子是一个构建在64位JVM上的电信pȝ。?4位JVMQ应用可以突?2位JVM?GB内存的限Ӟ试时用的是一? CPU/16G内存的服务器Q其?2GB的内存分配给了java应用使用Qؓ了提高性能Q他们在初始化时q存了过3,000,000个的对象到内存中Q以免在q行时创建如此多的对象。这个品在W一个小时的试中运行的非常快,但突Ӟpȝ差不多停止运行了30多分钟,l过,发现是因为gcD了系l停止了半个时?br id="u-.z2" />
gc是从那些不再被引用的对象回收内存的过E。不被引用的对象是指应用中不再用的对象Q因为所有对于这些对象的引用都已l不在应用的范围中了。如果一堆巨大的zd的对象存在在内存中(像3,000,000个缓存的对象Q,gc需要花费很长的旉来检查这些对象,q就是ؓ什么系l停止了如此长乃至不可接受的旉?br id="qqit2" />
在我们实验室中测试过的以内存Z心的Java应用中,我们发现具备有如下特征:
q样的应用是不好做扩展的Q当q发的用h增长Ӟq些应用所使用的内存也会大q度的增ѝ如果大量的zd对象无法被及时的回收QJVM会在gc上消耗很长的旉Q另外,如果i予了太大的内存Q在64位JVM上)Q在q行了相对较长的旉后,jvm会花费相当长的一D|间在 gc上,因此l论是如果给jvm分配了太多的内存的话Qjava应用不可扩展。在大部分场合下Q给jvm分配3G内存(通过"-Xmx"属?是?(在windows和linux中,32位的pȝ最多只能分?G的内?的。如果你拥有更多的内存,请将q些内存分配l其他的应用Q或者就它留给OS 使用Q许多OS都会使用I闲的内存来作ؓ数据的缓冲和~存来提升IO性能。实时JVM(JSR001)可以让开发h员来控制内存的回Ӟ应用Z此特性可以告诉JVMQ?#8220;q个巨大的内存空间是我的~存Q我自己来理它,请不要自动对它进行回?#8221;Q这个功能特性得Java应用也能够扩展来支持大量的内存资源,希望JVM的提供者们能将q个Ҏ在不久的将来带入到免费的JVM版本中?/p>
Z扩展q些以内存ؓ中心的java应用Q你需要多个jvm实例或者多台机器节炏V?br id="k9em2" />
其他垂直扩展的问?/strong>
有些Java EE应用的扩展性问题ƈ不在于其本nQ有些时候外部系l的限制会成为系l扩展能力的瓉Q这些瓶颈可能包括:
q些不仅仅是Java EE应用的问题,对于所有^台的所有系l而言同样如此。ؓ了解册些问题,需要从pȝ的各个层面来从数据库理员、系l工E师和网l分析h员处得到帮助?/p>
q篇文章的第二个部分来探讨水^扩展的问题?br id="yas54" />
?Hudson ?/span>
Hudson 是一U革命性的开放源?CI 服务器,它从以前?CI 服务器吸取了许多l验教训。Hudson 最吸引人的Ҏ之一是它很容易配|:很难扑ֈ更容易设|的 CI 服务器,也很难找到开即用特性如此丰富的 CI 服务器。Hudson Ҏ使用的第二个原因是它h强大的插件框Ӟ所以很ҎdҎ。例如,一?Hudson 插g可以随时间的推移跟踪 FindBugs 和代码覆盖。它q可以报告测试结果的势Q来?JUnit ?TestNGQ以及构建结果和对应的执行时间?
Hudson 需要运?Java 5。如果需要?Hudson 附带的嵌入式容器QWinstoneQ之外的其他容器Q那么只需使用一U?Servlet 2.4 容器。对于大多数情况QWinstone p够了?br />
?Hudson使用
CI q程的最后一个方面是 CI 服务器本w。CI 服务器在整个开发过E中的主要作用是控制者:当服务器在代码存储库中探到修改Ӟ它将q行构徏的Q务委托给构徏q程本n。如果构建失败了Q那?CI 服务器将通知相关斚wQ然后l监视存储库。它的角色看h是被动的Q但是,它是快速反映问题的关键?/span>
使用 Hudson 的主要好处之一是它的设|很单。在最单的情况下,Hudson 只需要两个步骤:
java -jar hudson.war
?q样可以了。因Z载的是一?WAR 文gQ所以如果愿意,可以它部v?Tomcat ?JBoss {容器中。这完全由您自己军_。当ӞHudson 假设在安装它的机器上q行着 Java 5Q而且如果定义?JAVA_HOME
环境变量QHudson ׃使用它。(正如前面提到的,Hudson 需?Java 5。)
在安装ƈq行 Hudson 之后Q将 WAR 文g部v?servlet 容器或从命o行执?java -jar hudson.war
Q,启动览器ƈ讉K默认安装位置。如果通过命o行运?Hudson 而且您在本地机器上,那么可以讉K http://localhost:8080/
?/span>
如果讉K Hudson 主页的本地实例ƈ单击左上角的 Manage Hudson 链接Q应该会看到?3 所C的可配|选项列表?/strong>
?3. 配置 Hudson 非常Ҏ参数说明:
system.message 填写一些说明信?br />
Quiet period:hudson定时构徏工程的时?U?
:讄hudson登陆的规?默认为匿名登?
TCP port for JNLP slave agents:不了解JNLP不敢胡写M是三种方式:固定(fixed) 随机(Radom) 不?disabled),使用固定时可以填入JNLP信息
q可以配|服务器的其他几个方面,比如?Hudson 提供一个电子邮件服务器的位|,以便在构建失败时接收电子邮g。根据您的组l设|电子邮件的方式Q可能需要让pȝ理员帮助设|这个特性。设|电子邮件ƈ不是必需的;Hudson q支持以 RSS 作ؓ通知机制Q对于某些h来说Q这U方式比电子邮g更好。究竟选择哪些通知机制完全取决于您。(注意Q这里说的是 “哪些”Q也是_可以同时使用多种通知机制Q)
既然 Hudson 已经能够?SCM 存储库通信了,p配置目了。这个示例所用的目UCؓ solar-ci
。在 Hudson 主页上单d上角?New Job 链接。这时会看到?5 所C的屏幕Q?/strong>
该页面可以我们通过hudson来管?/span>cvs里的一个对应的工程
Project name:工程名称
Description:描述信息
Discard build:如果选择此项可以讄build记录保存的天?/span>,或?/span>build记录保存的数?/span>,或者只保存最新的build记录,一般不需填写
Advance project options:可以讄hudson定时?/span>cvs工程的时间间?/span>,q可以指?/span>cvs工程check out到本地的工程路径,一般不需要填?/span>
Source code management:我们选择cvs出C下参?/span>:
Cvsroot:写cvs登陆字符?/span>,格式(:protocol:user:password@host:path),例如: :pserver:cvsadmin:1@127.0.0.1:2401:/CVSNT/Repository,使用cvs必填Modules:填写cvs仓库下的具体工程?span lang="EN-US">, 使用cvs必填
选择subversion可以q行相应?span lang="EN-US">subversion讄
Build trigger可以讄hudson自动执行的一些动?span lang="EN-US">,build after others projects are built指定hudson构徏完成后需要l构建的工程?span lang="EN-US">
Build periodically Ҏhudson定义的语法规则来讑֮自动构徏工程的时间间?span lang="EN-US">
讄一些构建完成后的动?span lang="EN-US">,如放邮g,打包,产生试报告,产生java doc {?span lang="EN-US">.
点击ok保存讄
成功的大型企业需要其 IT 部门通过跟上技术发展来保持高水准的竞争力。这通常需要代价很高的l常性投资以l护当前?IT 投资和增L的投资。然而,中小型企业通常只有有限的预来设法C化其 IT 基础设施和资产。通常可以注意刎ͼ中小型企业只有在充分利用当前 IT 投资以后才会考虑重大的升U。他们每隔几q进行一ơ较大规模的C化投资,而不是连l地q行投资?
“中小型企?#8221;Qsmall and medium businessQSMBQ这个术语非怸观ƈ取决于若q因素,例如q度营业额、员工数量、业务的地理分布{等。就本文而言Q我们的虚构公司 Mod Communications , Inc.Q以下也UCؓ“该公?#8221;Q是一家ؓ中西部若q个城区的家庭客户和当地企业提供高?Internet 接入、有U电视、本地和镉K电话以及无UK信服务的电信服务提供商。该公司是需要现代化?IT pȝ的中型企业的代表。该公司拥有 200 名员工,已有 20 q的l营历史Q分支机构不过 10 个,q拥有大U?75 ?IT 人员l护其当前的 IT 解决Ҏ?/p>
面对新的竞争Q他们感觉到了ؓ当前客户l持较高服务U别的压力。该公司希望着手进行遗留系l{换活动。该公司准备{换活动做出重大投资,q正在寻求现代化路线图规划方面的帮助。本文是?IT N、架构师和解x案开发h员准备的Qƈ解释了如何分析该公司的当前现状、组l动力和挑战Qƈ提供了一l?IT 转换zd。本文还演示了一些可在该解决Ҏ开发过E中提供帮助?IBM 产品和服务?/p>
Mod Communications Inc. 的大多数应用E序都是客户信息控制pȝQCustomer Information Control SystemQCICS®Q应用程序,q些应用E序使用 COBOL ~写q运行在 IBM System z™ pd中的 IBM 中端大型机系l上。虽然这些应用程序l尽最大可能地提供核心业务服务Q但是它们非常庞大、独立ƈ且难于修攏V替换或从头重新构徏q些应用E序会对当前业务程产生破坏性的影响Qƈ需要收集在q去 15 q里加入到系l中的业务智能和规则。采用某个基于面向服务的体系l构原则的渐q式遗留pȝ转换q程Q是有选择地替换该公司的应用程序组合的更加l济合算和风险更低的Ҏ。此Ҏ的一个示例是使用 Java EE (Java™ Enterprise Edition) 来开发将在诸?IBM 推出?Websphere® Application Server {应用程序服务器上运行的应用E序。新的应用程序将在可能和适当的Q何场合重用现有的功能。在构徏和部|新lgӞ其用范围超出目前应用程序的部分lg公开为服务,以便在以后的开发工作中重用?/p>
下面几个部分解?IT 架构师或N如何执行数据攉、分析和zdQƈ遗留系l{换过E告知公司的重要高层理人员。下面将从数据收集期间的各个步骤、分析阶D得出的各种输出、所定的徏议备选解x案和针对转换规划的指C等斚w对相x动进行描q?/p>
数据攉的重点在于获得关于业务活动、所使用?IT 技术和 IT 投资{事的当前状态的信息。然后可以分析该数据以确定{换机会。以下步骤将准备q执行有效的数据攉工作Q?/p>
务必要了解公司的l织l构图,以便定重要的团队成员和权力人物。Mod Communications, Inc. 的组l结构图表明Q总裁和首席运营官QChief Operating OfficerQCOOQ以及执行副总裁QExecutive Vice President Q将负责监督重要的业务和技术活动以及投资。对于日常职能和zdQ该l织拥有诸如“操作l?#8221;?#8220;业务服务l?#8221;?#8220;财务服务l?#8221;?#8220;通用开发组”{小l。其中每个小l都h业务和技术h员。这些小l的负责人将向执行副总裁报告Qƈ且是主要的业务和技术相兛_{的权力人物?/p>
此步骤将为准备用于数据收集的详细问题集奠定基。v初,可以从与高人员q行的讨Z获得有关公司l营的粗略概c在非正式的气氛中提出有兛_司背景、公司发展、公司所属行业、优ѝ弱炏V新Z、察觉到的竞争威胁、所获奖以及类g题的诱导性问题?/p>
?Mod Communications, Inc. q行的有兌{换活动的M目标的讨E中Q一名高U员工提到该公司作ؓ中小型企业区D中的最佛_工工作场所之一而感到自豪。大多数员工都已lؓ该公司工作了 15 q以上。另一位高层管理h员提到实现面向服务的体系l构在公司日E上处于优先位置。该信息可以在分析阶D中提供重要的输入,以评估关于组l更改和准备情况的可能徏议所h的媄响?/p>
此类问卷上的问题应该跨越q泛的主题,例如业务目标、当前流E评估、应用程序组合评估、企业数据体pȝ构、基设施和操作体pȝ构、面向服务的体系l构Q以及治理。以下问题类g一个样本集?/p>
来自 Mod Communications, Inc. 的高Uh员群{群力,一起合作回{上q问题?/p>
步骤 D. 计划安排与重要客L团队成员的后l访?/span>
从问L案中Q确定进一步的信息需求领域,q计划安排与重要人员的后l访谈。用组l结构图来确定要访谈的其他h员。完成后l访谈时Q数据收集阶D差不多完成了。随后的解释说明可以通过电子邮g或电话来获得?/p>
对于 Mod Communications, Inc.Q将准备一个关于访谈成果的报告。该报告提供了公?IT 环境和基设施、IT l织、主要角色和职责的当前状态摘要、应用程序组合概q、系l和功能摘要Q以及当前治理、未来三至五q的业务q景和目标的要概q。这可用作将来的所有工作的参考?/p>
在数据分析过E中Q研I收集到的相兌料和文信息Q以分析各种备选解x案,从而提供徏议。按以下几个斚w对信息进行组l:
对于 Mod Communications, Inc.Q以下是重要的业务远景和目标Q?/p>
Z与团队成员进行的有关该公怋用的当前程和实늚详细讨论Q以下是重要的难点和问题场景Q?/p>
对于 Mod Communications, Inc.Q解x案徏议需要考虑的各U约束如下:
该公司的应用E序l合分析提供了以下信息:
该公怸直?IBM Host Access Transformation Services (HATS) 来将某些应用E序从已有基于字W的屏幕界面转换?Web 用户界面。这使该公司可以快速将现有的基于字W的屏幕界面转换为网和表单Q从而将 Web 通道用于光留应用程序。该公司应该通过创徏Z最l用戯入、易用性、导航和上下文内容呈现的新用L面来Ҏq行改进?/p>
下一步是为客户交付一l解x案徏议?/p>
Z对信息的分析Qؓ重要?Mod Communications, Inc. 高层理人员准备一个解x案徏议,以从资金和项目决{方面说明后l步骤?/p>
核心是让公司在保留其当前遗留应用E序l合的h值的同时Q逐渐地迁Ud可促q松散耦合的体pȝ构的新技术。一个徏议是采用 Java Enterprise Edition (Java EE) 作ؓq行遗留pȝ转换的合适应用程序技术。Java EE Ҏ使公司可以开发能够提供出色的囑Ş和多通道用户界面的应用程序,同时qؓ面向服务的体pȝ构做好定位。这D对各U方法进行分析以实现 Java EE 环境。这些方法如下:
a) 替换Q?/strong>诸如服务订单管理、问题报告和理及计费系l等当前核心应用E序替换为商业化现成Qcommercial off-the-shelfQCOTSQ应用程序。然后自定义和配|该应用E序和界面。这是实现{换的快速方法,但它在客h受、对现有业务程和功能的影响、组l变更和培训需求方面引入了风险?/p>
b) 重新~写Q?/strong>使用 Java EE Ҏ重新~写应用E序。优先重新编写将l历转换的应用程序。对q些应用E序执行ZҎ的完整Y件生命周期开发,包括需求分析、设计以及开发和试。已知当前应用程序的数据库层l构非常良好和高效。在可能的情况下Q新lg可以重用数据库层的功能? c) 大规模{换然后客户化定制Q?/strong>q是选项 b) 的一U变化Ş式。在此情况下Q将使用自动化的工具执行所有应用程序到 Java EE lg的大规模转换。然后修Ҏ得到的组件以适合需求? d) 渐进地{换到目标q_lgQ?/strong>使用Z Java EE 的体pȝ构来构徏q渡环境。从当前遗留pȝ中公开?#8220;q后”模块提供实现。渐q地在目标^C~写代码以取代对遗留模块的依赖? e) 使用W?4 代语aQ?th Generation LanguageQ?GLQ方法渐q地转换Q?/strong>在此情况下,用某U?4GL 语言来定义应用程序。用工具将 4GL l构自动转换?Jave EE lgQ然后将后者部|在目标q_上。例如,此方法可以?IBM 企业生成语言QEnterprise Generation LanguageQEGLQ来实现Qƈ且很适合于非常精通诸?COBOL {程序语a的程序员Q他们将不必学习诸如 Java {面向对象的语言?/p>
从诸如成本、工作量、时间和复杂性等斚w分析上述Q然后按照下面图 1 所C的方式对这些徏议进行归c:每个参数都具有一个优先名称—?#8220;?(H)”?#8220;?(M)”?#8220;?(L)”?/p>
下面是一些补充徏议: 提供一l在C化期间优化内部操作的Q以便ؓ当前人员提供更多参与Z。这些徏议包括: h意,q些会因情况而异Qƈ且应该基于与某个情Ş有关的相关信息。上q案例研I只是一个用作指导原则的CZ?/p>
Z所选的Qؓ执行团队草拟l的转换计划。这包括短期Q一至两q_、中期(两至三年Q和长期Q五q_的项目计划。创建活动(目Q、活动的业务价倹{持l时间、大致成本和资源需求的摘要。这有助于推动资金分配决{和成果?/p>
转换规划期间的重要考虑事项之一涉及到硬件或遗留q_的现代化。在q一点上Q评估重用可能性也是最有利的。例如,客户拥有一?System z pd中的 IBM 中端大型机系l。该pȝ的功能之一是能够在q行 AIX® ?WebSphere Application Server 的单独分Zq行 Java 工作负蝲。该pȝ的此功能可用于实现重用,q且是确定投资需求时的一个重要考虑事项。请参见参考资?/a>部分以获得指向更多信息的链接?/p>
本文提供了深入的见解Q说明了如何Z型企业的主要高层管理h员提供遗留系l{换和C化活动的和指对{本文介l了如何通过执行数据攉、分析和步骤Qƈ提供转换规划信息以支持资金分配决{,从而有条不紊地完成该Q务?/p>
?1. 对各U备选解x案方法徏议的分析
Firebug ?Mozilla Firefox 览器的开源扩展,提供了很多工P可以监视、编辑和调试M Web 站点的联样式表QCSSQ、HTML、文档对象模型(DOMQ和 JavaScript。Firebug 包括一?JavaScript 控制台、一个日志记?API 以及一U有用的|络监视器。借助 FirebugQ可以很L地调试和优化 Web ?Ajax 应用E序?/p>
本文帮助您熟悉所如下?Firebug Ҏ:
![]() ![]() |
使用 FirefoxQ?a cmimpressionsent="1">下蝲 Firebug。通过单击面右侧的橙色按?Install Firebug 安装此扩展?
Firefox 安装了此扩展后,重启览器。要使用 FirebugQ?
本文使用了第一U方法在相同的浏览器H口中打开 FirebugQ如?1 所C:
安装后,Firebug 是禁用的。单?Enable Firebug 启用它,如图 2 所C:
本文的后面的内容讨?Firebug 的特性?
![]() ![]() |
HTML ?CSS 工具包括QHTML 查和~辑、CSS ~辑?CSS 可视化?
可以使用 HTML 查特性在源代码中定位可视 HTML?/p>
?4 l出?Firebug ~辑H口以及览器窗口中已编辑的文本?#8220;Editing with Firebug” 已经代替了原先的 Ajax 标题?/p>
?4. ~辑 HTML
在检查元素时Q将会看?Firebug H口内的元素嵌套Q如?5 所C:
q可以通过查这?Web 面q行 CSS ~辑。Inspection 视图会显C相关的 CSS 条目Q包括承样式。如?6 的示例:
CSS 工具q可用来~辑 CSS x属性、禁用属性、自动完成和囄预览Q如?7 所C:
CSS 的可视化在检?HTMLQ回??3 中的蓝色ҎQ已l展C了。Firebug Layout 选项卡显CZ更多的信息,比如间隙?偏移和其他相关的量度。图 8 中的布局H口则显CZ一个导航元素的量度Q?
?9 展示了能x~辑 CSS 盒的奇妙?Firebug Ҏ:
![]() ![]() |
现在QJavaScript 工具?Web 开发中最有用的工具之一。Firebug 提供了调试、剖析、日志记录和命o行控制台Ҏ?
Firebug JavaScript 工具包括断点、监视表辑ּ和典型调试器中常见的其他一些工兗图 10 展示了断点和逐步调试的实际例子。请注意作ؓ工具提示的主机变量的倹{?/p>
?10. JavaScript 调试?/strong>
有用的调试工兯Q?
JavaScript 剖析非常有用。如 Firebug 中的其他Ҏ一P剖析也很Ҏ使用。单?Console 选项卡上?Profile 启动剖析器,如图 11 所C:
剖析开始后Q可以浏览一下此站点。单?Profile 获得剖析报告Q如?12 所C:
该报告显CZ花在函数上的旉和^均时间等{?
对于更愿意用老的日志记录Q而非调试Q方式的开发h员,Firebug 提供了日志记录功能。日志记录用的是一U?Firebug JavaScript API。最单的一U日志条目是 console.log("logging");
?/p>
Console API 包含其他一些功能,如清?1 所C:
console.time("test timer"); console.log("Hello from ",document.title); console.info("This is info"); console.warn("This is warning"); console.error("This is error"); console.timeEnd("test timer"); |
可以使用 console.time
?console.timeEnd
来测量执行时间。在详细报告中显C结果的 console.profile()
?console.profileEnd()
Q见清单 1Q也可用来测量执行时间?/p>
?13 昄了这些结果。JavaScript 控制台日志测试功能被d到由 Web 服务器提供服务的面中?/p>
?13. Console 日志
Console API 内其他有用的Ҏ还有堆栈跟t、对象检查和字符串格式化?
Firebug 最为强大特性之一是 JavaScript 命o行。这U命令行的用方式与其他命o行一P它执行您~写的所?JavaScript 代码Q好像它们就是页面的一部分一栗通过命o行,可以?DOM、获得属性等{。所有返回值都昄在控制台上?/p>
命o行具有自动完成功能(使用 Tab 键)以及完善的文本编辑器Q能够编写完整的函数而不仅仅是几行代码){等。图 14 l出了一个简单的控制C话。请注意 Web 面左上角的徽标。这里也可以q行x~辑?/p>
?14. 命o?JavaScript
与控制台cMQ命令行也有一?APIQ它包含可用?Firebug 的特D函敎ͼ比如 $(id)。该函数能够q回带有l定 id 的元素?
![]() ![]() |
Firebug Network Monitor Ҏ可用来监视加蝲 Web 面所p的时间。?Net 选项卡可以看到进度栏Q该q度栏显CZ一个文件相Ҏ有其他文件开始和停止加蝲的时间。Network Monitor 分开每个文g的流量,因此可以查看加载图像、JavaScript、HTML {各占用了多时间。此外,q可以查看资源是否从览器缓存中加蝲?/p>
对于本例中的 Ajax 开发,Firebug ?Net 选项卡和 Console 选项卡中均显CZ每个 XMLHttpRequest?
?15 昄了如何利?Network Monitor 查看 HTTP h和响应头。要查看 HTTP _只需单击每个h左侧的箭头将其展开。全部请求、已用时间和内容的大均昄?Firebug H口底部?/p>
?15. Network Monitor
![]() ![]() |
Firebug 的其他特性包括:
一旦错误发生,Firebug 能够提供有用的:
Firebug q会昄只与所查看的页面相关的错误?/p>
Document Object Model ?Web 面中的对象和函数的{l构。Firebug DOM 包括所有定制的和标准的对象Q而且 DOM explorer 能够分L它们。这里同样可以进?JavaScript 代码D、自动完成和x~辑?/p>
Firebug 定制Ҏ包括黑名单和白名单以及依据个h需要更改字体大的功能?/p>