??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲夂夂婷婷色拍WW47,亚洲制服丝袜一区二区三区,亚洲国产婷婷六月丁香http://www.tkk7.com/sutao/category/24293.html用文字记录学习的体验Q?/description>zh-cnThu, 22 Nov 2007 09:21:14 GMTThu, 22 Nov 2007 09:21:14 GMT60java heap详细介绍http://www.tkk7.com/sutao/articles/162288.html苏醄苏醄Thu, 22 Nov 2007 02:20:00 GMThttp://www.tkk7.com/sutao/articles/162288.htmlhttp://www.tkk7.com/sutao/comments/162288.htmlhttp://www.tkk7.com/sutao/articles/162288.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162288.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162288.html

1?br />

PermGen space的全U是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决Ҏ也一定是加大内存。说说ؓ什么会内存益出Q这一部分用于存放Class和Meta的信?Class在被 Load的时候被攑օPermGen space区域Q它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主E序q行期对PermGen spaceq行清理Q所以如果你的APP会LOAD很多CLASS的话,很可能出现PermGen space错误。这U错误常见在web服务器对JSPq行pre compile的时候?/span>

ҎҎQ?Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

2?/span>

在tomcat中redeploy时出现outofmemory的错?

可以有以下几个方面的原因:

Q?使用?u>proxool,因ؓproxool内部包含了一个老版本的cglib.

2, log4j,最好不?只用common-logging

3, 老版本的cglib,快点更新到最新版?/span>

Q,更新到最新的hibernate3.2

3?br />
q里以tomcat环境ZQ其它WEB服务器如jboss,weblogic{是同一个道理?br /> 一、java.lang.OutOfMemoryError: PermGen space

PermGen space的全U是Permanent Generation space,是指内存的永久保存区?
q块内存主要是被JVM存放Class和Meta信息?Class在被Loader时就会被攑ֈPermGen space?
它和存放cd?Instance)的Heap区域不同,GC(Garbage Collection)不会在主E序q行期对
PermGen spaceq行清理Q所以如果你的应用中有很多CLASS的话,很可能出现PermGen space错误,
q种错误常见在web服务器对JSPq行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大?br /> 过了jvm默认的大?4M)那么׃产生此错误信息了?br /> 解决ҎQ?手动讄MaxPermSize大小

修改TOMCAT_HOME/bin/catalina.sh
?#8220;echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
Q将相同的第三方jar文gUȝ到tomcat/shared/lib目录下,q样可以辑ֈ减少jar 文重复占用内存的目的?/span>

二、java.lang.OutOfMemoryError: Java heap space
Heap size 讄
JVM堆的讄是指javaE序q行q程中JVM可以调配使用的内存空间的讄.JVM在启动的时候会自动讄Heap size的|
其初始空??Xms)是物理内存的1/64Q最大空?-Xmx)是物理内存的1/4。可以利用JVM提供?Xmn -Xms -Xmx{选项?br /> q行讄。Heap size 的大是Young Generation 和Tenured Generaion 之和?br /> 提示Q在JVM中如?8Q的旉是用于GC且可用的Heap size 不2Q的时候将抛出此异怿息?br /> 提示QHeap Size 最大不要超q可用物理内存的80Q,一般的要将-Xms?Xmx选项讄为相同,?Xmn?/4?Xmx倹{?
解决ҎQ手动设|Heap size
修改TOMCAT_HOME/bin/catalina.sh
?#8220;echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m   -XX:MaxNewSize=256m"

三、实例,以下l出1G内存环境下java jvm 的参数设|参考:

JAVA_OPTS="-server -Xms800m -Xmx800m  -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "


三、相兌?/span>

/show/3/7/20061112220131.htm

/show/3/7/20061112220054.htm

/show/3/7/20061112220201.htm

题外话:l常看到|友抱怨tomcat的性能不如...Q不E_{,其实ҎW者几q的l验Q从"互联星空“到现在的房门户|,我们
均用tomcat作ؓWEB服务器,每天讉K量百万多Qtomcat仍然q行良好。徏议大家有问题多从自己E序入手Q多看看java的DOC文
q详l了解JVM的知识。这样开发的E序才会健壮?br />
延阅读Q?/span>

JVM 性能调整的一些基本概?/span>

apache+Tomcat负蝲q讄详解[转]

java - the Java application launcher

JVM调优[转]



苏醄 2007-11-22 10:20 发表评论
]]>
struts异常处理http://www.tkk7.com/sutao/articles/161519.html苏醄苏醄Mon, 19 Nov 2007 02:06:00 GMThttp://www.tkk7.com/sutao/articles/161519.htmlhttp://www.tkk7.com/sutao/comments/161519.htmlhttp://www.tkk7.com/sutao/articles/161519.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161519.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161519.htmlStruts异常处理(原创) ?常是当JVM(JAVA虚拟?在执行应用程序的某个Ҏ的时候遇到的非正常现?JVM׃生成一个异常对?抛给客户以便客户q行异常处理. Struts框架的异常处理机制徏立在java异常处理的基之上.在研IStruts异常处理之前,先回一下java异常处理原理,理解java虚拟 机JVM的异常处理过E有助于应用设计正确的异常处理方?处理异常需要JVM付出不小的开销,所以用于必L重? JAVA 异常是在javaE序q行的时候遇到非正常的情况而创建的对象,它封装了异常信息,java异常的根cMؓjava.lang.Throwable,整个c?有两个直接子cjava.lang.Error和java.lang.Exception.Error是程序本w无法恢复的严重错误.Exception 则表C可以被E序捕获q处理的异常错误.JVM用方法调用栈来跟t每个线E中一pd的方法调用过E?该栈保存了每个调用方法的本地信息.对于独立?JAVAE序,可以一直到该程序的mainҎ.当一个新Ҏ被调用的时?JVM把描q该Ҏ的栈l构|入栈顶,位于栈顶的方法ؓ正确执行的方?当一 个JAVAҎ正常执行完毕,JVM回从调用栈中弹处该方法的栈结?然后l箋处理前一个方?如果javaҎ在执行代码的q程中抛出异?JVM必须 扑ֈ能捕获异常的catch块代?它首先查看当前方法是否贼q样的catch代码?如果存在执行该catch代码?否则JVM回调用栈中弹处该?法的栈结?l箋到前一个方法中查找合适的catch代码?最后如果JVM向上q到了main()Ҏ,也就是一直把异常抛给了main()Ҏ,仍然 没有扑ֈ该异常处理的代码?该线E就会异常终?如果该线E是ȝE?应用E序也随之终?此时JVM把异常直接抛给用户,在用L端上会看到原始的 异常信息.回顾完了JAVA的异常处理机?p开始研IStruts的异常处理了. Struts 框架在视囑ֱ和控制层提供了对异常处理的支?Struts的控制器负责捕获各种异常,包括控制器运行中本n抛出的异?以及调用模型的业务方法的异常. 当异常被控制器捕L时?在异常处理代码块?创徏描述异常信息的ActionMessage对象把它保存在ActionMessages或者它的子c?ActionErrors对象?然后把它保存在特定的范围?比如request或session.接下来在视图? 标签索特定范围的ActionMessages对象,把本地化错误消息输出到页面上.q种异常处理机制可以避免用户看到原始?java异常信息.可以更友好的把错误信息展C给用户. Struts 框架处理异常是以JVM的异常处理机制ؓ基础?管它提供了强大的通用错误处理机制,但是不能保证捕获到所有的异常或者错?当错误发生的时?如果 Struts不能处理q种异常或者错?把错误抛给JavaWeb容器.容器先查看是否在Web应用发布描述文g中配|了元素,如果存在该元素就q回元素的子元素指定的错误页?否则׃把错误直接抛l用?下面单介l一 Struts几个重要的类的异常处理机?如果想了解这几个cȝ更深的异常机?查看Struts源代? 1) ActionServletcȝpeocess()Ҏ不捕获Q何异?仅仅声明向上层调用方法抛出异? 2) RequestProcessorcLStruts框架处理异常的核心组? 3) ExceptionHandlercL默认的异常处理类,它的execute()Ҏ负责处理异常. Ҏ打造技术Blog,LJAVA_N! Servlet规范,当容器捕获到异常的时?查看是否在Web.xml中配|了相应?error-page>元素,如果存在,׃q回?location>子元素指定的错误面.举个单明了的例子如下: 500 /error.jsp javax.servlet.ServletException /error.jsp Struts框架也允总配置的方式来处理??配置Ҏ可以避免在ActioncM通过编码来处理异常,提高应用的灵zL?可重用性和可维护?对于Actioncȝexecute()Ҏ抛出 的异怼先查扑ּ常处理元?exception>,如果是被嵌套?global-exception>元素中就表示是全局异常处理元素,Ҏ有的Action都适用.如果是嵌套在元素?pC局部的异常处理元素,仅对当前的Action适用.?qC?exception>元素的属? 1) type:指定待处理的异常c?2) handler:指定异常处理c?默认是ExceptionHandler.如果自己要定义必ȝ承它 3) path:指定转发路径 4) key:指定错误消息key.Ҏq个key到ResourceBundle中寻扑֌配的消息文本 5) bundle:指定ResourceBundle,如果没设|将使用哦么人的ResourceBundle 6) scope:指定ActionMessages对象的存放范?默认request,也可以设|session Struts框架提供了强大的异常处理功能,Struts控制器负责捕获异?q把异常包装?ResourceBundlel定?ActionMessages对象,在视囑ֱ 标签能够昄出来,主要可以通过配置的方式和~程的方式实?q里不推 荐用~程的方?可以增强E序的灵zL?可重用?可维护? (|友们的支持,是我l箋写技术文章的动力!) Struts的异常处理机制ȝ来说Q在struts新的版本中加入了对异常的处理Q称之ؓQException HandlingQ标志着作ؓ一个整体的解决框架Qstruts原来趋于成熟??常来_以前在用struts开发的q程中,对于异常的处理,主要是采用手动处理的方式Q如通过try/catch{等捕获异常Q然后定制个性化的比较详 l的错误信息放进ActionError中,然后在具体的q回面中把q些错误信息反馈l用P包括开发员Q。异常原始的信息不管是最l用戯是开发员都是不希望看到的?下面着重讲一下在struts中是如何通过配置文g来解军_常?Struts中的Exception Handleing不难Q简单高效是业内l其的一个比较好的评仗?通过配置文gQ主要是struts-config.xmlQ来定制异常处理Q就象定义formbean一P定制异常也有两种ҎQ姑且把它分为:“全局异常”?#8220;局部异?#8221;?全局异常Q定义方法如下: ………… ………… ?qC码在struts-config.xml中定义了一个全局异常Q它的作用是抛出InvalidiItemsCatalogNameException Q本处的意思是当在d商品分类的时候发现该cd已经存在Q异常的时候返回到error.jsp中,q且携带自定的比较规范的异常信息 expired.InvalidItemsCatalogNameQexpired.InvalidItemsCatalogName可以在应用程序的资源配置文g中找?如: expired.InvalidItemsCatalogName=你要d的商品类别已l存在,h加新的类别! 局部异常,定义Ҏ如下Q?………… ………… Q关于Tiles的内容参看我的另一文?#8220;Struts使用Tiles辅助开?#8221;Q?下面我们把关注的目光攑֜具体action里,看看struts是如何进行异常处理的 //ItemsCatalogAction.java package com.iplateau.jshop.action.ItemsCatalogAction import com.iplateau.jshop.business.ItemsCatalogMap; import com.iplateau.jshop.action.ItemsCatalogForm; import ***; public class ItemsCatalogAction extends BaseAction { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String flg=”error”; String act=request.getParameter(“act”); ItemsCatalogMap map=new ItemsCatalogMap(); ItemsCatalogForm thisform=( ItemsCatalogForm)form; // ItemsCatalogMap为具体的处理商品cd的类 if(act.equals(“create”)) { map.validateNameOfCatalog(thisform); map.create(thisform); flg=”success”; return mapping.findForward(flg); } else{ return mapping.findForward(flg); } } } 上便是一个简单的actionQ其中用act的具体内Ҏ判断此时的action要处理的操作Q如act为cteate的时候,处理的是商品cd的添加等{?看了上边的代码,可以了解Q在调用具体的业务类q行d商品cd以前先要判断此时要添加的商品cd的合法性,如: 调用map.validateNameOfCatalog(thisform); 其中在ItemsCatalogMap定义的validateNameOfCatalog Ҏ抛出InvalidiItemsCatalogNameException?下面让我们运行一下添加商品类别的例子Q如果此时数据库中已l存?#8220;牛奶制品”q个商品cdQ而我们又要添加此cd的时?E序如我们预想的一栯{到error.jspq且昄了我们要先是的错误信息:你要d的商品类别已l存在,h加新的类别! 其实p么简单,我们的定制的异常在程序中q不需要用try/catch来捕P一旦出C我们已经定义的异帔R么就会{到相应得面Qƈ且携带定制的信息?q记得在struts先前的版本中我们的请求都是通过action的perform来处理,可是现在都要通过execute来处理,其原因一个很重要的就?#8220;成全”Exception Handling。ؓ什么呢Q?因ؓperform在声明的时候仅仅抛出IOException 和ServletExceptionQ这q远不能满Exception Handling的要?那么让我们看看execute是怎样的:它笼l的抛出ExceptionQ所有异常的父类Q??面的阐述只是一个引子,而且默认struts的异常是通过org.apache.struts.action. ExceptionHandler来处理的Q你可以定义自己的处理方式,只要l承它ƈ实现其中的executeҎQ这个方法在ExceptionHandler的定义如下: public ActionForward execute (Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException 具体而且专业的分析Exception Handling的内容,请参看《Programming Jakarta Struts》第10??q本书的电子版网上很多地方可以下载?原文地址 http://tech.ccidnet.com/pub/article/c322_a74029_p1.html

苏醄 2007-11-19 10:06 发表评论
]]>
Jive论坛pȝ详细介绍http://www.tkk7.com/sutao/articles/158764.html苏醄苏醄Wed, 07 Nov 2007 03:08:00 GMThttp://www.tkk7.com/sutao/articles/158764.htmlhttp://www.tkk7.com/sutao/comments/158764.htmlhttp://www.tkk7.com/sutao/articles/158764.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/158764.htmlhttp://www.tkk7.com/sutao/services/trackbacks/158764.html阅读全文

苏醄 2007-11-07 11:08 发表评论
]]>
用Apache做负载均衡时HTTP长连接每5分钟断线 http://www.tkk7.com/sutao/articles/138857.html苏醄苏醄Thu, 23 Aug 2007 07:41:00 GMThttp://www.tkk7.com/sutao/articles/138857.htmlhttp://www.tkk7.com/sutao/comments/138857.htmlhttp://www.tkk7.com/sutao/articles/138857.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/138857.htmlhttp://www.tkk7.com/sutao/services/trackbacks/138857.html用Apache做负载均衡时HTTP长连接每5分钟断线

Apache 被常用来做Java应用pȝ的负载均衡YӞTomcat、Websphere、Weblogic{都有相应的插g支持Apache集成负蝲均衡。但是最 q遇到这L问题Q对于大数据量的长HTTPq接的业务每q?分钟断U了Q而且?分钟重发同一个httph到应用服务器?br> Apache的httpd.conf有下列两个配|参敎ͼcM地Array、F5{负载均衡硬件也应该有这些配|:
#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

q两个参CD那些HTTP长连接,如对大数据量操作的请求每q?00U就会断U,q且会每300U重试发送请求给Weblogic{应用服务器Q导致应用异常?br> 虽然应用E序应该量避免每次httph别太长,但是万一有这L业务Q那么只能调整Timeout参数?/font>


苏醄 2007-08-23 15:41 发表评论
]]>
Apache 实现止囄盗链http://www.tkk7.com/sutao/articles/136033.html苏醄苏醄Sat, 11 Aug 2007 08:01:00 GMThttp://www.tkk7.com/sutao/articles/136033.htmlhttp://www.tkk7.com/sutao/comments/136033.htmlhttp://www.tkk7.com/sutao/articles/136033.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/136033.htmlhttp://www.tkk7.com/sutao/services/trackbacks/136033.html Apache 实现止盗链

1、假讑օ许连l?strong style="background-color: #a0ffff;">囄的主机域名ؓQwww.gongyelu.cn

2、修改httpd.conf

Code:
SetEnvIfNoCase Referer "^http://www.gongyelu.cn/" local_ref=1
<FilesMatch ".(gif|jpg)">
Order Allow,Deny
Allow from env=local_ref
</FilesMatch>


q个单的应用不光可以解决盗链的问题,E加修改q可以防止Q意文件盗链下载的问题?

使用以上的方法当从非指定的主l?strong style="background-color: #a0ffff;">囄Ӟ无法显C,如果希望昄一?#8220;止盗链”?strong style="background-color: #a0ffff;">囄Q我们可以用mod_rewrite 来实现?

首先在安?apache 时要加上 --enable-rewrite 参数加蝲 mod_rewrite 模组?

假设“止盗链”?strong style="background-color: #a0ffff;">囄为abc.gifQ我们在 httpd.conf 中可以这样配|:


Code:
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?demo.com.cn /.*$ [NC]
RewriteRule \.(gif|jpg)$ http://www.demo.com.cn/abc.gif [R,L]

Q+Q+Q+Q+Q+Q+Q+Q+Q+Q+Q+Q+Q+Q?/p>

DocumentRoot "/usr/local/apache/htdocs"
#讄


苏醄 2007-08-11 16:01 发表评论
]]>
Tomcat安全域设|大?/title><link>http://www.tkk7.com/sutao/articles/134194.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Fri, 03 Aug 2007 03:20:00 GMT</pubDate><guid>http://www.tkk7.com/sutao/articles/134194.html</guid><wfw:comment>http://www.tkk7.com/sutao/comments/134194.html</wfw:comment><comments>http://www.tkk7.com/sutao/articles/134194.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/sutao/comments/commentRss/134194.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/sutao/services/trackbacks/134194.html</trackback:ping><description><![CDATA[<p>安全域是tomcat内置的功能,在org.apache.catalina.Realm接口中声明了把一l用户名Q口令及所兌的角色集成到Tomcat的方法中QTomcat5提供?个实现这一接口的类Q它们代表了4U安全域cd?/p> <p>  下面我一一介绍其相关配|,及其应用Ҏ?/p> <p>  q行环境Qwindows2000Qtomcat5.0.28Qjdk1.5Qjdbc3.0Qsqlserver2000Q?<br>  试目录Q?tomcat%\webapps\Area目录?/p> <p>  1. 内存域:cdQMemoryRealmQ在初始化阶D,从xml文g中读取安全验证信息,q把它们以一l对象的形式攑֜内存中?<br>  对于资源讉K它有三种方式QBASIC、DIGEST、FORM。用Basic Authentication通过被认为是不安全的Q因为它没有强健的加密方法,除非在客L和服务器端都使用HTTPS或者其他密码加密码方式Q比如,在一个虚拟私人网l中Q?<br>  配置文g%tomcat%\conf\Catalina\localhost\Area.xml为: <br>  <?xml version='1.0' encoding='utf-8'?> <br>  <Context docBase="D:\jakarta-tomcat-5.0.28\webapps\Area" path="/Area" reloadable="true" <br>   workDir="work\Catalina\localhost\Area"> <br>    <Realm className="org.apache.catalina.realm.MemoryRealm"/> <br>  </Context> <br>  web应用所在的WEB-INF\web.xml为: <br>  <?xml version="1.0" encoding="GB2312"?> <br>  <!DOCTYPE web-app <br>   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <br>   <web-app> <br>    <security-constraint> <br>    <display-name>sessiontest secruity constraint</display-name> <br>    <web-resource-collection> <br>    <web-resource-name>Protected Area</web-resource-name> <br>    <url-pattern>/test/*</url-pattern> <br>    </web-resource-collection></p> <p>   <auth-constraint> <br>    <role-name>cool</role-name> <br>   </auth-constraint> <br>   </security-constraint></p> <p><!--以下是基于BASIC验证--> <br>    <login-config> <br>   <auth-method>BASIC</auth-method> <br>    <realm-name>Sessiontest Realm</realm-name> <br>   </login-config></p> <p><!--以下是基于DIGEST验证--> <br><!--  <login-config> <br>   <auth-method>DIGEST</auth-method> <br>    <realm-name>Sessiontest Realm</realm-name> <br>   </login-config> <br>--></p> <p><!--以下是基于FORM验证--> <br><!-- <login-config> <br>    <auth-method>FORM</auth-method> <br>    <realm-name>Sessiontest Realm</realm-name> <br>    <form-login-config> <br>     <form-login-page>/usercheck.jsp</form-login-page> <br>     <form-error-page>/error.jsp</form-error-page> <br>    </form-login-config> <br>   </login-config> <br>若采用form验证Qusercheck.jspQ主要参?不要L改它)讄如下Q?<br><form method="post" action="j_security_check"> <br><input type="text" name="j_username"><br> <br><br> <br><input type="password" name="j_password"><br> <br><br> <br><input type="submit" value="login"> <br><input type="reset" value="reset"> <br></form> <br>--></p> <p>    <security-role> <br>   <description> session jdbctest </description> <br>   <role-name>cool</role-name> <br>   </security-role> <br>  </web-app> <br> Z<url-pattern>/test/*</url-pattern>表示受保护的资源为:http: //localhost:8080/Area/test/下的所有资源。role角色cool?tomcat%conf中的tomcat- users.xml中添加: <br>   <role rolename="cool"/> <br>  <user username="zxj1" password="zxj2" roles="cool"/></p> <p>  2. JDBC域:cdQJDBCRealmQ通过jdbc驱动E序讉K存在数据库中的安全验证?/p> <p>  3. 数据源域Q类名,DataSourceRealmQ通过JNDI数据源访问存在数据库中的安全验证信息?/p> 4. JNDI域:cdQJNDIRealmQ通过JNDIproveider讉K存放在基于LDAP的目录服务器中的安全验证信息<img src ="http://www.tkk7.com/sutao/aggbug/134194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/sutao/" target="_blank">苏醄</a> 2007-08-03 11:20 <a href="http://www.tkk7.com/sutao/articles/134194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat5集群中的SESSON复制http://www.tkk7.com/sutao/articles/134191.html苏醄苏醄Fri, 03 Aug 2007 03:10:00 GMThttp://www.tkk7.com/sutao/articles/134191.htmlhttp://www.tkk7.com/sutao/comments/134191.htmlhttp://www.tkk7.com/sutao/articles/134191.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/134191.htmlhttp://www.tkk7.com/sutao/services/trackbacks/134191.html  
  集群
  
  传统独立服务器(非集的Q不提供M失效无缝转移以及负蝲q能力。当服务器失败的时候,无法获取整个网站的内容Q除非服务器被重新唤赗由于服务器失效QQ何存储在服务器内存中的SESSION都会丢失Q用户必重新登陆ƈ且输入所有由于服务器失效丢失的数据?br>  
不同的是Q作为集一部分的服务器则提供了可测性以及失效无~{U能力。一个集就是一l同步运行ƈ且协同工作,能提供高可靠性,高稳定性以及高可测? 的多服务器例E。服务端集群对客L表现出来g是一个单独的服务器例E。从客户端的视角来看Q集的客户端和单独的服务器没多大不同,但是他们通过? 供实效无~{UdSESSION复制做到了不间断服务以及SESSION数据持久性?br>  
  集群中的服务器通讯
  
  集群中的应用E序服务器通过诸如IP多点传送(IP multicastQ和IP socketsq样的技术和其他服务器共享信?br>  
  ●IP多点传送:主要用于1对多的服务器通讯Q通过q播服务?heartbeats消息的可用来昄服务器的有效
  
  ●IP socketsQ主要用于在集群的服务器例程中进行P2P服务器通讯
  
  使用IP多点传送进行一对多通讯
  
TOMCAT服务器用IP多点传送在集群中的服务器例E间q行一对多的通讯QIP多点传送是一U能够让多服务器向指定IP地址和端口号q行订阅q且? 听消息的q播技术(多点传送IP地址范围?24.0.0.0 ?39.255.255.255Q。在集群中的每个服务器都使用多点传送广播特定的 heartbeat消息Q通过监视q些 heartbeat消息Q在集群中的服务器例E判断什么时候服务器例程失效。在服务器通讯中用IP多点传送的一个缺Ҏ他不能保证这些消息被实接收? 了。例如,一个应用持l的本地多点传送缓存满了,׃能写入新的多点传送消息,{消息过了之后该应用E序没有被通知到?br>  
  使用IP Socketsq行服务器通讯
  
IP sockets 同样也通过了一套在集群中的服务器间q行发送消息和数据的机制。服务器例程使用IP sockets 在集节炚wq行HTTP SESSION状态的复制。正的SOKET配制对于集群的性能是至关重要的Q基于SOCKET的通讯的效率取决于SOCKET的实现类别(例如Q系l 用本地的或者纯JAVA SOCKETd器实玎ͼQ如果服务器使用UJAVA SOCKETd器则要看服务器例E是否注册用了_的SOCKETd器线E?br>  
  如果惌有最佳的SOCKET性能Q系l应? 注册使用本地的SOCEKT而不是纯JAVA实现。这是因为相对于ZJAVA的SOCKET实现Q本地SOCKET消耗更的pȝ资源。虽? SOCKETd器的JAVA实现是P2P通信中一U可靠而且可移动的ҎQ可是他不能为集中的重型SOCKET使用提供最好的性能。当判断? SOCKET是否有数据读取的时候本地SOCKETd器用了更有效率的方法。用本地SOCKETd器实玎ͼd器线E不需要去l计静止? SOCKETQ他们仅仅ؓzd的SOCKET服务Qƈ且在一个给定的SOCKET开始活跃v来时他们可以立刻捕捉到。而用纯JAVA SOCKETd器,U程必须动态的l计所有打开的SOCKETQ判断他们是否包含可d的数据。换句话_SOCKETd器L忙于l计 SOCKETQ即使这些SOCKET没有数据可读。这些本不应该的pȝ开销降低了性能?br>  
  TOMCAT 5中的集群
  
虽然在TOMCAT5的早些版本中也有集群的功能,但是在稍后的版本中(5??9或者更高)Q集变的更加模块组件化。在 server.xml 中集元素已l被重构Q这h们可以替换集的不同部分而不会媄响其他元素。例如,当前配置中把成员服务讄为多点传送发现。这里可以轻易地把成员服务修 Ҏ换ؓ使用TCP或?Unicast Q而不会改变集c逻辑的其他部分?br>  
  其他一些集元素,例如SESSION理器,复制发送端Q复制接受端也可以被自定义的实现取代而不影响集群配置的其他部分。同P在TOMCAT集群中的M服务器组件可以用集cAPI向集中的所有成员发送消息?br>  
  SESSION复制
  
服务器集通常操纵两种SESSIONQ?sticky sessions?replicated sessions 。sticky sessions是存在单机服务器中的接受网l请求的SESSIONQ其他集成员对该服务器的SESSION状态完全不清楚Q如果存有SESSION 的服务器p|的话Q用户必dơ登陆网站,重新输入所有存储在SESSION中的数据?br>  
  另一USESSIONcd是,在一台服? 器中SESSION状态被复制到集中的其他所有服务器上,无论何时Q只要SESSION 被改变,SESSION数据都要重新被复制。这是 replicated session ?sticky ?replicated sessions都有他们的优~点Q?Sticky sessions单而又Ҏ操作Q因为我们不必复制Q何SESSION数据到其他服务器上。这样就会减系l消耗,提高性能。但是如果服务器p|Q所? 存储在该服务器内存中的SESSION数据也同样会消失。如果SESSION数据没有被复制到其他服务器,q些SESSION完全丢׃。当我们在进? 一个查询事务当中的时候,丢失所有已l输入的数据Q就会导致很多问题?br>  
  Z支持 JSP HTTP session 状态的自动失效无缝转移QTOMCAT服务器复制了在内存中的SESSION状态。这是通过复制存储在一台服务器上的SESSION数据到集中其他成员上防止数据丢׃及允许失效无~{UR?br>  
  对象的状态管?/strong>
  
  通过在服务器上的保存状态可以区分出4U对象:
  
●无状态:一个无状态对象在调用的时候不会在内存中保存Q何状态,因ؓ客户端和服务器端没必要保存Q何有兛_方的信息。在q种情况下,客户端会在每ơ请 求服务器旉会发送数据给服务器。SESSION状态被在客L和服务器端来回发送。这U方法不L可行和理想的Q特别是当传输的数据比较大或者一些安? 信息我们不想保存在客L的时候;
  
  ●会话:一个会话对象在一个SESSION中只被用于特定的某个客户端。在SESSION中, 他可以ؓ所有来自该客户端的h服务Qƈ且仅仅是q个客户端的h。诏I一个SESSIONQ两个请求间的状态信息必M存。会话服务通常在内存中保存? 暂的状态,当在服务器失败的时候可能会丢失。SESSION状态通常被保存在h间的服务器的内存中。ؓ了清I内存,SESSION状态也可以被从内存? 释放Q就像在一个对象CACHEQ。在该对象中Q性能和可量测性都有待提高Q因为更新ƈ不是被单独的写到盘上,q且服务器失败的时候数据也没办法抢救?br>  
  ●缓存:~存对象在内存中保存状态,q且使用q个d理从多客L来的h。缓存服务的实现可以扩展C们把~存的是数据备䆾保存在后端存储器中(通常是一个关pL据库Q?br>  
●独立的Q一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客L的请求。他通常由那些私有的Q持久的Q在内存中缓寸的数据支持? 他同样也在内存中保持短暂状态,在服务器p|的时候要重徏或者丢失。当p|的时候,独立对象必须在同一个服务器上重h者移植到另一台服务器上?br>  
  (来源: "Using WebLogic Server Clusters")
  
  SESSION复制的设计考虑事项
  
  |络考虑事项

  
把集的多点传送地址和其他应用程序隔L臛_重要的。我们不希望集群配置或者网l布局q扰到多点传送服务器通信。和其他应用E序׃n集群多点传送地址 迫佉K的服务器例E处理不应该的消息,消耗系l内存。共享多点传送地址可能也会使IP多点传送缓冲过载,延迟服务?heartbeat 消息传输。这L延迟可能D一个服务器例程被标识ؓMQ仅仅因Z?heartbeat 消息没有被及时接收?br>  
  ~程考虑事项
  
  除了上面提到的网l相兛_素,q有些和我们?J2EE |络应用E序有关的设计考虑也会影响SESSION复制。以下列Z一些编E方面的考虑Q?br>  
  ●SESSION数据必须被序列化Qؓ了支持HTTP session 状态的内存内复Ӟ所有的 servlet ?JSP session 数据必须被序列化Q对象中的每个域都必被序列化,q样对象被可靠的序列化?br>  
●把应用E序设计为幂{的Q幂{的的意思就是一个操做不会修改状态信息,q且每次操作的时候都q回同样的结果(换句话说是Q做多次和做一ơ的效果是一 LQ,通常QWEBhQ特别是 HTML forms 都被发送多ơ(当用Ld送按U两ơ,重蝲面多次Q,D多次HTTPh。设计SERVLET和其他WEB对象? q等的,可以容忍多次h。详l可以去参考设计模?#8220;Synchronized Token ”?#8220;Idempotent Receiver ”关于怎样设计q等的的应用E序?br>  
  ●在BUSINESS层存储状态:会话状态应该用有状态的SESSION BEANS存储在EJB层,而不是存储在WEB层的HttpSession。因Z业应用程序要支持各种cd客户端(WEB客户端,JAVA应用E序Q其 他EJBQ,存储数据在WEB层会D在客L的双数据存储。因此,有状态的SESSION BEAN在这些情况下p用于存储SESSION状态。无状态的SESSION BEAN要ؓ每次的调用重构造会话状态。这些状态可能必M数据库中恢复的数据中重编译。这些缺点失M使用无状态SESSION BEANL高性能和可量性的目的Q严重的减低了性能?br>  
  ●序列化pȝ消耗:序列化SESSION数据在复制SESSION状态的时候回会些pȝ消耗。随着序列化对象大的增长消耗也多。最好是保持SE


实践中整理出tomcat集群和负载均?br>(一)环境说明
(1)服务器有4収ͼ一台安装apache,三台安装tomcat
(2)apache2.0.55、tomcat5.5.15、jk2.0.4、jdk1.5.6或jdk1.4.2
(3)ip配置,一台安装apache的ip?92.168.0.88,三台安装tomcat的服务器ip分别?92.168.0.1/2/4
(?安装q程
(1)在三台要安装tomcat的服务器上先安装jdk
(2)配置jdk的安装\?在环境变量path中加入jdk的bin路径,新徏环境变量JAVA_HOME指向jdk的安装\?br>(3)在三台要安装tomcat的服务器上分别安装tomcat,调试三个tomcat到能够正常启?br>(4)tomcat的默认WEB服务端口?080,默认的模式是单独服务,我的三个tomcat的WEB服务端口修改?080/8888/9999
修改位置为tomcat的安装目录下的conf/server.xml
修改前的配置?br>    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />
修改后的配置?br>    <Connector port="7080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />
依次修改每个tomcat的监听端?7080/8888/9999)

(5)分别试每个tomcat的启动是否正?br>http://192.168.0.1:7080
http://192.168.0.2:8888
http://192.168.0.4:9999
(?负蝲均衡配置q程
(1)在那台要安装apache的服务器上安装apache2.0.55,我的安装路径为默认C:\Program Files\Apache Group\Apache2
(2)安装后测试apache能否正常启动Q调试到能够正常启动http://192.168.0.88
(3)下蝲jk2.0.4后解压羃文g
(4)解压羃后的目录中的modules目录中的mod_jk2.so文g复制到apache的安装目录下的modules目录?我的为C:\Program Files\Apache Group\Apache2\modules
(5)修改apache的安装目录中的conf目录的配|文件httpd.confQ在文g中加LoadModule模块配置信息的最后加上一句LoadModule jk2_module modules/mod_jk2.so
(6)分别修改三个tomcat的配|文件conf/server.xmlQ修改内容如?br>修改?br>    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host). -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">        
    -->
        
    <!-- Define the top level container in our container hierarchy -->
    <Engine name="Catalina" defaultHost="localhost">
修改?br>    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host). -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :-->
    <Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1">        
    
        
    <!-- Define the top level container in our container hierarchy
    <Engine name="Catalina" defaultHost="localhost">
    -->
其中的jvmRoute="jvm1"分别修改为jvmRoute="tomcat1"和jvmRoute="tomcat2"和jvmRoute="tomcat3"

(7)然后重启三个tomcatQ调试能够正常启动?br>(8)在apache的安装目录中的conf目录下创建文件workers2.propertieQ写入文件内容如?br>
# fine the communication channel
[channel.socket:192.168.0.1:8009]
info=Ajp13 forwarding over socket
#配置W一个服务器
tomcatId=tomcat1 #要和tomcat的配|文件server.xml中的jvmRoute="tomcat1"名称一?br>debug=0
lb_factor=1 #负蝲q因子Q数字越大请求被分配的几率越?br>
# Define the communication channel
[channel.socket:192.168.0.2:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat2
debug=0
lb_factor=1

# Define the communication channel
[channel.socket:192.168.0.4:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat3
debug=0
lb_factor=1

[status:]
info=Status worker, displays runtime information.  

[uri:/jkstatus.jsp]
info=Display status information and checks the config file for changes.
group=status:

[uri:/*]
info=Map the whole webapp
debug=0
(9)在三个tomcat的安装目录中的webapps建立相同的应?我和应用目录名ؓTomcatDemo,在三个应用目录中建立相同 WEB-INF目录和页面index.jsp,index.jsp的页面内容如?br><%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
  out.println("<br> ID " + session.getId()+"<br>");

  // 如果有新?Session 属性设|?br>  String dataName = request.getParameter("dataName");
  if (dataName != null && dataName.length() > 0) {
     String dataValue = request.getParameter("dataValue");
     session.setAttribute(dataName, dataValue);
  }

  out.print("<b>Session 列表</b>");

  Enumeration e = session.getAttributeNames();
  while (e.hasMoreElements()) {
     String name = (String)e.nextElement();
     String value = session.getAttribute(name).toString();
     out.println( name + " = " + value+"<br>");
         System.out.println( name + " = " + value);
   }
%>
  <form action="index.jsp" method="POST">
    名称:<input type=text size=20 name="dataName">
     <br>
    ?<input type=text size=20 name="dataValue">
     <br>
    <input type=submit>
   </form>
</body>
</html>
(10)重启apache服务器和三个tomcat服务?到此负蝲 均衡已配|完成。测试负载均衡先试apache,讉Khttp://192.168.0.88/jkstatus.jsp
能否正常讉KQƈ查询其中的内容,有三个tomcat的相关配|信息和负蝲说明,讉Khttp://192.168.0.88/TomcatDemo/index.jsp看能够运?
能运行,则已建立负蝲均衡?br>(?tomcat集群配置
(1)负蝲均衡配置的条件下配置tomcat集群
(2)分别修改三个tomcat的配|文件conf/server.xml,修改内容如下
修改?br>        <!--
        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 useDirtyFlag="true"
                 notifyListenersOnReplication="true">

            <Membership
                className="org.apache.catalina.cluster.mcast.McastService"
                mcastAddr="228.0.0.4"
                mcastPort="45564"
                mcastFrequency="500"
                mcastDropTime="3000"/>

            <Receiver
                className="org.apache.catalina.cluster.tcp.ReplicationListener"
                tcpListenAddress="auto"
                tcpListenPort="4001"
                tcpSelectorTimeout="100"
                tcpThreadCount="6"/>

            <Sender
                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                replicationMode="pooled"
                ackTimeout="5000"/>

            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
                  
            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                      tempDir="/tmp/war-temp/"
                      deployDir="/tmp/war-deploy/"
                      watchDir="/tmp/war-listen/"
                      watchEnabled="false"/>
                      
            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
        </Cluster>
        -->  
修改?br>        <!-- modify by whh -->
        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 useDirtyFlag="true"
                 notifyListenersOnReplication="true">

            <Membership
                className="org.apache.catalina.cluster.mcast.McastService"
                mcastAddr="228.0.0.4"
                mcastPort="45564"
                mcastFrequency="500"
                mcastDropTime="3000"/>

            <Receiver
                className="org.apache.catalina.cluster.tcp.ReplicationListener"
                tcpListenAddress="auto"
                tcpListenPort="4001"
                tcpSelectorTimeout="100"
                tcpThreadCount="6"/>

            <Sender
                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                replicationMode="pooled"
                ackTimeout="5000"/>

            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
                  
            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                      tempDir="/tmp/war-temp/"
                      deployDir="/tmp/war-deploy/"
                      watchDir="/tmp/war-listen/"
                      watchEnabled="false"/>
                      
            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
        </Cluster>
       <!-- modify by whh -->      
集配|选项的注释放开卛_Q如上?br>(3)重启三个tomcat。到此tomcat的集已配置完成?/p>

 

(?应用配置
对于要进行负载和集群的的tomcat目录下的webapps中的应用中的WEB-INF中的web.xml文g要添加如下一句配|?br><distributable/>
配置?br><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
  <display-name>TomcatDemo</display-name>
</web-app>
配置?br><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
  <display-name>TomcatDemo</display-name>
   <distributable/>
</web-app>

?tomcat集群是怎么处理session的阿

{?在tomcat做集之后,每个tomcat之间自动Ҏtomcat的配|文件中的参数进行session复制,
对于一个客L对说Q只要是同一个IPQ那它每ơ上传的sessionID是一L,


苏醄 2007-08-03 11:10 发表评论
]]>
Hibernate二~存全攻?/title><link>http://www.tkk7.com/sutao/articles/134086.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 02 Aug 2007 10:06:00 GMT</pubDate><guid>http://www.tkk7.com/sutao/articles/134086.html</guid><wfw:comment>http://www.tkk7.com/sutao/comments/134086.html</wfw:comment><comments>http://www.tkk7.com/sutao/articles/134086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/sutao/comments/commentRss/134086.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/sutao/services/trackbacks/134086.html</trackback:ping><description><![CDATA[<font size="2">   【IT168 技术文】很多h对二U缓存都不太了解Q或者是有错误的认识Q我一直想写一文章介l一下hibernate的二U缓存的Q今天终于忍不住了?<br>我的l验主要来自hibernate2.1版本Q基本原理和3.0?.1是一LQ请原谅我的固不化?/font> <p><font size="2">    hibernate的session提供了一U缓存,每个sessionQ对同一个idq行两次loadQ不会发送两条sqll数据库Q但是session关闭的时候,一U缓存就失效了?/font></p> <p><font size="2">    二~存是SessionFactoryU别的全局~存Q它底下可以使用不同的缓存类库,比如ehcache、oscache{,需要设|hibernate.cache.provider_classQ我们这里用ehcacheQ在2.1中就?<br>hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider <br>如果使用查询~存Q加?<br>hibernate.cache.use_query_cache=true</font></p> <p><font size="2">~存可以单的看成一个MapQ通过key在缓存里面找value?/font></p> <p><font size="2"><strong>Class的缓?/strong><br>    对于一条记录,也就是一个PO来说Q是ҎID来找的,~存的key是IDQvalue是POJO。无论listQloadq是 iterateQ只要读Z个对象,都会填充~存。但是list不会使用~存Q而iterate会先取数据库select id出来Q然后一个id一个id的loadQ如果在~存里面有,׃~存取,没有的话去数据库load。假设是d~存Q需要设|: <br><br><cache usage="read-write"/> <br><br>    如果你用的二~存实现是ehcache的话Q需要配|ehcache.xml <br><cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" /> <br><br>    其中eternal表示~存是不是永q不时QtimeToLiveSeconds是缓存中每个元素Q这里也是一个POJOQ的时旉Q如? eternal="false"Q超q指定的旉Q这个元素就被移C。timeToIdleSeconds是发呆时_是可选的。当往~存里面put 的元素超q?00个时Q如果overflowToDisk="true"Q就会把~存中的部分数据保存在硬盘上的时文仉面?<br><br>    每个需要缓存的class都要q样配置。如果你没有配置Qhibernate会在启动的时候警告你Q然后用defaultCache的配|,q样多个class会共享一个配|?<br>当某个ID通过hibernate修改Ӟhibernate会知道,于是U除~存?<br><br>    q样大家可能会想Q同L查询条gQ第一ơ先listQ第二次再iterateQ就可以使用到缓存了。实际上q是很难的,因ؓ你无法判断什么时候是W一 ơ,而且每次查询的条仉常是不一LQ假如数据库里面?00条记录,id??00Q第一ơlist的时候出了前50个idQ第二次 iterate的时候却查询?0?0号idQ那?0-50是从~存里面取的Q?1?0是从数据库取的,共发?+20条sql。所以我一直认? iterate没有什么用QL会有1+N的问题?<br><br>    Q题外话Q有说法说大型查询用list会把整个l果集装入内存,很慢Q而iterate只select id比较好,但是大型查询L要分|的,谁也不会真的把整个结果集装进来,假如一?0条的话,iterate共需要执?1条语句,list虽然选择 若干字段Q比iterateW一条select id语句慢一些,但只有一条语句,不装入整个结果集hibernateq会Ҏ数据库方a做优化,比如使用mysql的limitQ整体看来应该还? list快。) <br><br>    如果惌对list或者iterate查询的结果缓存,p用到查询~存?/font></p> <p><br></p> <p><font size="2"><br></font> </p> <p><font size="2"><strong>查询~存<br></strong><br>    首先需要配|hibernate.cache.use_query_cache=true <br><br>    如果用ehcacheQ配|ehcache.xmlQ注意hibernate3.0以后不是net.sf的包名了 <br><cache name="net.sf.hibernate.cache.StandardQueryCache" <br>maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600" <br>timeToLiveSeconds="7200" overflowToDisk="true"/> <br><cache name="net.sf.hibernate.cache.UpdateTimestampsCache" <br>maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/> <br>然后 <br>query.setCacheable(true);//ȀzL询缓?<br>query.setCacheRegion("myCacheRegion");//指定要用的cacheRegionQ可?<br>W二行指定要使用的cacheRegion是myCacheRegionQ即你可以给每个查询~存做一个单独的配置Q用setCacheRegion来做q个指定Q需要在ehcache.xml里面配置它: <br><br><cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" /> <br><br>    如果省略W二行,不设|cacheRegion的话Q那么会使用上面提到的标准查询缓存的配置Q也是net.sf.hibernate.cache.StandardQueryCache</font><font size="2">对于查询~存来说Q缓存的key是根据hql生成的sqlQ再加上参数Q分늭信息Q可以通过日志输出看到Q不q它的输Z是很可读Q最好改一下它的代码)?<br>比如hqlQ?<br>from Cat c where c.name like ? <br>生成大致如下的sqlQ?<br>select * from cat c where c.name like ? <br><br>    参数?tiger%"Q那么查询缓存的key*大约*是这L字符Ԍ我是凭记忆写的,q不_Q不q看了也该明白了Q: <br><br>select * from cat c where c.name like ? , parameter:tiger% <br><br>    q样Q保证了同样的查询、同L参数{条件下h一Lkey?<br>? 在说说缓存的valueQ如果是list方式的话Qvalue在这里ƈ不是整个l果集,而是查询出来的这一串ID。也是_不管是listҎq是 iterateҎQ第一ơ查询的时候,它们的查询方式很它们qx的方式是一LQlist执行一条sqlQiterate执行1+N条,多出来的行ؓ? 它们填充了缓存。但是到同样条gW二ơ查询的时候,都和iterate的行Z样了Q根据缓存的keyȝ存里面查CvalueQvalue是一? idQ然后在到class的缓存里面去一个一个的load出来。这样做是ؓ了节U内存?<br><br>    可以看出来,查询~存需要打开相关cȝclass~存。list和iterateҎW一ơ执行的时候,都是既填充查询缓存又填充class~存的?<br><br><strong>    q里q有一个很Ҏ被忽视的重要问题Q即打开查询~存以后Q即使是listҎ也可能遇?+N的问题!</strong>? 同条件第一ơlist的时候,因ؓ查询~存中找不到Q不class~存是否存在数据QL发送一条sql语句到数据库获取全部数据Q然后填充查询缓存和 class~存。但是第二次执行的时候,问题来了,如果你的class~存的超时时间比较短Q现在class~存都超时了Q但是查询缓存还在,那么 listҎ在获取id串以后,会一个一个去数据库loadQ因此,class~存的超时时间一定不能短于查询缓存设|的时旉Q如果还讄了发呆时 间的话,保证class~存的发呆时间也大于查询的缓存的生存旉。这里还有其他情况,比如class~存被程序强制evict了,q种情况p自己注意 了?/font></p> <p><font size="2">    另外Q如果hql查询包含select字句Q那么查询缓存里面的value是整个l果集了?/font></p> <p><font size="2">    当hibernate更新数据库的时候,它怎么知道更新哪些查询~存呢? <br>hibernate在一个地方维护每个表的最后更新时_其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配|里面?<br>? 通过hibernate更新的时候,hibernate会知道这ơ更新媄响了哪些表。然后它更新q些表的最后更新时间。每个缓存都有一个生成时间和q个~? 存所查询的表Q当hibernate查询一个缓存是否存在的时候,如果~存存在Q它q要取出~存的生成时间和q个~存所查询的表Q然后去查找q些表的最? 更新旉Q如果有一个表在生成时间后更新q了Q那么这个缓存是无效的?<br>可以看出Q只要更新过一个表Q那么凡是涉及到q个表的查询~存失效了Q因此查询缓存的命中率可能会比较低?/font></p> <p><font size="2"><strong>Collection~存<br></strong><br>    需要在hbm的collection里面讄 <br><cache usage="read-write"/> <br>假如class是CatQcollection叫childrenQ那么ehcache里面配置 <br><cache name="com.xxx.pojo.Cat.children" <br>maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" <br>overflowToDisk="true" /> <br>Collection的缓存和前面查询~存的list一P也是只保持一串idQ但它不会因个表更新q就失效Q一个collection~存仅在q个collection里面的元素有增删时才失效?br><br>    q样有一个问题,如果你的collection是根据某个字D|序的Q当其中一个元素更C该字D|Q导致顺序改变时Qcollection~存里面的顺序没有做更新?br> <p><strong>~存{略<br></strong><br>    只读~存Qread-onlyQ:没有什么好说的 <br>    ?写缓存(read-writeQ?E序可能要的更新数据 <br>    不严格的?写缓存(nonstrict-read-writeQ:需要更新数据,但是两个事务更新同一条记录的可能性很,性能比读写缓存好 <br>    事务~存QtransactionalQ:~存支持事务Q发生异常的时候,~存也能够回滚,只支持jta环境Q这个我没有怎么研究q?/p> <p>    d~存和不严格d~存在实C的区别在于,d~存更新~存的时候会把缓存里面的数据换成一个锁Q其他事务如果去取相应的~存数据Q发现被锁住了,然后q接取数据库查询?<br>在hibernate2.1的ehcache实现中,如果锁住部分~存的事务发生了异常Q那么缓存会一直被锁住Q直?0U后时?<br>不严D写缓存不锁定~存中的数据?/p> </font></p> <p> </p> <p><font size="2"><strong>使用二~存的前|条?br></strong><br>    你的hibernateE序Ҏ据库有独占的写访问权Q其他的q程更新了数据库Qhibernate是不可能知道的。你操作数据库必需直接通过 hibernateQ如果你调用存储q程Q或者自׃用jdbc更新数据库,hibernate也是不知道的。hibernate3.0的大扚w更新和删 除是不更CU缓存的Q但是据?.1已经解决了这个问题?<br>q个限制相当的棘手,有时候hibernate做批量更新、删除很慢,但是你却不能自己写jdbc来优化,很郁闷吧?<br><br>    SessionFactory也提供了U除~存的方法,你一定要自己写一些JDBC的话Q可以调用这些方法移除缓存,q些Ҏ是: <br>void evict(Class persistentClass) <br>Evict all entries from the second-level cache. <br>void evict(Class persistentClass, Serializable id) <br>Evict an entry from the second-level cache. <br>void evictCollection(String roleName) <br>Evict all entries from the second-level cache. <br>void evictCollection(String roleName, Serializable id) <br>Evict an entry from the second-level cache. <br>void evictQueries() <br>Evict any query result sets cached in the default query cache region. <br>void evictQueries(String cacheRegion) <br>Evict any query result sets cached in the named query cache region. <br><br>    不过我不q样做,因ؓq样很难l护。比如你现在用JDBC扚w更新了某个表Q有3个查询缓存会用到q个表,用evictQueries (String cacheRegion)U除?个查询缓存,然后用evict(Class persistentClass)U除了class~存Q看上去好像完整了。不q哪天你d了一个相x询缓存,可能会忘记更新这里的U除代码。如果你? jdbc代码到处都是Q在你添加一个查询缓存的时候,q知道其他什么地方也要做相应的改动吗Q?/font></p> <p><font size="2">----------------------------------------------------</font></p> <p><font size="2"><strong>ȝQ?/strong><br>    不要惛_然的以ؓ~存一定能提高性能Q仅仅在你能够驾驭它q且条g合适的情况下才是这L。hibernate的二U缓存限制还是比较多的,不方便用 jdbc可能会大大的降低更新性能。在不了解原理的情况下ؕ用,可能会有1+N的问题。不当的使用q可能导致读数据?<br>如果受不了hibernate的诸多限Ӟ那么q是自己在应用程序的层面上做~存吧?<br>    在越高的层面上做~存Q效果就会越好。就好像管盘有缓存,数据库还是要实现自己的缓存,管数据库有~存Q咱们的应用E序q是要做~存。因为底层的~? 存它q不知道高层要用q些数据q什么,只能做的比较通用Q而高层可以有针对性的实现~存Q所以在更高的别上做缓存,效果也要好些吧?/font></p> <p><font size="2">    l于写完了,好篏……</font></p><img src ="http://www.tkk7.com/sutao/aggbug/134086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/sutao/" target="_blank">苏醄</a> 2007-08-02 18:06 <a href="http://www.tkk7.com/sutao/articles/134086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBM WebSphere Application Server诊断和调?/title><link>http://www.tkk7.com/sutao/articles/134085.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 02 Aug 2007 10:04:00 GMT</pubDate><guid>http://www.tkk7.com/sutao/articles/134085.html</guid><wfw:comment>http://www.tkk7.com/sutao/comments/134085.html</wfw:comment><comments>http://www.tkk7.com/sutao/articles/134085.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/sutao/comments/commentRss/134085.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/sutao/services/trackbacks/134085.html</trackback:ping><description><![CDATA[<div id="k82qscc" class="w_t1"> <div id="ymmmoq8" class="w_c2"> <div id="kcawwue" class="l2 f16"> <h1>IBM WebSphere Application Server诊断和调优(二)</h1> </div> <div id="seqq4ku" class="r2 top8">[<a href="javascript:d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();">收藏此页</a>] [<a href="javascript:window.print();">打印</a>]</div> </div> <div id="yiy2quu" class="top11"> </div> <div id="om4euge" class="w_c2"> <div id="oqscmeu" class="l2"> 作者:<strong class="red">佚名</strong>  2007-06-25 </div> <div id="cewweu2" class="r2"> <div><strong>内容DQ?/strong></div> <a href="javascript:;" id="Nav1" class="sel"> W?? </a> <div id="gakssas" class="pp"> <div class="qmsassq" id="Nav1Menu" class="p"> <a title="W?? class="hov1">W?:<span> W?? </span></a> <a title="W??>W?:<span> W?? </span></a> <a title="W??>W?:<span> W?? </span></a> <a title="W??>W?:<span> W?? </span></a> </div> </div> </div> <script>init_Nav();</script> </div> </div> <div class="ackccks" id="1"><font size="2">IT168 技术文档】近D|_我们目中用到的WebSphere应用服务?WAS)Q但在客Lproduction环境下极不稳定,l常宕机。给客户造成? 怸好的影响Q同Ӟ也给目l很大压力。ؓ此,我们׃q一个月旉对其诊断Q现在基本上E_了,需要l观察一D|间。现在我主要工作做一个阶D|? 的ȝ?<br>我们的品环境是QWAS6.0QDB2 8.1QAIX5.3QRS/6000。在该品环境下Q出现的问题非常多,现象如下Q?<br>WASl常不稳定、宕机几乎一天一ơ,l常报告OutOfMemory(内存泄漏吗?NO)?<br>DB2q接数过大,有时把DB2撑死Q有时也把AIX撑死?<br>AIX虚拟内存报错、分|错、IO也报错、还有很多其它莫名奇妙的错?/font> <p><font size="2">    LQ每ơ问题发生的现象和理Z的L不一_D我们不知道从何入手,也无从检自q优化参数。咨询过多次IBM技术支持,只解决了某些局部问题?<br>虽然问题依然存在Q但我想Q解决问题的思\、特别是理论基础Q还是有一些规律和原则?/font></p> <p><font size="2">对于WASq块Q我q段旉的主要时间集中在以下几个斚w(旉序)Q?<br>1、Java性能监测工具QJprofilerQ也用到Jprobe。后来发现Jprofiler在AIX下几乎不可用?<br>2、IBM Java虚拟机和WAS技术细节,特别是IBM JVM的GC原理Q我发现它和sun、bea的差别很大?<br>3、IBM的heap分析器Heap Analyzer、GCCollector。这两个事后监测工具非常实用Q特别是我们的品运行环境,非测试环境?<br>4、某些Application的怀疑和诊断?<br>5、AIX诊断Q我几乎没有q个能力Q只能常规监一下,需另请高h?/font></p> <p><font size="2">我打将本文分成以下几个部分ȝQ?<br>JVM原理、IBM JVM的GC{略和调优?<br>Jprofiler和IBM工具的实际体?<br>WAS的诊断体会和AIX调优</font></p> <p><font size="2">    下面开始主题吧Q可能比较零,另外Q开始的理论基本上看书都可以,我只是ȝ一下,再添加一些自q理解?/font></p> <p><font size="2">以下是我参考的最重要的两本电子书和一些网站: <br>《Inside Java Vrtual Machine?半部分有U四章我认ؓ非常,其它章节可能意义不大?<br>《The Java Virtual Machine Specification, 2nd》:前半部分有两三章很不错,不过可以对照上一本书看?<br>sun的hotspot虚拟机技术:</font><a target="blank"><font size="2">http://java.sun.com/javase/technologies/hotspot/ </font></a><br><font size="2">BEA的JRockit虚拟机技术:</font><a target="blank"><font size="2">http://edocs.bea.com/jrockit/geninfo/genintro/index.html </font></a><font size="2">JVM技术文入口,虚拟机理论,内存泄漏诊断{的索引c?<br>IBM诊断资料Q?/font><a target="blank"><font size="2">http://www-128.ibm.com/developerworks/java/jdk/diagnosis/</font></a><font size="2"> 上面有一?00多页的pdf文Q对IBM JVM技术和诊断讲解很深入?/font></p> <p><font size="2">    我不得不提的是,在查资料q块QBEA和Sun都有很好的官Ҏ和论坛支持Qƈ且官Ҏ导航非常好。虽然IBM的诊断资料也不少Q但需要搜索,其搜? 是很痛苦的。而且QIBM官方论坛很差。如果用IBM的品出问题Q切讎ͼ找IBM技术支持,千万不要蒙着头搞Q反正它们的产品很少免费。说实话Q它们的 技术支持还是挺负责的,一般会Z推荐很多support资料Q而该资料往往都在developerworks|站上,属于support那个频道Q但? 是搜不着?/font></p> <p><font size="2"><strong>Java虚拟范概?/strong> <br><br>    研究Java虚拟机,首先要了解Sun的Java虚拟范。现在,该实现版本很多,如比较有名的Sun、IBM、BEA、Apple、HP、MS? Apache Harmony。它们都实现了JVM规范Q但有各自扩展。譬如,针对IBM虚拟机的堆碎片导致OutOfMemoryQOOMQ,在Sun的虚拟机上就? 会发生。Sun的JVM有maxPermSize的概念,IBM没有,如果你设|这个参敎ͼ虚拟机根本就启动不了?br> <br>    比较有意思的是,学JavaQ就一定要了解各种规范Q这和MS的风格很不一栗SunL在定义一些规范,实现都留l各厂商。我们除了理解规范本w外Q一 定要理解规范和实C间的关系Q譬如JDBC规范和JDBC驱动的关p,它们是怎么l合CL。要是你用过php的xml解析库,或db函数Q就会体? 深刻Q它们可没有什么规范可aQ所以每个数据库厂商的db函数用法都不一栗我推荐大家研读一下HSQLDB的jdbc和Tomcat的servlet? 兛_玎ͼ因ؓ我认为它们还是比较好懂的?<br><br>    JVM规范只是定义一个虚拟机该做什么,但它q没有要求你该怎么做。例如我们最常见的Servlet规范Q在该规范中Q有 HttpServletRequest、HttpServletResponseQHttpSession{接口,但它们的实现都留l了各个容器厂商。遗 憄是,规范留下的空白,会把我们q些开发h员给整惨了:容器间移植有时候就是恶梦。譬如J2EEq没有SSO规范Q但它很重要Q我以前专门针对它做q? WebSphere AppServer和Weblogic AppServer的SSO目Q差别还是不,不过q是有点共通,那就是都遵@JAAS规范?/font></p> <p><br></p> <p><font size="2"><strong>JVM的结?/strong> <br><br>    从功能上分,Java虚拟Z要由六个部分l成Q可以分成三c: <br>W一c:JVM APIQ就是我们最常用的Java APIQ它是开发h员和Java交互的入口,它主要是JAVA_HOME/jre/lib下的q行时类库rt.jar和编译相关的tools.jar</font></p> <p><font size="2">W二c:JVM内部lg <br><strong>c装载器</strong>(ClassLoader)Q将Byte Array?.class文g装蝲、链接和初始化?<br><strong>内存理</strong>(Memory Managent)Qؓ对象分配内存Q以及释攑ֆ存。后者就是垃圑֛收Garbage CollectorQGCQ。由于JVM最复杂的、最影响性能的就是GCQ所以内存管理一般就指垃圑֛收?<br><strong>诊断接口</strong>(Diagostics Interface)Q这主要体现在JVMTI(jdk1.4下的JVMPI和JVMDI)Q它主要用来诊断E序的问题和性能Q一般提供给工具厂商实现。如eclispe IDE下的debug功能QJprofiler性能调优工具?<br><strong>c解释器</strong>(Interpreter)Q解释装载进虚拟机的class对象Q包括JIT{特性相兟?/font></p> <p><font size="2">W三c:q_相关接口(Platform Interface)Q主要ؓ了跨操作pȝq_重用JVM代码Q不q,它和我们开发h员关pM大?/font></p> <p><font size="2">    在以上六个组件中Q我们开发h员最兛_的是<strong>ClassLoader</strong>?strong>GC</strong>Q? 用Java做系l框架、容器和它们密切相关。做业务pȝ时一些基代码也和它们打交道,譬如最常用的Class.forName(), Thread.currentThread.getContextClassLoader()。我们仔l想惻IZ么是上面两个问题Q因为,它和我们 class的整个生命周期最为相养I怎么一个class和相关class加蝲q来Qclass实例什么时候创建,什么时候被销毁? <br>所以,下面的部分我们要专门讨论q些问题?/font></p> <p><font size="2"><strong>ClassLoader</strong> <br><br>    JVM主要有三cClassLoaderQBootstrap、Extention、ApplicationQ该三类ClassLoader从上C是分U?hierarchy)l构Q遵循代理模?Delegation Model)?<br>TipQ大家可以看看sun.misc.Launcher的源码,Bootstrap和Extention在该文仉。该src可以在sun的网站上下蝲该压~包Q约60M(jdk-1_5_0-src-scsl.zip)Q它不在jdk自带的那个src.zip里?/font></p> <p><font size="2">    Bootstrap ClassLoaderQ也UCؓprimordial(root) class loader。主要是负责装蝲jre/lib下的jar文gQ当Ӟ你也可以通过-Xbootclasspath参数定义。该ClassLoader不能 被Java代码实例化,因ؓ它是JVM本n的一部分?/font></p> <p><font size="2">    Extention ClassLoaderQ该ClassLoader是Bootstrap classLoader的子class loader。它主要负责加蝲jre/lib/ext/下的所有jar文g。只要jar包放|这个位|,׃被虚拟机加蝲。一个常见的、类似的问题是,? mysql的低版本驱动不小心放|在q儿Q但你的Web应用E序的lib下有一个新的jdbc驱动Q但怎么都报错,譬如不支持JDBC2.0? DataSourceQ这时你p当心你的新jdbc可能q没有被加蝲。这是ClassLoader的delegate现象。常见的有log4j? common-log、dbcp会出现问题,因ؓ它们很容易被人塞到这个ext目录Q或是Tomcat下的common/lib目录?/font></p> <p><font size="2">    Application ClassLoaderQ也UCؓSystem ClassLoaer。它负责加蝲CLASSPATH环境变量下的classes。缺省情况下Q它是用户创建的MClassLoader的父 ClassLoaderQ我们创建的standalone应用的main class~省情况下也是由它加?通过Thread.currentThread().getContextClassLoader()查看)?<br>我们实际开发中Q用ClassLoader更多时候是用其加蝲classpath下的资源Q特别是配置文gQ如ClassLoader.getResource()Q比FileInputStream直接?/font></p> <p><font size="2">ClassLoader是一U分U?<strong>hierarchy</strong>)的代?<strong>delegation</strong>)模型?<br>DelegationQ? 其实是Parent DelegationQ当需要加载一个classӞ当前U程的ClassLoader首先会将h代理到其父classLoaderQ递归向上Q如果该 class已经被父classLoader加蝲Q那么直接拿来用Q譬如典型的ArrayListQ它最l由Bootstrap ClassLoader加蝲。ƈ且,每个ClassLoader只有一个父ClassLoader?<br>Class查找的位|和序依次是:Cache、parent、self?<br>HierarchyQ? 上面的delegation已经暗示了一U分U结构,同时它也说明Q一个ClassLoader只能看到被它自己加蝲的classesQ或是看到其? (parent) ClassLoader或祖?ancestor) ClassLoader加蝲的Classes?<br>在一个单虚拟机环境下Q标识一个类有两个因素:class的全路径名、该cȝClassLoader?/font></p> <p><font size="2">    我碰到的一个典型的例子是:在做WAS的SSO开发时Q由于我们的cL由WAS在启动时加蝲Q该ClassLoader比下面的部v的Applicaton的ClassLoader的别高。所以,在我们自qcM没法用到应用E序的连接池Q必自建?<br>? 理模型是Java安全模型的保证。譬如,我们自己写一个String.javaQƈ且编译、package到自qjava.lang包下。按照代理模 型,当前U程的ClassLoader会将其代理到父ClassLoaderQ父ClassLoader(最l会是Bootstrap)会找? rt.jar下的String.classQ也是说我们的String.class不会捣ؕ?/font></p> <p><font size="2"><strong>自定义ClassLoader</strong> <br>    我们前面说过Q自定义ClassLoader的缺省父ClassLoader是Application ClassLoader。一般的应用开发用不到它,但我们最好理解。因为在内存泄漏查找、应用程序部|出问题Ӟ很多都和它有兟?<br>? 如,内存泄漏是怎么产生的?q就涉及到ClassLoader和Class的生命周期。我曄到q样一个问题:我们的程序用CWebwork? Spring框架Q当部v到Tomcat下时没有M问题Q但部v到WAS下,报告找不到Webwork的xml的DTD文gQ而且Spring的日志也 L失效。WhyQ因析xml dtdӞ用的是IBM的XercesQ不是我们的。而Spring日志问题是因为应用程序用的是WAS的Common-log.jarQ而不是我们的? 应用的ClassLoader从默认的Parent-FirstQ改成Parent-Last可以解冻I不过我们目中用到其它库Q又发生了其它问 题?/font></p> <p><font size="2">一般来_用到自定义ClassLoader有三U情况: <br>1、应用框架可以自己控制Classes的目录,q且自动部v?<br>我读qJive公司的Wildfire(著名的即旉讯服务?Q它自己有一套应用框Ӟ非常灉|Q遵循该框架插g规范的的W三方的plug-in攄在指定目录可以自动部|Ԍ实现某些扩展功能Q如文g传输、语韌天?<br>2、区分用户代?<br>q被q泛应用在Servlet容器和类似容器,譬如EJB Container设计中,大家看到Tomcat下有common、server、share三个目录?ClassLoader序从左到有)Q另外也有用户应用的WEB-INF目录Q它是我们自己开发的?<br>3、允许Classes卸蝲 <br>? 果没有自定义的ClassLoaderQ那么我们自己应用中的classes永远都不能被卸蝲Q因些类被Application ClassLoader加蝲后cacheh了,我们的classes一直对该ClassLoader有引用,而该pȝU的ClassLoader永远? 不会被卸载,除非JVM shutdown了。JSP和Servlet的动态部|就用到q个Ҏ?/font></p> <p><font size="2">待箋.......</font></p> <p><font size="2">Note: q有JVMq行?Runtime)架构QClassLoader加蝲classq程没有ȝQ这两部分我觉得太重要了Q但内容太多Q写不完啊?<br>q部分内容,《Inside Java Virtual Machine》讲解非常清楚,BEA的官方网站这部分也非怸错,要理解深刻,我徏议结合JProfiler工具Q非常直观?/font></p> <p><font size="2">待箋.......</font></p> <br><font size="2"><br><br><br>【IT168 技术文?br><br></font> <p><font size="2">    l写q篇文章Q已l过M个半月了。直到现在,pȝ一直运行^E?<br>先说说我接手q项工作的经? 吧:该项目大部分?6q?0月就部v在客户那边了Q到07q?月䆾QWAS宕机问题实在无法忍受Q我才加入进来,前半q有另外一位同事断断箋l处理,? 寚w题一直都无可奈何Q而且目负责Z没有引v_的重视。可惌知Q最后付出的代h是非常惨重的。在q近半年的时间内Q服务器宕机63ơ。每ơ宕? ӞWAS的JVM会dumpZ个heapdump.phd文g(heap快照)Q然后JVM死掉了Q当Ӟ此时WAS也停止了响应。一般我们的做法 是重启,最后是q脆AIX每天晚上定时重启。有时候一天还dơ。大家见附g的截图(all-GC.pngQ。这是我接手后,用IBM的分析工具得到的? 图。对截图的分析,留给后面对应的部分吧?<br>服务器不E_、宕机问题,拖g到最后,客户愤怒了Q公叔R层也x了Q部门还专门成立了八人攻关组。当然了Q我当时的压力也非常大,因ؓ我是技术负责hQ也是实实在在q活、想L的?<br>服务器诊断那D|_从前到后Q我们也是沿着一条线C来,虽然最后发现很多\都走不通。现在就按这个思\Q也是旉先后一步步叙述吧。我惻I大家如果也碰到类似应用服务器诊断Q应该思\差不多?/font></p> <p><font size="2">术语说明Q?<br>IBM Websphere Application ServerQWASQWebSphere本n是一个^収ͼ产品家族 <br>OutOfMemoryErrorQOOMQ内存泄漏,内存溢出 <br>Gabage CollectionQGCQ自动垃圑֛?<br>Content Management SystemQCMSQ就是给新闻c门L站编辑们用的pȝ</font></p> <p><font size="2">我们诊断大体上经历了以下几个阶段Q?<br>1、按Job调度U程池引起内存泄漏诊断:因ؓ很多ơOOM是发生在某个特定时候,譬如14Q?0?2Q?0左右?<br>2、按应用E序引v内存泄漏诊断Q用JProfiler{工h:因ؓL发生OOM?<br>3、分WAS怀疑有OOM的应用:因ؓ每个WAS应用太多Q?0来个Q؜一h法定位?<br>4、用IBM官方heap、GC分析工具。以及和IBM技术支持联pRWAS、AIX参数优化?<br>5、隔dWAS恉E序Q一个CMS产品?<br>6、WAS、AIX参数优化、设|?/font></p> <p><font size="2">我们走到W?步时Q才出现效果。计一下,那时已经q去一个月了。服务器宕机、系l不E_Q在q个验收的时候,客户已经忍无可忍Q以致后来的每一ơ行动都得胆战心惊得d?/font></p> <p><font size="2"><strong>一、按Job调度U程池导致内存泄漏诊?/strong> <br>    因ؓ从我们WAS的日?默认是native_stderr.log)来看Q最q半q的宕机旉都有一个明显时间规律。见附g截图Job1-1.png?<br>    我想Q做qJava服务器性能调优的朋友,都知道在Web容器里面启线E池是个不太好的做法Q因为Web容器本n有一个线E池Q譬如ServletU程? QTomcat默认?5个)Q而自启的U程池很ҎDServletU程理混ؕQ最l导致GC问题。我们的现象g和那很符合。如果我们沿着q个? 路做下去Q具体怎样实施呢?</font></p> <p><font size="2">    我们的WAS上部|了20个左右的Web应用Q譬如Lucene全文索、B2B行业数据同步{,都是通过Quartz的Job调度做的Q当然还有很多其 它调度。当Ӟ由我负责Q通知相关负责人,定时调度暂时去掉。观察了几天Q后来发现问题依然存在,不过旉有点随机了?<br>不过Q最后还是发现OOM不是由Job调度引v的?<br>? 是_我们q个Ҏ是失败的。而且Q我们的很多x都是臆测的,没有可靠的根据,也没有方向,再加上我是第一ơ处理这U问题,q导致后来查N题的? 难。但是,仔细xQ我们又能拿什么做依据呢?出现OOM错误Q我惛_多数人想到的Q除了JVM参数讄Q就是内存泄漏。其实,OOM发生有很多种情况Q? 在IBM、Sun、BEA{不同虚拟机上,因ؓGC机制不一P所以原因一般都不同Q容易定位难度也不一栗下文会谈到?<br>于是Q我们干脆釜底抽薪分析问题吧Q用JProfiler?/font></p> <p><br></p> <p><font size="2"><strong>二、按应用E序D内存泄漏诊断QJProfiler?/strong> <br><br>    如果遇到OOM问题Q我惛_安会想到内存检工P现在最可靠的还是下面三U分析工PBorland 的Optimizeit SuiteQQuest的JProbeQej-technologies的JProfiler。但面三个问题Q?<br>1、三个都是商业品,公司暂时没有乎ͼ必须自己下蝲Q而且要找序列受?<br>2、工具必L持AIX5.3QJDK1.42QWAS6.0Q不是Windowsq_?<br>3、工具必d客户真实环境下部|Ԍ对客L业务不能有冲击,也就是说部v试工具前,必须做个大量试Q对工具非常熟练Q遇到意外可以立x复现场?<br>Note:目上线后,而不是测试或试运行阶D遇到此c问题,非常考验人;另外一个,是性能和可伸羃性问题,很可能把整个目l毁了?/font></p> <p><font size="2">    当我军_要这么做后,q卛_手查阅这些工L官方文Q用emule下蝲Q最l都下蝲C。试用后Q最l选择了JProfiler4.03Q比起其它工 P它界面美观、清晰、功能强大、集成度?Heap,Memory,CPU,Thread都统一?。另外,JProbe没有AIX版本Q这也是攑ּ? 的一个原因?/font></p> <p><font size="2">    JVM的Profiler原理Q都是通过JVM内置的的标准C语言Profiler 接口攉数据Q然后通过Profiler工具的客L展现。也是说各厂商的Profiler工具Q都有两个部分,一个部分是Profiler AgentQ和JVMl定Q负责收集JVM内部数据Q譬如方法调用次数、耗费旉{;另外一个部分就是Profiler front-end。通过Profiler工具的自定义local或remote协议传输到front-endQ其实,我们最常用的JavaIDE? debug功能是在此基础上的QJPDAQ。(JProfiler的截?/font><a target="blank"><font size="2">http://www.ej-technologies.com/products/jprofiler/screenshots.html</font></a><font size="2"> Q?<br>下面是Sun官方文Q?<br>JDK1.42及以前是JVM PIQ?/font><a target="blank"><font size="2">http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html</font></a><font size="2"> <br>JDK1.5是JVM TIQ?/font><a target="blank"><font size="2">http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html</font></a><font size="2"> <br>具体到JProfiler的配|上Q专门针对JDK1.4?.5的JVM配置差别很大?<br><br>我用的JProfiler?.31版本Q透露l大家一个万能序列号?q东西不太好?Q对各版本应该都支持。深入了解JavaQ这cdh不可的Q?<br>Name: License for You <br>Lincese Code: A-G667#42616F-10kg1r134fq9m#2217</font></p> <p><font size="2">Z保证真实环境的检成功,我做了大量的试验Q譬如: <br>1、Windowspd的本地、远E测试?<br>2、AIX的远E测试?<br>3、Tomcat5.0、WebLogic8.14、WebSphere6.02Q以及上qCU方式的l合试Q排列组合,场景不下10个?<br>当时也参阅了大量JVM文QJProfiler官方几百英文文,辅助的JProbe对照。而且也制造过内存泄漏造成的OOM场景?<br>当然Q要是在几个月前Q在客户那边部v的测试环境时Q就q行试该多好啊?/font></p> <p><font size="2">    在公司内部,我用JProfiler试了我们当旉|的几个应用Q没有发现内存泄漏,所以,我们最怀疑的是就是CMSpȝ。因为出问题的那个WAS上它 占去?0Q的负荷Q我们有多台AIX、WAS服务器)。该CMS庞大Q感觉著名的赛_|就用它Q当时该CMS厂商l我们部|都׃快一个月。所以再 重新部v一套测试环境也挺困难。另外,CMS提供商不llisence。现在测试,客户早就Ҏ们恼火了Q当然不怎么配合Q这Ҏ们工作的开展就有很大的 挑战?/font></p> <p><font size="2">    在大致可以确定万无一q情况下,我们最l决定在客户的真实环境下试。也是让JProfiler的agent端直接在WAS的JVM里面启动Q北京IDCQ,然后q程Q大q)监控?<br>? 来该模式在另外几个应用的试都通过了(因ؓ北京IDC那边好几台AIX服务器)。但一部v上,客户的一些编辑用CMS时就感觉慢,管我们用了 JProfiler的最负载模式。半个小时后Q客户实在无法忍受,打电话过来,又把我们部长和经理训了一,q要写书面报告。我们被q马׃止测试,? 复现场?/font></p> <p><font size="2">    虽然JProfiler也支持客户那边的环境Q但q是有bugQ至负载一高就有严重的性能问题Q几乎导致系l挂Pq是我当时没有料到的? JProfiler一启动QWAS的启动时间就由原来的3分钟降到10分钟Q而且pȝ响应明显变慢Q我们具体的环境如下Q排列组合恐怕不?0U)Q?<br>1、AIX5.3QPower PC64位(不是32位) <br>2、WebSphere6.0 <br>3、IBM JVM1.42 <br>4、Remote 模式</font></p> <p><font size="2">    我后来仔l读了一下JProfiler的changeLogQ发现对上面的环境支持不够也很正常,因ؓ官方在最q的4.3.x版本下陆l有对IBM JVM和Websphere6.0的features和bug fixQ?/font><a target="blank"><font size="2">http://www.ej-technologies.com/download/jprofiler/changelog.html</font></a><font size="2"> </font></p> <p><font size="2">    q行到这一步,我忽然觉得无计可施了<img src="http://www.javaeye.com/images/forum/smiles/icon_sad.gif" alt=""> Q此时已l过了三周?<br>上面的策略,我认为是很正l的处理Ҏ。谁怪我们当初项目上U时没有q行充分的测试呢Q其实,q类试没做也正常,OOMq类问题谁都无法预测?/font></p> <p><font size="2">到这个时候,我想肯定有h会问我?你知道导致JVM的OOM有几U情况吗Q在当时Q我惛_了以下五U: <br>1、JVM的heap最、最大值没有设Q或不合理?<br>2、JVM的maxPermSize没有讄Q这个IBM的JVM没有Q一讄JVMpv不来Q?<br>对于Sun和BEA的JVMQ以上两U参数设|,可以排除90Q以上的非程序内存溢出导致的OOM?<br>3、程序内存泄?<br>4、有的JVMQ当?0%的CPU旉内,不能GC?%的heapӞ也发生OOMQIBM的JVM是Q但我没有验证) <br>5、JVM本n内存泄漏QJVM有bug不是不可能)</font></p> <p><font size="2">    现在的难题是Q如果是那个可怕的CMSE序本n有内存溢出,在品环境下Q我们怎么去验证?我们自己开发的10来个web应用Q测试ƈ不是很难Q在公司? 试都可以。但是,我现在最惌决的Q就是CMS试的问题。而且Q在我们那种环境下,该CMS产品供应商ƈ没有透露成功案例?/font></p> <p><font size="2">其实Q最后发玎ͼq不是内存泄漏造成的,因ؓ我们的heap走势都很q稳。纳L是,?000M的heapQ每ơ在heap只被占用400来M时就发生OOMQ没有Q何预兆。大家猜猜,会是什么原?img src="http://www.javaeye.com/images/forum/smiles/icon_rolleyes.gif" alt=""> Q这个问题我到后面相关章节再说吧?/font></p> <p><font size="2">既然我们所有的矛头都指向那个可怕的CMSpȝQ现在就是考虑隔离的问题。如果我们验证这个问题是CMS造成的, 那么大部分责d应该由CMS厂商承担<img src="http://www.javaeye.com/images/forum/smiles/icon_wink.gif" alt=""> ?<br>既然CMS我们不敢U(费劲Q而且客户在正式用Q,那我q我们开发的10来个webpȝ吧?/font></p> <p><font size="2"><strong>三、移出除CMSpȝ以外的所有应?/strong> <br>说v来容易啊Q做呢? 隔离Q移动)工作由我负责Q具体涉及到10来个相关负责人?<br>转移工作Q必d理好很多问题Q就说几个印象最q吧: <br>1、某些应用,如Blog和BBSQ都涉及到文件、图片上传目录和产品本n的环境,?JDBCq接池、Cache位置?<br>2、目标服务器本n的环境,WAS安装环境、网l等?<br>3、移植时的先后顺序、调度,各应用内部本w的U束关系?<br>4、移植后的测试?<br>当然Q还有一个最严峻的问题,客户允许我们q么做吗Q对它们目前q行的系l有多大影响Q风险如何评伎ͼ</font></p> <p><font size="2">    q个工作持箋了一天,已经完成?0Q的工作Q到W二天,客户又恼火了QWAS又宕Z?<br>Z 么?q确实是WAS的一个bugQWAS的后台随便一操作Qheap׃H然上升几百MQ导致JVM内存不够。不qWAS撑住的话Q过半小时后׃降下 来,我估计是WAS后台对用h作状态、文仉~存到Session里面。你们可以检查类DL一个文件夹Qd:\IBM\WebSphere\ AppServer\profiles\AppSrv01\wstempQ我不知道ؓ什么WAS不主动去清除它,它偷L׃升到几个GQ系l硬盘可能不 久就后就会空间不IWAS莫名q缓、最后死掉。听qWAS6.0以前q个目录更夸张。大家见我附件的截图WAS_Console.png那个峰?/font></p> <p><font size="2">咋办Q经理也已经不敢让我们l铤而走险了。这个方案最l又以失败告l?img src="http://www.javaeye.com/images/forum/smiles/icon_sad.gif" alt=""> ?/font></p> <p><font size="2">    不过Q最后我们还是发现问题出在CMS上。我们以前把q个问题向CMS技术支持反映,有大量依据和现象Qƈ且把相关日志都给它们。过了两天,他们最后竟然只回了一句话“从给我的两个日志来看Q没有找CQ何与XXX有关的东?...”。TMDQ我真的很生?img src="http://www.javaeye.com/images/forum/smiles/icon_twisted.gif" alt=""> Q它们的产品都折我们半q之久了。不q,看他们对IBM的WAS和JVM也不懂,我也׃惛_说什么了。下面是我的邮gQ公司机密部分都隐去了:</font></p> <div id="0ueemwe" class="quote_title"><font size="2">引用</font></div> <div id="2ekcmu4" class="quote_div"><font size="2">    附g是我们这D|间服务器宕机的日志。我们用IBM Pattern Modeling and Analysis Tool for Java Garbage Collector Version 1.3.2分析了一下虚拟机日志Q没有发现是内存泄漏DQ用IBM HeapAnalyzer Version 1.4.4 分析heap文gQ也没有发现很可疑的内存泄漏?<br><br>    我想以前你们也这样做q,现在我们分析错误日志Q发现有一个现象,在宕机时QL找不到文Ӟ我看是Websphere或是AIX IO资源不够Q不知道是什么导致的。但是,我们自己的应用,基本上没有什么IOQ除了一ơload几个配置文g。不q,我觉得你们WCM的IO操作挺多 的,不知道你Ҏ志有什么新的发现?<br>客观的说Q这几个月来Q宕机那台服务器Q除了你们的XXXQ就以论坛和blogZQ而且他们都是开源的。在频繁宕机?6q?1月䆾Q我们的论坛和blogq没有上Uѝ现在我们不得不每天晚上11点定旉启,但这也不是长久之计?<br>现在Q我们进行分遇到很大阻力,原来x你们的XXX单独分离出来Q在当前的环境下Q不是很现实Q如安装、测试(负蝲、定时服务)Q所以现在分L们自q应用Q但当前在品环境下Q客hd也很大?<br>希望快能够得到你们的问题徏议和Ҏ?/font></div> <p><font size="2">    文中说到了IBM的两个分析工Pq也是我们后来的救星Q我们就是需要这U?strong>ȝ分析</strong>工具Q因?strong>实时?/strong>已经证明不现实。但我始l对该分析出来的l果抱怀疑态度Q直到我L入IBM的JVM以及和IBM的技术支持交?.....</font></p> <p><font size="2">x花明?img src="http://www.javaeye.com/images/forum/smiles/icon_smile.gif" alt=""> Q至看C一点希望,不过最后我们还是失望而返?/font></p> <p><br></p> <p><strong><font size="2">四、用IBM的HeapAnalyzer和GarbageCollector?/font></strong></p> <p><font size="2">    扑ֈq两个工P已经是够费劲了,因ؓ以前扄IBM HeapRoot工具Q让我对q类工具很失望。而且Q这两个工具Q只有在IBM的Techinical Support|站能够搜烦刎ͼ但很不容易,因ؓ那两个工Pq不是象IBM的Websphere产品那样宣传Q它只在IBM Techinical Support文章的某些角落里出现。要知道QTechinical Support是IBM很重要的收入来源Q这cL,他们q不会让你很L拿刎ͼ比vBEA WLS的支持网站dev2dev差远了?<br>具体 诊断l节我就不详qC。我认ؓQIBM的WAS或JVMZ性能和OOM问题Q这两个工具是最有效的,而且是离U分析工P比v那些实时Profiler 工具Q某些场合有l对的优势:譬如我们目前的品环境,你只能分析宕机后的日志,实时分析前面已经验证是不可行的?<br>从日志分析,我们最l得出结论,我们购买的CMSpȝ有严重的片Q大对象Q问题,而该问题是OOM的罪祸首,而且IBM工程师也得出了同一l论。不q,在v先我们得一l论一周后Q我q始l不怿heap片会导致OOMQ直到IBM工程师L向我?/font></p> <p><font size="2">    我想很多Z是不太相信,因ؓ大多Ch用的都是Sun的JVMQ譬如Windows、Solaris上的hotspot。而且QSun JVM出问题,如果是配|的问题Q一般通过配置heap最大最|以及maxPermSize都可以解冟뀂Heap片D的OOMQ只有BEA? JRockit和IBM JVM上发生,不过JRockit有专门文说明,而且很容易找刎ͼ在jdk的文里面)?/font></p> <p><font size="2"><strong>    配置heap最最大?/strong>Q我惛_多数人都有经验。对于Sun的JVM? _一般可以设|heap最大最g_也是推荐的做法。因为它的GC{略默认是复制、分代算法。也是_它会heap分成不同的几个区Q譬? Solaris JVM中最上面有两个大相{的区。GC时刻Q将一个区的存zd象复制到另外一个对{区Q垃圑֯象就遗弃了。这样在heap里面Q就不存在碎片问题。另 外,ҎJava对象的存zL不同Q将之{Ud不同的区QTenured区)Q存zL长的在最底部Q火车算法)Q这也就是分代模型。具体请参考官Ҏ:</font><a target="blank"><font size="2">http://java.sun.com/docs/hotspot/gc1.4.2/</font></a><font size="2"> </font></p> <p><font size="2"><strong>    对于maxPermSizeQPermanent GenerationQ,</strong>主要和那些加载到JVM里面的Java Class对象相关Q它的空间不是在Java Heap里面分配。如果你当前的heap?000MQpermSize?00MQ那么JVM臛_占用1200M?<br>? q个I间内的对象的生存期和JVM是一LQ譬如JDK的核心类库,它们被System Classloader加蝲到JVM的Method AreaQ方法区Q后Q就不会被GC掉的Q这些对象一般是Class对象Q而不是普通的实例对象Q也是JVM的元数据。我们在用反时l常用到它们。所 以,对于现在象Spring、Hibernateq些框架l常通过反射创徏实例Q可能对maxPermSize要求大了,~省?4M很多时候是不够 的,特别是对于应用服务器里的应用Q象JSP׃产生和加载很多classes。不q,如果是它D的OOMQ一般会有类?perm size提示?/font></p> <p><font size="2">    但是Q对于IBM的JVMQ情况就完全不一栗它的默认GC{略q没有采取复制、分代。这个可以从GC日志分析出来。它不像Sun的JVM那样Q有个单? 的方法区Q它的方法区放在Java Heap里面。JVM规范里面q没有要求方法区的必d攄位置Q因为它只是一个JVM实现问题?/font></p> <p><font size="2">    在IBM的JVM里面Q这些对象一般分配在UCؓk-cluster和p-cluster里(cluster又是属于HeapQ,而后者一般是临时? heap里面甌。ƈ且,q些cluster是不能GCQ或是被Ud重排的(Compactq程Q。这导致Java Heap里面如同马蜂窝Q但不同的蜂孔又不能合ƈQ于是,当我们程序里面生一个大对象Q譬?M的数l?数组必须分配在连l的内存?Ӟ没有可? 配空间了Q于是就报告OOM。这些不能被Ud的clusterq为所谓的片。此ӞJVM的Heap利用率可能不?0%?<br>当然Q通过一定时期的GC日志Q可以计出cluster的合理大(专门在Java Heap的底部)Q另外,q可以ؓq些大对象专门分配大对象区的Q超q?4k的对象)?/font></p> <p><font size="2">    通过上面的理Zl,我想大家一定知道了Z么IBM的JVM里面不推荐heap的最大最值相同,因ؓq样片问题会非怸重:如果我们每次大对象申? 内存Ӟheap都扩?%Q譬?0MQ碎片问题很大程度上可以避开Q程序性能也高些(L可用I隙和分配耗时Q以及每ơGC旉拉长Q?<br>以上的具体阐qͼ请参考我在上文推荐的几个URLQ另外再推荐三个宝贵的链接: <br></font><a target="blank"><font size="2">http://www-1.ibm.com/support/docview.wss?rs=180&context=SSEQTP&q1=fragmentation&uid=swg21176363&loc=en_US&cs=utf-8&lang=en</font></a><font size="2"> <br></font><a target="blank"><font size="2">http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2447476A10000</font></a><font size="2">QIBM 技术支持告诉我的,太重要了Q) <br></font><a target="blank"><font size="2">http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=2847476B08000</font></a></p> <p><font size="2">    我想大家应该会问Q?strong>我怎么能够肯定我的OOM问题是heap片造成的呢</strong>Q下面的Ҏ可以验证?<br>在OOM 发生ӞJVM会生一个heapdump文g。然后用GarbageCollector分析OOM发生时刻QJVMȝLI间Q譬如约235k? 此时Q你再用HeapAnalyzerd析此时的heap快照里面的gap size大小Q空隙大)和各自的可用数目。你会发玎ͼ大于235k的空隙个Cؓ0。这是片DOOM的证据?/font></p> <p><font size="2">另外Q有Z问:<strong>我怀疑我的OOM是因为程序内存泄漏造成的,怎么去验?/strong>Q?/font></p> <p><font size="2">    你可以用HeapAnalyzer分析发生OOM时刻的heap快照Q工具会|列出哪些对象怀疑有内存泄漏Q譬如Cache对象都非常大Q但你可以确定它 不是内存泄漏Q。另外,分析q次宕机Q从q次虚拟机启动到宕机q段旉Q的heap走势Q如果曲U明显是向上倾斜Q也是那种典型的内存泄漏图Q就有可? 是内存泄漏。当Ӟq必ȝ合heap快照?<br>内存持箋上升在JVM开始一D|间很正常Q因为JVM对第一ơ访问到的Class 对象Q譬如一个典型的Web应用Q就有jdk的class、Spring或Hibernate的class对象Q它们都会被~存下来 (ClassLoader原理)Q一般均不会被GC。当大多数class对象~存差不多(当然q可能有一些Singleton对象Q不q不怎么占分量)Q? JVM的Heap^E了Q呈一水^波浪或锯齿线?<br>如果可以用JProfilerq类工具实时监控Q就更容易确诊了?/font></p> <p><font size="2">l过一番周折,我们l于看到了一U希望了<img src="http://www.javaeye.com/images/forum/smiles/icon_smile.gif" alt=""> ?/font></p> <p><font size="2">    在一定的准备后,我们军_对WASq行性能调优了。WAS的调优参敎ͼ可以分ؓ两个部分QJVMU别和WASU别Q?<br>JVMQ主要是GC和Heap?<br>WASQThread PoolQJDBC DataSource?<br>当然要调节,你需要明白你的目标是什么,调节依据是什么,怎么计算Q绝对不是凭I想象的Q譬如heap最?024MQ日志证明,该参数非怸适合我们的环境。具体细节,留给后文吧?/font></p> <p><font size="2">战战兢兢圎ͼ中午12:00Q我们给产品环境下的WAS调节参数、重启,同时优化了AIX的IO相关参数?/font></p> <p><font size="2">    我试着讄了一下JVM的k-cluster和p-cluster。下?5:00左右QWAS挂了QAIX也挂了。这下麻烦可大了。我们都慌了Q马山客 L老d来电话了Q一阵哗哗啦啦。实在无奈,让客户那边工作h员通知机房Q服务器托管处)工作人员重启AIX。我也不得不更改刚才的参敎ͼ立即设ؓ 另外一个倹{?<br>其实Q我把那个两个cluster值确实设|太大了Q我把它们设|ؓ推荐值的5倍,譬如p-cluster?5k×110%×5。另外一个愚蠢的讄是把最heap讄?048M(AIX?G内存)?<br>后来我恢复到U正常的|也就是去掉那个cluster?Q另外分配了一?0%的大对象区(如果1000M的heapQ就?00MQ?00MQ?/font></p> <p><font size="2">pPpȝ持箋正常q行了三天,以前可是一天一down。当在三天后再次宕机Ӟ我们都没有自信了<img src="http://www.javaeye.com/images/forum/smiles/icon_evil.gif" alt=""> 。不得不通过AIX的cronQl每天深?1点的WAS定时重启?<br>不过Q那ơ宕机,包括以后的几ơ宕机,<strong>再也没有出现OOM错误?/strong>Q但pȝ依然不稳定。虽然我可以说OOM问题解决了,但领导和客户需要的q不是这U结果?/font></p> <p><font size="2">其实Q在q个时候,我们已经发现我们pȝ的四大问题: <br>1、WAS和JVM参数QOOM问题 <br>2、AIX的IO和Paging Spacing不QAIX日志后来昄错误 <br>3、AIX的WAS分区I间不够QWAS的日志膨胀一周就把那个opt分区塞满了?<br>4、应用程序的JDBCq接池:我们20来个应用Q一?0 connectionsQDB2数据库有时被撑死?/font></p> <p><font size="2">也就是说Q我们最初在客户那儿部vӞ用的默认值根本不行。而且Q部|涉及多人,人员之间出现断层。如果我们只是按OOMQ无疑是走入死胡同,必须全局考虑Q?<br>? 是,目l实力薄弱,公司范围内就没有对AIX_N的。不q项目组原来有一个搞银行pȝQ在AIX下开发,׃熟悉些。我当时对AIX也比较陌生,你们? Linux转到AIXQ你q道它有多别扭了。命令都自定一套(也许因ؓ是Unix元老吧Q,那个shell也超U别扭,而且参考书特少。不是自诩,我两 q前负责一个高负蝲的Linux服务器管理一q多Q也是玩得很转的?/font></p> <p><font size="2">pP他负责AIX的相关问题,我负责WAS相关的?<br>但是Q现实环境,已经不允许我们再试验下去?img src="http://www.javaeye.com/images/forum/smiles/icon_sad.gif" alt=""> 。我们必LC条绝对可靠的对策Q?<br>q就是下文的CMSpȝ大迁U,服务器再ơ优化?/font></p> <p><br></p> <p><font size="2"><strong>五、隔CMSpȝQ服务器优化</strong> <br>    从前面的介绍Q大家应该记得,我们开始是固定CMSQ分d它应用,但遭遇失败。现在是反过来,q脆把CMSpȝ赶出WASq_<img src="http://www.javaeye.com/images/forum/smiles/icon_question.gif" alt=""> ?/font></p> <p><font size="2">说实话,目l理做这个决定,我认为已l是鼓出很大勇气?img src="http://www.javaeye.com/images/forum/smiles/icon_idea.gif" alt=""> ?/font></p> <p><font size="2">    当时我们惛_一个备用AIXZ安装CMS产品试Q但最后还是没有做成: <br>CMSq类文章发布pȝ很难安装Q也不好试Q又没有liscenceQ而且q有一堆准备工作。绝Ҏ有著名的openCMS安装那么单,当然功能q远比它复杂。而且Q我们当时也低估了后来的工作Q总觉得问题好解决?/font></p> <p><font size="2">    在很遥远?6q中期,CMS厂商在客户那边一台AIX的Tomcat上部|了一套CMS产品。但当时客户执意要求其跑在WAS上,也就是现在的情况? 最开始,客户q要求我们必ȝWAS的集?我们买的是WAS的ND?Q无奈该CMS不支持。要是集,又是M一遍。其实,现在xQ我们当时太? 动,CMSq种东西Q就供公司的几十个编辑用Q一个普通Tomcat完全够用。而且Q把它和面向公网的Internet应用混在一P完全没有必要。也 许,被动是因为我的实力造成的?/font></p> <p><font size="2">我们军_背水一战时Q已l做q周密的计划Q某q某月某日晚?:00...... <br>CMS产品负责人现场切?<br>xxQ我Q负责WAS相关参数调整 <br>yy负责AIX参数?<br>zz负责应用的测?<br>…..</font></p> <p><font size="2">MQ该行动涉及到客h、品提供商、公叔R层、项目组。每个h都密切关注,不下20人。每个h都守在电脑前Q随时听候调遣,当天晚上Q我们都没有准备回家睡觉Q大安心协力?/font></p> <p><font size="2">真没惛_Q整个式切换工作Q一个小时就利完成<img src="http://www.javaeye.com/images/forum/smiles/icon_surprised.gif" alt=""> Q第二天Q客L辑打开览器,她们一定想不到昨晚大家准备l历一场厮杀….</font></p> <p><font size="2">pȝ持箋q稳地运行了一周,然后是O长的五一Q我回湖北黄冈老家休息了八天。回来时Q一切依旧?/font></p> <p><font size="2">当天晚上Q我们这边主要做了两工作: <br>1、JVM的Heap参数Q共五个?<br>2、AIX的IO、Paging Space{共六个?<br>当然q有其他人的工作Q譬如测试、监控?/font></p> <p><font size="2">    q有一个非帔R要的斚wQJDBCq接池。我们原来是在每个Web应用里面独立讄Q这?0来个应用有几百个DBq接Q一不小心DBq撑死。现在统 一交由WAS内置DataSource处理Qdq接不到30个。其实,我们目开始部|时Q就是这样做的,但当时WAS内置的DataSource? JTA(XA)支持有bug Q这个和IBM技术支持确认过Q但他们没有l予很好的解x案)Q不qDatasourceq是配好的?/font></p> <p><font size="2">    但是q个工作已经属于WAS性能优化的主题了Q而且优化值必Ll观察一D|_通过专门的分析工h计算?<br>优化本nQ是一很考验人的工作Q我q单说一下最实用Ҏ吧,也许是专门针对IBM的品?<br>1、清理归零WAS日志。然后启动WASQ生成日志(-verbose:gc默认是开的) <br>2、让WAS持箋q行U两周,让JVM Heap占用曲线q稳一D|间即可(用IBM的Garbage Collector分析观察Q?<br>3? 在AIX的shell里,产生heapdump.phd文gQ也是heap快照。命令:kill -3 pid (pid是WAS的PIDQ通过ps –ef查看)Q观察heap当时的碎片情况,是否需要单独分大对象区Q一般不需要设|)Q特别是那个Ҏ区Class对象大小Qp-cluster? 敎ͼ?<br>4、通过GC工具Q观察GCq_旉、Heap实际占用情况。Note: GC是一个Stop The Worldq程Q也是说GC时系l对外不响应Q多CPU也不例外。看你的应用实际需求了QGC持箋旉和频率是矛盾的,另外q有性能考虑。一般Web? 用,我想让GC持箋旉QPause timeQ调节到合理值就ok了,譬如0.2?.4s?<br>5、根?可以出k-cluster|它是工具推荐值的110%?<br>6、Heap的最值是E序刚启动不久的占用|譬如320M。切讎ͼIBM JVM初始值太大非怸好?<br>7? Heap的最大值是pȝq稳后的100/70。也是说如果最大值是1000MQ那么应该^Ex?00MQ还?0%的空余。IBM的JVM默认情下? 片问题QWAS控制C操作Heap猛增q种bugQ你不得不堤阌ӀHeap最大g设,AIX下的WAS肯定OOM?/font></p> <p><font size="2">当然啦,我没有考虑到大对象区的计算Q虽然我们的应用讄了专门的大对象区Q,包括IBM JVM支持的分代GC、ƈ行GCQHeap每次expand癑ֈ比等。那些情冉|们一般不常用Q譬如,你的AIXq_一般不?6CPU吧?</font></p> <p><font size="2">一口气写到现在Q我忽然觉得该收了。下面就说说我对q类工作的整体看法吧?<br>1、尽量在目试和试q行的时候就q行压力、性能试Q当正式投入使用后,如果发现cM问题Q代价非常大。躲q算你运气好Q一般来_可能你们pȝ没多h用,也不是核心业务系l,譬如一般的电子政务?<br>2、千万不要低C技术风险,用IBM的系列品尤其要慎重Q出问题一定不要忘了技术支持。而且Q查资料Ӟ用google EnglishQ因WebSphereq类问题Q很有中文资料?<br>3、程序部|环境徏立时Q就要考虑到日后的正式环境Q譬如AIX的Paging Space、IO、分区大,默认值往往是不行的Q而且在品环境下改这些|往往非常难?<br>4? 在项目开发初期,p虑到日志的问题Q因为它分散到每个方法内Q必L重定义好debug、info、warn、errorU别Q不要随便忽视异? Qcatch里面不记录)Q到真正E序出问题时Q它是我们的最重要的依据之一。当然这主要是功能性问题诊断。另外对于高负蝲|站Q日志文件往往非常大, 各别日志千万不要؜在一P否则N题就很困难了?<br>5、怎么说呢Q别L技术,以ؓ什么都可以通过技术解冟뀂你看我们最大的问题是? CMSl移到Tomcat下。你要是问我Qؓ什么CMS产品会导致系l这么多的问题,我也不知道,到那时候,我确实也不想深入。我只要知道Q赶Zq个? 用,我的pȝ好控制多了。而且Q那个CMSpȝQ在Tomcat下,是跑得服服帖帖的,非常E_。难度是可恶的WASQ不q那CMSQ据IBM工程 师,包括我们二次开发,都觉得够烂了Q每个jsp面都打开、关闭DB connectionQ?q前的jsp开发模式)Q还有那么严重的大对象问题?/font></p> <p><font size="2">    好了Q以上ȝ的几点可能也不充分、深入,但如果你仔细Lq篇文章Q应该有自己的想法。毕竟,只有l过思考的东西Q才会属于自己?/font></p> </div><img src ="http://www.tkk7.com/sutao/aggbug/134085.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/sutao/" target="_blank">苏醄</a> 2007-08-02 18:04 <a href="http://www.tkk7.com/sutao/articles/134085.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://350725.com" target="_blank">kkk4444߹ۿ</a>| <a href="http://222941.com" target="_blank">120Ů̬Ƶ</a>| <a href="http://q2c6.com" target="_blank">ľþþƷ1</a>| <a href="http://zddzbp.com" target="_blank">ɫƵ</a>| <a href="http://see01.com" target="_blank">Ƶһ</a>| <a href="http://cc88899.com" target="_blank">ƷƵ׽Ƶ</a>| <a href="http://sdzsx.com" target="_blank">Ů˽Ƶ</a>| <a href="http://664403.com" target="_blank">ձ</a>| <a href="http://yule4.com" target="_blank">޳ɫӰԺ</a>| <a href="http://xmjcjc.com" target="_blank">AVƬ߹ۿ</a>| <a href="http://vvihh.com" target="_blank">ѹۿ</a>| <a href="http://yeshenghuowang.com" target="_blank">߾ѹۿ</a>| <a href="http://baizhengsh.com" target="_blank">aëƬëƬѹۿ</a>| <a href="http://liulaogendawutai.com" target="_blank">㽶Ƶһ</a>| <a href="http://whdysdt.com" target="_blank">޾ƷaĻ</a>| <a href="http://6000cpkj.com" target="_blank">쾫Ʒ߹ۿ</a>| <a href="http://bjbf99.com" target="_blank">޹ƷþSM</a>| <a href="http://cc88899.com" target="_blank">߾ƷһС˵</a>| <a href="http://sxhnyl.com" target="_blank">޹Ʒһ</a>| <a href="http://qq2071.com" target="_blank">ԲľƷƵѿ</a>| <a href="http://milbolg.com" target="_blank">Ƶ߹ۿַ</a>| <a href="http://6969aaa.com" target="_blank">¸Ļ </a>| <a href="http://chinahongfeng.com" target="_blank">ƷѾþþþþþ</a>| <a href="http://szzrjk.com" target="_blank">ҳ߹ۿ</a>| <a href="http://xsxdsb.com" target="_blank">պŷƵ</a>| <a href="http://10242016.com" target="_blank">hƵѸ߹ۿ</a>| <a href="http://14743592.com" target="_blank">ҰƵ߹1</a>| <a href="http://89895cc.com" target="_blank">vavava</a>| <a href="http://yg1617.com" target="_blank">Ůwwwһ</a>| <a href="http://1111xxxx.com" target="_blank">һ245699</a>| <a href="http://bii59.com" target="_blank">޾Ʒ91</a>| <a href="http://wangdei.com" target="_blank">ŷ޹Ʒ㽶</a>| <a href="http://345504.com" target="_blank">þAV</a>| <a href="http://szmazida.com" target="_blank">վ߲</a>| <a href="http://jdwx58.com" target="_blank">һ</a>| <a href="http://1880531.com" target="_blank">˾þô߽</a>| <a href="http://doubiseo.com" target="_blank">91Ƶ߹ۿ</a>| <a href="http://7299jj.com" target="_blank">99999þþþþ</a>| <a href="http://1314c.com" target="_blank">պ</a>| <a href="http://9qwx.com" target="_blank">޳츾߳XXXXX </a>| <a href="http://sdkjkj.com" target="_blank">ձvƬһ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>