﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-HERE WE GO!!!-随笔分类-weblogic+structs</title><link>http://www.cnitblog.com/xiaoyaocao/category/877.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Sep 2011 15:46:30 GMT</lastBuildDate><pubDate>Tue, 27 Sep 2011 15:46:30 GMT</pubDate><ttl>60</ttl><item><title>JSP数据库连接池的必要性</title><link>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/30/3002.html</link><dc:creator>逍遥草</dc:creator><author>逍遥草</author><pubDate>Fri, 30 Sep 2005 09:52:00 GMT</pubDate><guid>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/30/3002.html</guid><wfw:comment>http://www.cnitblog.com/xiaoyaocao/comments/3002.html</wfw:comment><comments>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/30/3002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xiaoyaocao/comments/commentRss/3002.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xiaoyaocao/services/trackbacks/3002.html</trackback:ping><description><![CDATA[一般情况下，在使用开发基于<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>的WEB程序时，传统的模式基本是按以下步骤：<BR>　　1． 在主程序（如Servlet、Beans）中建立<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接。 <BR>　　2． 进行SQL操作，取出数据。<BR>　　3． 断开<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接。<BR>　　使用这种模式开发，存在很多问题。首先，我们要为每一次WEB请求（例如察看某一篇文章的内容）建立一次<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接，对于一次或几次操作来讲，或许你觉察不到系统的开销，但是，对于WEB程序来讲，即使在某一较短的时间段内，其操作请求数也远远不是一两次，而是数十上百次（想想全世界的网友都有可能在您的网页上查找资料），在这种情况下，系统开销是相当大的。事实上，在一个基于<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>的WEB系统中，建立<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接的操作将是系统中代价最大的操作之一。很多时候，可能您的网站速度瓶颈就在于此。<BR>　　其次，使用传统的模式，你必须去管理每一个连接，确保他们能被正确关闭，如果出现程序异常而导致某些连接未能关闭，将导致<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>系统中的内存泄露，最终我们将不得不重启<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>。<BR>　　针对以上问题，我们首先想到可以采用一个全局的Connection对象，创建后就不关闭，以后程序一直使用它，这样就不存在每次创建、关闭连接的问题了。但是，同一个连接使用次数过多，将会导致连接的不稳定，进而会导致WEB SERVER的频频重启。故而，这种方法也不可取。实际上，我们可以使用连接池技术来解决上述问题。首先，介绍一下连接池技术的基本原理。顾名思义，连接池最基本的思想就是预先建立一些连接放置于内存对象中以备使用：　 　　　<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当程序中需要建立<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接时，只须从内存中取一个来用而不用新建。同样，使用完毕后，只需放回内存即可。而连接的建立、断开都有连接池自身来管理。同时，我们还可以通过设置连接池的参数来控制连接池中的连接数、每个连接的最大使用次数等等。通过使用连接池，将大大提高程序效率，同时，我们可以通过其自身的管理机制来监视<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接的数量、使用情况等。下面我们以一个名为ConnectionPool的连接池为例来看看连接池的实现。先看看ConnectionPool的基本属性：<BR>　　m_ConnectionPoolSize：连接池中连接数量下限<BR>　　m_ConnectionPoolMax：连接池中连接数量上限 <BR>　　m_ConnectionUseCount：一个连接的最大使用次数<BR>　　m_ConnectionTimeout：一个连接的最长空闲时间<BR>　　m_MaxConnections = -1：同一时间的最大连接数<BR>　　m_timer：定时器 <BR>　　这些属性定义了连接池与其中的每个连接的有效状态值。连接池的自我管理，实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。其管理流程如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们可以定义出ConnectionPool要完成管理所需要的基本接口： <BR>public class ConnectionPool implements TimerListener{<BR>　　public boolean initialize() //连接池初始化 <BR>　　public void destroy() //连接池的销毁 <BR>　　public synchronized java.sql.Connection getConnection() //取一个连接 <BR>　　public synchronized void close() //关闭一个连接 <BR>　　private synchronized void removeFromPool() //把一个连接从连接池中删除 <BR>　　private synchronized void fillPool() //维护连接池大小 <BR>　　public synchronized void TimerEvent() //定时器事件处理函数 <BR>} <BR>　　通过这几个接口，已经可以完成连接池的基本管理。在TimeEvent（）函数中完成连接池的状态检验工作，fillPool()时连接池至少保持最小连接数。因为我们要保存每一个连接的状态，所以还需要一个<SPAN class=unnamed8><FONT color=#0000ff>数据库</FONT></SPAN>连接对象： <BR>class ConnectionObject{<BR>　　public java.sql.Connection con; public boolean inUse; //是否被使用标志 <BR>　　public long lastAccess; //最近一次开始使用时间 <BR>　　public int useCount; //被使用次数<BR>}<BR>加入了ConnectionObject对象后，在ConnectionPool中操作的应该只是ConnectionObject,而其他进程需要的只是ConnectionObject的con属性，因此我们再加入一个类，作为其他进程获得与返回连接的接口： CLASS Conn{<BR>　　GetConnection(); //从连接池中取出一个有效连接 <BR>　　CloseConnection(); //返回连接，此时并没有关闭连接，只是放回了连接池 <BR>　　DestroyPool(); //销毁连接池 <BR>}<BR>　<BR>通过上面的介绍，我们可以看出，连接池技术的关键就是其自身的管理机制，以上的管理流程只是本人一点见解，关键是想向大家介绍一种思路，在此基础上，您可以进一步完善连接池技术为您所用。<BR><BR><BR>文章出处：<A href="http://www.vipcn.com/InfoView/Article_40881.html">http://www.vipcn.com/InfoView/Article_40881.html</A><img src ="http://www.cnitblog.com/xiaoyaocao/aggbug/3002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xiaoyaocao/" target="_blank">逍遥草</a> 2005-09-30 17:52 <a href="http://www.cnitblog.com/xiaoyaocao/archive/2005/09/30/3002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdbc性能优化</title><link>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2958.html</link><dc:creator>逍遥草</dc:creator><author>逍遥草</author><pubDate>Wed, 28 Sep 2005 14:13:00 GMT</pubDate><guid>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2958.html</guid><wfw:comment>http://www.cnitblog.com/xiaoyaocao/comments/2958.html</wfw:comment><comments>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2958.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xiaoyaocao/comments/commentRss/2958.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xiaoyaocao/services/trackbacks/2958.html</trackback:ping><description><![CDATA[<TABLE style="WORD-BREAK: break-all; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
<TBODY>
<TR>
<TD vAlign=top>jdbc程序的性能主要由两个因素决定,一是数据库本身的性质,另一个是与数据库相对独立的jdbc应用程序接口(api)的使用.这里说的是如何正确使用jdbc编程接口,以获得更好的性能. <BR>&nbsp;&nbsp;jdbc主要优化有: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.选择正确的jdbc驱动程序 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.Connention的优化&nbsp;&nbsp;使用连接池来管理Connection对象 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.Statement的优化&nbsp;&nbsp;&nbsp;使用批量更新等 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.Result的优化&nbsp;&nbsp;正确的从数据库中get数据等 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)选择正确的jdbc驱动程序: <BR>&nbsp;&nbsp;1&nbsp;jdbc-odbc&nbsp;桥 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;本地api-部分&nbsp;java驱动 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;jdbc网路协议-纯java驱动 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;jdbc本地协议 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最好选择&nbsp;jdbc网路协议-纯java驱动&nbsp;&nbsp;效率比较高&nbsp;&nbsp;但需要第三方软件的支持&nbsp;比如corba&nbsp;&nbsp;weblogic属于这种类型 <BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)优化Connection对象: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.设置适当的参数&nbsp;&nbsp;DriverManager.getConnection(String&nbsp;url,Properties&nbsp;props); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props=new&nbsp;Properties(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("user","wuwei"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("password","wuwei"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("defaultRowPrefectch","30"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("dufaultBatchValue","5"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con=DriverManager.getConnection("jdbc<IMG src="http://www.chinaunix.net/forum/images/smiles/icon_surprised.gif" border=0>racle:thin:@hostsString",props); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对象可以通过设置setDefaultRowPrefetch(int)&nbsp;和&nbsp;setDefaultBatchValue(int)&nbsp;两个参数类优化连接 <BR><BR>&nbsp;2.使用连接池&nbsp;&nbsp;可以自己写一个连接池&nbsp;这样程序的灵活性强,便于移植. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;apache项目开发了一套非常通用而表现非常稳定的对象池&nbsp;http://jakarta.apache.org/commons/pool.htm <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设计了自己的连接池后&nbsp;在客户端调用建立对象 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;makeObject()&nbsp;throws&nbsp;Exception{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;Class.forName("oracle.jdbc.driver.OracalDriver"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;DriverManager.getConnection("url","username","password"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;销毁对象时用 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;destroyObject(Object&nbsp;obj)&nbsp;throws&nbsp;Exception{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((Connection)obj.close()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意几点&nbsp;对象池里有没有回收机制,对象池里有机有容量限制,对象池里有多少个闲置对象(可以释放)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.控制事务的提交&nbsp;&nbsp;最好手动提交事务,不但可以可以保证数据原子性,而且对新能提高留下余地. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try{ <BR>&nbsp;&nbsp;&nbsp;connection.setAutoCommint(false); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;代码&nbsp;用PreparedStatement&nbsp;&nbsp;性能比Statementh好. <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.commit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.setAutoCommit(true); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch(SQLException&nbsp;e){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally{ <BR>&nbsp;&nbsp;&nbsp;//代码 <BR>&nbsp;&nbsp;&nbsp;if(connection!=null){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.close();&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR><BR>&nbsp;4.适当的选择事务的隔离级别&nbsp;&nbsp;&nbsp;TRANSACTION_READ_UNCOMMITED&nbsp;&nbsp;性能最高 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TRANSACTION_READ_COMMITED&nbsp;&nbsp;&nbsp;&nbsp;快 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TRANSACTION_REFEATABLE_READ&nbsp;&nbsp;中等 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RANSACTION_SERIALIZABLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;慢 <BR>&nbsp; <BR>&nbsp;&nbsp;&nbsp;(3)Statement&nbsp;优化 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jdbc3个接口用来处理sql的执行,是Statement&nbsp;PreparedStatement&nbsp;CallableStatement <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;提供适当的Statement接口&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;批量执行sql <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从数据库批量获取数据 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement&nbsp;比Statement性能要好&nbsp;主要体现在一个sql语句多次重复执行的情况 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatemnt只编译解析一次而Statement每次编译一次. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;批量修改数据库&nbsp;&nbsp;&nbsp; <BR>&nbsp;Statement&nbsp;提供了方法addBatch(String)和executeBatch() <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;调用方法为stmt.addBatch("isnert.....");&nbsp;stmt.addBatch("update.....") <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stmt.executeBatch(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;也可以用PreparedStatement从而更好的提高性能. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt=conn.preparedStatement("insert&nbsp;into&nbsp;test_table(......)&nbsp;values(....?)"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt.setString(1,"aaa"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt.addBatch(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt.setString(1,"bbb"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt.addBatch(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..... <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pstmt.executeBatch(); <BR>&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;批量地从数据库中取数据. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过setFetchSize()和getFectchSize()方法来设定和查看这个参数.这个参数对体统的性能影响比较大. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这个参数太小会严重地降低程序地性能. <BR>&nbsp;&nbsp;&nbsp;Connection&nbsp;Statement&nbsp;ResultSet都有这个参数,他们对性能地影响顺序是: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet---------Statement---------Connection <BR>&nbsp;&nbsp;(4)优化ResultSet. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;体现在以下几个方面 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;批量读取数据.合理设置ResultSet的getFetchSize()和setFetchSize()方法中的参数 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用正确的get和set方法 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用整数而不是字段名作为参数性能比较高, <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如&nbsp;setInt(1,100); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setString(2,"aaaa"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;比&nbsp;setInt("id","100"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setString("name","aaaa"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;性能好 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置适当的滚动方向.有3个方向FETCH_FORWORD,FETCH_REVERSE&nbsp;FETCH_UNKNOWN <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;单向滚动性能比较高. <BR>&nbsp;&nbsp;其他方面的性能优化 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;及时显示的关闭Connection&nbsp;Statement&nbsp;ResultSet <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其中Connection可以用Connetion&nbsp;Pool处理. <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用数据库系统的强大查询功能去组织数据.这样程序运行是和数据库服务的交互次数少,数据库返回给 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;程序的记录条数少的多,所以性能有很大的提高. <BR></TD></TR></TBODY></TABLE><img src ="http://www.cnitblog.com/xiaoyaocao/aggbug/2958.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xiaoyaocao/" target="_blank">逍遥草</a> 2005-09-28 22:13 <a href="http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2958.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用WLST监控WebLogic服务器</title><link>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2949.html</link><dc:creator>逍遥草</dc:creator><author>逍遥草</author><pubDate>Wed, 28 Sep 2005 10:49:00 GMT</pubDate><guid>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2949.html</guid><wfw:comment>http://www.cnitblog.com/xiaoyaocao/comments/2949.html</wfw:comment><comments>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xiaoyaocao/comments/commentRss/2949.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xiaoyaocao/services/trackbacks/2949.html</trackback:ping><description><![CDATA[脚本语言近来受到一些关注。随着Groovy和 Jython的到来，编写与Java合并的脚本比Ant更简单自然。一直以来使用XML来调用Java方法都是被迫的，这主要是因为在标记语言中解释流、条件表达式和自定义代码比较困难（虽然自Ant 1.5之后这一点有了较大的改进）。
<P>　　为什么用脚本语言呢？是这样的，如果我有完整的Java编程IDE，用Jython或是Groovy看起来就显得有些落伍了。虽然可以用较少行来编码（虽然不是少很多），但是我希望输入的编写能够自动化。我希望编译器在编码时告警，而且我需要分解。这需要Java IDE以外的插件。</P>
<P>　　但有时候没有完整的IDE配置。想一下要自动敏捷的工作，或者想一下服务器管理员。这些人没有任何像Eclipse之类的东西，而且他们的工作不可能事先完成。不可能为系统管理而编码。这就是像WLST这类工具产生的来由，它们使得世界更美好。</P>
<P>　　WebLogic 脚本工具（WLST，WebLogic Scripting Tool）是一个帮助编写远程管理和修改服务器安装脚本的Jython模块。它有两个版本：离线，它可以配置尚不存在的服务器实例，以及在线，它需要连接到一个WebLogic服务器。这两个版本都是Beta版而且文档很少，但是它们保证会改进并在将来的某个WebLogic版本中包含。</P>
<P>　　这里我们将专注于在线版本，因为它的功能比离线版本更为完整。</P>
<P><STRONG>使服务器配置自动化：</STRONG></P>
<P>　　让我们从难以对付的WebLogic服务器配置开始吧！典型的开发团队在几台主机上复制同样的配置，仅仅改变少量参数，如IP、主机名和TCP端口。在相对典型的项目中，必须对每个开发人员的PC、集成测试主机和生产主机，都要执行一遍这个过程。Ant任务对这个问题有很大帮助，但是它还没有准备好处理像定制JMX bean这类的事务。</P>
<P>　　我们将创建并装载服务器，配置它，然后关机，混合使用Ant和WLST。首先，让我们创建清单1中的服务器。为了简化，我们将在这里使用Ant任务，因为结合使用WLST离线和在线会使事情复杂化。 </P>
<P><STRONG>清单</STRONG><STRONG>1</STRONG></P>
<P>build.properties:</P>
<P>server=weblogic</P>
<P>weblogic.server.name=myserver</P>
<P>weblogic.domain.name=mydomain</P>
<P>weblogic.admin.username=weblogic</P>
<P>weblogic.admin.password=weblogic</P>
<P>weblogic.home=C:/bea</P>
<P>weblogic.lib.dir=/weblogic81/server/lib</P>
<P>weblogic.mbeantypes.dir=/mbeantypes</P>
<P>server.project.root.dir=/user_projects/domains/</P>
<P></P>
<P>server.deploy.dir=/applications</P>
<P>　　我检查了属性，因为在多于一个品牌的应用服务器上部署时，很容易使用错误的build.properties文件（参见清单2）。</P>
<P><STRONG>清单</STRONG><STRONG> 2</STRONG></P>
<P>build.xml:</P>
<P>[...]</P>
<P>&lt;path id="weblogic.classpath"&gt;</P>
<P>&lt;fileset dir=""&gt;</P>
<P>&lt;include name="weblogic.jar"/&gt;</P>
<P>&lt;/fileset&gt;</P>
<P>&lt;/path&gt;</P>
<P>&lt;target name="check-properties"&gt;</P>
<P>&lt;condition property="wlproperties.ok"&gt;</P>
<P>&lt;and&gt;</P>
<P>&lt;isset property="weblogic.server.name"/&gt;</P>
<P>&lt;isset property="weblogic.domain.name"/&gt;</P>
<P>&lt;isset property="weblogic.admin.username"/&gt;</P>
<P>&lt;isset property="weblogic.admin.password"/&gt;</P>
<P>&lt;/and&gt;</P>
<P>&lt;/condition&gt;</P>
<P>&lt;fail unless="wlproperties.ok"&gt;</P>
<P>Weblogic properties are missing. Double check build.properties.</P>
<P>&lt;/fail&gt;</P>
<P>&lt;fail&gt;</P>
<P>&lt;condition&gt;</P>
<P>&lt;not&gt;&lt;available file="/weblogic.jar"/&gt;&lt;/ not&gt;</P>
<P>&lt;/condition&gt;</P>
<P>Missing file /weblogic.jar</P>
<P>&lt;/fail&gt;</P>
<P>&lt;/target&gt;</P>
<P>&lt;target name="create-server" depends="check-properties"&gt;</P>
<P>&lt;taskdef name="wlserver" classname="weblogic.ant.taskdefs. management.WLServer"</P>
<P>classpathref="weblogic.classpath"/&gt;</P>
<P>&lt;echo&gt;Creating server at &lt;/echo&gt;</P>
<P>&lt;delete dir="" includeemptydirs="true" quiet="true"/&gt;</P>
<P>&lt;mkdir dir="" /&gt;</P>
<P>&lt;wlserver</P>
<P>dir=""</P>
<P>domainName=""</P>
<P>serverName=""</P>
<P>host=""</P>
<P>port=""</P>
<P>generateConfig="true"</P>
<P>productionModeEnabled="false"</P>
<P>weblogicHome="/weblogic81"</P>
<P>username=""</P>
<P>password=""</P>
<P>action="start"</P>
<P>&gt;</P>
<P>&lt;classpath refid="weblogic.classpath"/&gt;</P>
<P>&lt;/wlserver&gt;</P>
<P>　　我们刚刚删除了整个域目录，创建了一个新的、干净的目录，并让服务器运行，这样，在清单3中，我们可连接并配置它。 </P>
<P><STRONG>清单</STRONG><STRONG>3</STRONG></P>
<P>&lt;java classname="weblogic.WLST" fork="true" failOnError="true" dir="scripts/wlst"&gt;</P>
<P>&lt;classpath refid="weblogic.classpath"/&gt;</P>
<P>&lt;classpath&gt;</P>
<P>&lt;fileset dir="lib/wlst"&gt;</P>
<P>&lt;include name="*.jar"/&gt;</P>
<P>&lt;/fileset&gt;</P>
<P>&lt;/classpath&gt;</P>
<P>&lt;arg line="createAll.py" /&gt;</P>
<P>&lt;/java&gt;</P>
<P>&lt;wlserver</P>
<P>host=""</P>
<P>port=""</P>
<P>username=""</P>
<P>password=""</P>
<P>action="shutdown"</P>
<P>/&gt;</P>
<P>&lt;/target&gt;</P>
<P>　　停止服务器是必要的，因为有些设置改变了，如安全验证者，需要正常关机以保存到磁盘。省略这一步将会在Ant脚本结束处突然中止服务器。</P>
<P>　　注意：WLST任务有分叉，因此，如果WLST在脚本中发现了错误，Ant仍将会显示“成功编译”，从而会使得装载该脚本的人迷惑。</P>
<P>　　让我们将WLST脚本分成两个部份，这样在以后的管理任务中能尽可能多的重用它。我已经使用了包含在WLST包中的很棒的例子，并且将saveDomain()命令的输出作为起点。saveDomain()生成的脚本不是很完美，但是它能指出工具的可能性（参见清单4）。</P>
<P><STRONG>清单</STRONG><STRONG> 4</STRONG></P>
<P>createAll.py:</P>
<P>execfile("AdminTool.py")</P>
<P>admin.configureServer()</P>
<P>admin.createXaPool()</P>
<P>AdminTool.py:</P>
<P>from javax.management import InstanceNotFoundException</P>
<P># Python 2.4 will include booleans, but until then this is required</P>
<P>true = 1</P>
<P>false = 0</P>
<P>class AdminTool:</P>
<P>def __init__(self):</P>
<P>loadProperties("administration.properties")</P>
<P># Connects with a weblogic instance</P>
<P>def connect(self):</P>
<P>connect(username, password, "t3://" + host + ":" + port)</P>
<P>self.myServer = getTarget("/Server/" + serverName)</P>
<P># Server attributes that cannot be generated via ant</P>
<P>def configureServer(self):</P>
<P># Activates console DEBUG mode - I really like that</P>
<P>self.myServer.setStdoutSeverityLevel(64)</P>
<P>print "Configured server " + self.myServer.getName()</P>
<P># Creates a JDBC pool:</P>
<P>def createPool(self, poolName, driverName):</P>
<P>pool = create(poolName, "JDBCConnectionPool")</P>
<P>pool.setDriverName(driverName)</P>
<P>pool.setURL(dbURL)</P>
<P>pool.setPassword(dbPassword)</P>
<P>pool.setProperties(makePropertiesObject("user=" + dbUsername))</P>
<P>pool.setRemoveInfectedConnectionsEnabled(false)</P>
<P>pool.setTestConnectionsOnCreate(true)</P>
<P>pool.setTestTableName("SQL SELECT 1 FROM DUAL")</P>
<P># setTestFrecuencySeconds is not soported by WLST objects</P>
<P># so here is a workaround</P>
<P>cd(´/JDBCConnectionPool/´ + poolName)</P>
<P>set(´TestFrequencySeconds´, 300)</P>
<P>cd(´/´)</P>
<P>pool.addTarget(self.myServer)</P>
<P>def createXaPool(self):</P>
<P>self.createPool(MY_POOL_NAME, ´oracle.jdbc.xa.client.? OracleXADataSource´)</P>
<P># Removes an element if it exists</P>
<P>def removeIfExists(self, name, type):</P>
<P>try:</P>
<P>mbean = home.getAdminMBean(name, type)</P>
<P>home.deleteMBean(mbean)</P>
<P>print ´Removed the ´ + type + ´: ´ + name</P>
<P>except InstanceNotFoundException, e:</P>
<P>print "Cannot remove " + name + ",type=" + type + " because ? it does not exist"</P>
<P>def removeXaPool(self):</P>
<P>self.removeIfExists(MY_POOL_NAME, "JDBCConnectionPool")</P>
<P># The JDBC Connection Pool name</P>
<P>MY_POOL_NAME=´MyPool´</P>
<P># the instance we are going to use </P>
<P>admin = AdminTool()</P>
<P>admin.connect()</P>
<P>administration.properties</P>
<P>host=127.0.0.1</P>
<P>port=7001</P>
<P>username=weblogic</P>
<P>password=weblogic</P>
<P>dbURL=jdbc:oracle:thin::1521:DATABASE</P>
<P>dbUsername=foo</P>
<P>dbPassword=bar</P>
<P>　　LoadProperties任务将administration.properties文件中的所有项转换成Jython变量。我们已经使用了Jython类的第一个方法来管理WebLogic服务器实例。还可以轻易将它扩展到创建和删除DataSources，这是一个JMS环境，甚至还可以扩展到安全领域。</P>
<P><STRONG>MBean方法</STRONG></P>
<P>　　前面我们已经看到的是创建和配置MBeans的一个方法（下一节会解释另一种方法）。不利的一面是必须知道支持的属性和方法，而WLST没有这些文档。我怎么去猜哪个方法可用呢？</P>
<P>　　噢，我想到的第一个方法是到config.xml文件或是Web控制台去找，并假设属性名称未改变。如果有一个不错的IDE，我们还可以打开Mbean接口类看看那里有些什么（它和Mbean的名称一样，以“Mbean”结束）。这不会显示代码，但是可以查到哪个方法可用。</P>
<P>　　我喜欢连接到<A href="http://e-docs.bea.com/wls/docs81/javadocs/index.html" target=_blank>http://e-docs.bea.com/wls/docs81/javadocs/index.html</A>，查看weblogic.management.configuration包的内容。比如，如果我们找到ServerMBean类，就可以看到两个有趣的但是不太为人们所熟悉的方法isJDBCLoggingEnabled()和setJDBCLoggingEnabled()。我们可通过打开wlst交互shell来查看它们，如下所示：</P>
<P>wls:/mydomain/config&gt; server=home.getAdminMBean(´myserver´, ´Server´)<BR>wls:/mydomain/config&gt; server.setJDBCLoggingEnabled(1)<BR>wls:/mydomain/config&gt; server.isJDBCLoggingEnabled()<BR>1</P>
<P>　　（“home”是一个AdminMbeanHomeImpl类型的变量，可以像对任何其他Mbean一样研究；唯一的问题是因为它是一个内部类，所以没有javadoc可用。）</P>
<P>　　如果最后三个命令不好理解，不要担心。我们会在下一节介绍Shell。</P>
<P><STRONG>命令行系统管理</STRONG></P>
<P>　　系统管理员也可以通过使用交互式shell来手工管理WebLogic服务器实例。其优点是在试图修改系统配置时，不用事先知道Mbean接口。对这一部分，需要在classpath包含webLogic.jar、jython.jar以及wlst.jar，并启动主类weblogic.WLST，它是交互式控制台。</P>
<P>　　要记住这是Jython。引号和双引号用于字符串声明；实例化不需要新的运算符（事实上，这是一个语法错误）；不需要分号，因为每行用回车结束；而且不必声明变量（la Unix shell脚本）。如果这还不够，请参考Python和WLST的文档。</P>
<P>　　我们需要开始连接到WebLogic服务器的实例。我们可以选择使用之前编写的AdminTool脚本，或者手工连接： </P>
<P>execfile(´AdminTool.py´)<BR>admin.connect()</P>
<P>或</P>
<P>connect(´weblogic´, ´weblogic´, "t3://localhost:7001)</P>
<P>Connecting to weblogic server instance running at t3://127.0.0.1:7001 as<BR>username weblogic ...<BR></P>
<P>　　成功连接到属于“mydomain”域的Admin服务器“myserver”是系统输出，而且应采用编码的格式。</P>
<P>　　现在，我们可以开始好好玩一下了。对于WLST，JMX树可像UNIX文件系统一样进行遍历，在这里JMX Mbeans是目录而其属性是文件。在所有这些过程中要记住Python语法，并要记得WLST仍然不能分辨通配符。这就是为什么我们要省略大多数ls()输出的原因（参见清单5）。</P>
<P><STRONG>清单</STRONG><STRONG>5</STRONG></P>
<P>wls:/mydomain/config&gt; ls()</P>
<P>[...]</P>
<P>drw-JDBCConnectionPools</P>
<P>drw-JDBCDataSourceFactories</P>
<P>drw-JDBCDataSources</P>
<P>drw-JDBCMultiPools</P>
<P>drw-JDBCTxDataSources</P>
<P>[...]</P>
<P>wls:/mydomain/config&gt; cd(´JDBCConnectionPools´)</P>
<P>wls:/mydomain/config/JDBCConnectionPools&gt; ls()</P>
<P>drw-MyPool</P>
<P>wls:/mydomain/config/JDBCConnectionPools&gt; cd(´MyPool´)</P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; ls()</P>
<P>[...]</P>
<P>-rw-TestConnectionsOnCreatetrue</P>
<P>-rw-TestConnectionsOnReleasefalse</P>
<P>-rw-TestConnectionsOnReservefalse</P>
<P>-rw-TestFrequencySeconds300</P>
<P>-rw-TestStatementTimeout-1</P>
<P>-rw-TestTableNameSQL SELECT 1 FROM DUAL</P>
<P>-r--TypeJDBCConnectionPool</P>
<P>-rw-URLjdbc:oracle:thin::1521:DATABASE</P>
<P>[...]</P>
<P>　　我们还可以对于单个cd(´/JDBCConnectionPools/MyPool´)命令深入到这个地步。WLST永远记得cmo（当前管理对象，Current Managed Object），即与我们正在浏览的当前“文件夹”相关的Mbean。因此，从实际角度来看这些命令是相当的： </P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; cmo<BR>[Caching Stub]Proxy for mydomain:Name=MyPool,Type=JDBCConnectionPool<BR>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; pwd()<BR>´/JDBCConnectionPools/MyPool´</P>
<P>　　现在，让我们改变一些随机属性（参见清单6）。记住Python没有布尔属性。服务器可返回真或假（既然它运行Java），但是不能赋这些值。然而，不用担心；如果通过WebLogic控制台查看它，布尔值1得到了服务器的正确解释。</P>
<P><STRONG>清单</STRONG><STRONG> 6</STRONG></P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; set?(´TestFrequencySeconds´, 500)</P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; set(´TestConnectionsOnRelease´, 1)</P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; ls()</P>
<P>-rw-TestConnectionsOnCreatetrue</P>
<P>-rw-TestConnectionsOnRelease1</P>
<P>-rw-TestConnectionsOnReservefalse</P>
<P>-rw-TestFrequencySeconds500</P>
<P>-rw-TestStatementTimeout-1</P>
<P>-rw-TestTableNameSQL SELECT 1 FROM DUAL</P>
<P>-r-- TypeJDBCConnectionPool</P>
<P>-rw-URLjdbc:oracle:?thin::1521:DATABASE</P>
<P>[...]</P>
<P>wls:/mydomain/config/JDBCConnectionPools/MyPool&gt; get(´TestConnectionsOn?Release´)</P>
<P>1</P>
<P>　　使用前一节关于“使服务器配置自动化”中介绍的相当技术，也可能得到了同样的结果。我发现这个方法对于系统管理员更简单，而第一个方法对于开发人员准备脚本则更简单。这只是适应不同类型的工具集：系统管理员更习惯于Unix Shell，而开发人员对于的Java的“味道”则感觉更为舒服。</P>
<P><STRONG>管理服务器配置的例子：一个真实例子</STRONG></P>
<P>　　需要了解那些烦人的JDBC调用内部是一种常见现象。有时人们真的希望能够看见WebLogic服务器和数据库之间对话，为什么它会见鬼地返回0行，或者轮廓性能，OK。用热插拔功能记录JDBC调用（而不仅是SQL，拜托了，还要记录参数）应该不错。想试一下吗？</P>
<P>　　首先，让我们下载p6spy JDBC驱动程序。它是一个JDBC包，可以记录任何经过它的东西。要配置它，将p6spy.jar和包含p6spy.properties的目录放到服务器classpath目录下（不要忘了这个目录，否则WebLogic会报告JAR文件不存在）。按照需要调整p6spy.properties。</P>
<P>　　我们想要到达的目的是创建两个Connection Pool（连接池），一个直接用Oracle JDBC驱动程序而另一个通过p6spy。然后，我们将修改数据源指向p6spy数据源而不重启服务器（如果我们相信Web控制台接口，这个修改无需重启）。</P>
<P>　　我们将通过执行之前开发出的管理脚本来开始：</P>
<P>wls:/(offline)&gt; execfile(´AdminTool.py´)</P>
<P>Connecting to weblogic server instance running at t3://127.0.0.1:7001 as<BR>username weblogic ...</P>
<P>　　成功连接到属于“mydomain”域的Admin服务器“myserver”，它也是系统输出并且应正确格式化。</P>
<P>　　我们现在可以创建连接池了。</P>
<P>wls:/mydomain/config&gt; admin.createPool("P6SPY Connection Pool",<BR>"com.p6spy.engine.spy.P6SpyDriver")<BR>JDBCConnectionPool with name ´P6SPY Connection Pool´<BR>has been created successfully.</P>
<P>　　在WebLogic控制台我们可看到以下显示（WebLogic日志行将只在将“debug to console”选项启用时才会显示）： </P>
<P>&lt;28-feb-2005 20H18´ GMT&gt; &lt;Info&gt; &lt;JDBC&gt; &lt;BEA-001132&gt;<BR>&lt;Initialized statement cache of size "10"<BR>for connection in pool "P6SPY Connection Pool".&gt;<BR>1109621928226|0|1|statement|SELECT 1 FROM DUAL|SELECT 1 FROM DUAL<BR>1109621928242|0|1|statement|SELECT 1 FROM DUAL|SELECT 1 FROM DUAL</P>
<P>　　这显示连接池初始化以及新连接测试。我们将假设数据源还不存在。如果我们还清楚，应该已经预见到这一点并在AdminTool类创建了方法，但是，我们还是可通过清单7中所列的交互式shell来这么做。</P>
<P><STRONG>清单</STRONG><STRONG> 7</STRONG></P>
<P>wls:/mydomain/config&gt; datasource=create(´MyDS´, ´JDBCTxDataSource´)</P>
<P>JDBCTxDataSource with name ´MyDS´ has been created successfully.</P>
<P>wls:/mydomain/config&gt; datasource.setJNDIName("MyDS")</P>
<P>wls:/mydomain/config&gt; datasource.setPoolName("P6SPY Connection Pool")</P>
<P>wls:/mydomain/config&gt; datasource.setEnableTwoPhaseCommit(true)</P>
<P>wls:/mydomain/config&gt; datasource.addTarget(admin.myServer)</P>
<P>1</P>
<P>　　我们已经开始将数据源指向P6SPY连接池，因此，可以检查应用程序看看它真的记录了JDBC语句；用测试案例来尝试。现在，有两个方法可以禁止记录。既然在Jython变量中有数据源，我们就可以用“Java”的方式来做。</P>
<P>datasource.setPoolName(MY_POOL_NAME)</P>
<P>　　或者，采用如清单8所示的“system administrator”方法：</P>
<P><STRONG>清单</STRONG><STRONG>8</STRONG></P>
<P>wls:/mydomain/config&gt; cd (´JDBCTxDataSources´)</P>
<P>wls:/mydomain/config/JDBCTxDataSources&gt; ls()</P>
<P>drw-MyDS</P>
<P>wls:/mydomain/config/JDBCTxDataSources&gt; cd(´MyDS´)</P>
<P>wls:/mydomain/config/JDBCTxDataSources/MyDS&gt; ls()</P>
<P>[...]</P>
<P>-rw-PoolNameMyPool</P>
<P>[...]</P>
<P>wls:/mydomain/config/JDBCTxDataSources/MyDS&gt; set(´PoolName´, MY_POOL_?NAME)</P>
<P><STRONG>结束语</STRONG> </P>
<P>　　WLST是一个能够推进应用程序服务器配置和远程维护的杰出工具。它还不支持用通配符查找/定位选项（对于一些并非不常见的情况，如有人需要查找某个配置选项但是想不起它的位置）。但是，当最后与WebLogic 9绑定后，它肯定会非常有用。</P>
<P><STRONG>参考资料</STRONG></P>
<UL>
<LI>p6spy开放资源驱动程序: <A href="http://www.p6spy.com/" target=_blank>www.p6spy.com/</A> 
<LI>在线下载WLST: <A href="http://dev2dev.bea.com/codelibrary/code/wlst.jsp" target=_blank>http://dev2dev.bea.com/codelibrary/code/wlst.jsp</A> 
<LI>离线下载WLST: <A href="http://dev2dev.bea.com/codelibrary/code/wlst_offline.jsp" target=_blank>http://dev2dev.bea.com/codelibrary/code/wlst_offline.jsp</A> 
<LI>WebLogic域配置策略: <A href="http://www.sys-con.com/story/?storyid=47096&amp;DE=1" target=_blank>www.sys-con.com/story/?storyid=47096&amp;DE=1</A> 
<LI>Martin Fowler on scripting languages for complex tasks not easily achieved with XML: <A href="http://martinfowler.com/bliki/BuildLanguage.html" target=_blank>http://martinfowler.com/bliki/BuildLanguage.html</A> </LI></UL>
<P><STRONG>原文出处</STRONG></P>
<P><A href="http://wldj.sys-con.com/read/48932.htm" target=_blank>http://wldj.sys-con.com/read/48932.htm</A></P><!--文章其他信息-->
<DIV class=dot001><IMG height=1 alt="" src="http://dev2dev.bea.com.cn/images/_.gif" width="100%"></DIV>
<TABLE cellSpacing=0 cellPadding=3 width="100%" border=0>
<TBODY>
<TR vAlign=bottom>
<TD colSpan=2 height=20>&nbsp;<SPAN class=h2b>作者简介</SPAN></TD></TR>
<TR>
<TD vAlign=top align=middle width=0></TD>
<TD>Ignacio Coloma 是InfoInnova的J2EE架构师。过去6年以来，他已经为电子银行、航空运输、电子政府以及消息处理系统开发了许多应用程序。目前，他正在用脚本语言扩展J2EE应用程序。</TD></TR></TBODY></TABLE><img src ="http://www.cnitblog.com/xiaoyaocao/aggbug/2949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xiaoyaocao/" target="_blank">逍遥草</a> 2005-09-28 18:49 <a href="http://www.cnitblog.com/xiaoyaocao/archive/2005/09/28/2949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEBLOGIC 常规服务器挂起问题</title><link>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2912.html</link><dc:creator>逍遥草</dc:creator><author>逍遥草</author><pubDate>Tue, 27 Sep 2005 08:42:00 GMT</pubDate><guid>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2912.html</guid><wfw:comment>http://www.cnitblog.com/xiaoyaocao/comments/2912.html</wfw:comment><comments>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2912.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xiaoyaocao/comments/commentRss/2912.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xiaoyaocao/services/trackbacks/2912.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width=615 border=0>
<TBODY>
<TR>
<TD class=px14L150gray height=40></TD></TR>
<TR>
<TD class=px12none><IMG height=3 src="http://www.bea.com.cn/support_pattern/images/line.gif" width=615></TD></TR>
<TR>
<TD class=px12none><A name=TOP></A>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top">
<P><B><U>问题描述</U></B><BR>在出现以下情况时怀疑服务器挂起：</P>
<UL>
<LI>服务器不响应新的请求。 
<LI>请求超时。 
<LI>请求处理的时间越来越长（其最终结果可能是挂起）。 
<LI>通常，服务器挂起不会表现为服务器崩溃，但服务器挂起之后可能会崩溃。 </LI></UL></TD></TR></TBODY></TABLE>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top"><U><STRONG>故障排除</STRONG><B><BR></B></U>请注意，并非下面所有任务都需要完成。有些问题仅通过执行几项任务就可以解决。 
<P><B><U>快速链接：</U></B> 
<UL>
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Why_does_the_problem_occur?">为什么发生此问题？</A></U> 
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Potential_Causes_of_Server_Hang">服务器挂起的可能原因</A></U> 
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Basic_Steps">基本步骤</A></U> 
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Known_WebLogic_Server_Issues">已知的 WebLogic Server 问题</A></U> 
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Collecting_Thread_Dumps">收集 Thread Dump</A></U> 
<LI><U><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Analysis_of_Thread_Dump">Thread Dump 分析</A></U> </LI></UL>
<P><U><B><A name=Why_does_the_problem_occur?></A></B><SPAN style="TEXT-DECORATION: underline"><STRONG>为什么发生此问题？</STRONG></SPAN><STRONG></STRONG></U><BR>服务器挂起有多种原因（请参考<A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Potential_Causes_of_Server_Hang">服务器挂起的可能原因</A>一节）。一般而言，服务器挂起是因为缺少某种资源。缺少资源会阻止服务器响应服务请求。例如，由于故障（死锁）或者大量请求的缘故，可能没有任何可用的执行线程来完成工作，所有执行线程都被占用或忙于处理以前的请求。 
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A> 
<P><STRONG><U><A name=Potential_Causes_of_Server_Hang>服务器挂起的可能原因</A></U></STRONG> </P></TD></TR></TBODY></TABLE>
<TABLE class=px12none cols=3 width=615 border=1>
<TBODY>
<TR>
<TD width="45%">
<DIV align=center><STRONG>主题</STRONG></DIV></TD>
<TD width="25%">
<DIV align=center><STRONG>模式名称</STRONG></DIV></TD>
<TD width="30%">
<DIV align=center><STRONG>链接</STRONG></DIV></TD></TR>
<TR>
<TD vAlign=top>RMI、RJVM 响应 － 所有绑定线程等待 RJVM、RMI 响应。</TD>
<TD>EJB_RMI 服务器挂起</TD>
<TD>
<DIV align=center><A href="http://www.bea.com.cn/support_pattern/EJB_RMI_Server_Hang_Pattern.html">EJB_RMI 服务器挂起</A></DIV></TD></TR>
<TR>
<TD vAlign=top>应用程序死锁 － 线程锁定资源 1，然后等待锁定资源 2。另一个线程锁定资源 2，然后等待锁定资源 1。</TD>
<TD>应用程序死锁导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>线程全部被占用，没有线程可用于新工作。</TD>
<TD>线程占用导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>垃圾回收花费太多时间。</TD>
<TD>垃圾回收导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>servlet 时间的 JSP 错误设置，比如 PageCheckSeconds。</TD>
<TD>JSP 导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>死锁造成 JDBC 挂起。</TD>
<TD>JDBC 中的服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>（代码优化）过程中的 JVM 挂起类似于服务器挂起。</TD>
<TD>代码优化中服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>在大量负载情况下 JSP 编译造成服务器挂起。</TD>
<TD>JSP 编译导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR>
<TR>
<TD vAlign=top>SUN JVM 错误，比如轻量型线程库。</TD>
<TD>Sun JVM 错误导致服务器挂起</TD>
<TD>
<DIV align=center>待定</DIV></TD></TR></TBODY></TABLE>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top">
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A> 
<P><A name=Basic_Steps><STRONG><U>基本步骤</U></STRONG></A><BR>当服务器挂起时，首先使用 <FONT face="Courier New, Courier, mono">java weblogic.Admin t3://server:port PING</FONT> 来 ping 该服务器。如果服务器能够响应此 ping，则可能是应用程序正在挂起而不是服务器自身。 
<P>确保服务器确实正在挂起，而不是在做垃圾回收。若要验证挂起，启用 <FONT face="Courier New, Courier, mono">-verbosegc</FONT> 重新启动服务器，然后将 <FONT face="Courier New, Courier, mono">stdout</FONT> 和 <FONT face="Courier New, Courier, mono">stderr</FONT> 重定向到一个文件中。当服务器停止响应时，可以判断它是正在收集无用信息还是确实挂起。 
<P>WebLogic Server 使用“Default”线程队列响应客户端服务请求。这些是在发生服务器挂起时应当检查的线程。下面是其中一个线程在 Thread Dump 中的形式示例。Execute Thread 14 正在等待任务。该线程调用的最后方法是 Object.wait()。 </P></TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px" cellSpacing=2 cellPadding=2 width=615 border=1>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(204,204,204)" width=615>"ExecuteThread: '14' for queue: 'default'" daemon prio=5 tid=0x8b0ab30 nid=0x1f4 waiting on monitor [0x96af000..0x96afdc4]<BR>at<BR>java.lang.Object.wait(Native Method)<BR>at<BR>java.lang.Object.wait(Object.java:420)<BR>at<BR>weblogic.kernel.ExecuteThread.waitForRequest(ExecuteThread.java:94)<BR>at<BR>weblogic.kernel.ExecuteThread.run(ExecuteThread.java:118)</TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top"><FONT color=#009900><U></U></FONT>
<P>确定“Default”ExecuteThread 队列是否超载。利用控制台确定“Default”队列中的所有 ExecuteThreads 是否空闲。如果没有一个空闲，则应用程序可能需要一个更大的 ExecuteThread 数来配置。可以通过控制台更改该值，并将其保存在 config.xml 文件中。 
<P>如果执行队列有空闲线程，则可能没有分配足够的 Socket Reader 线程。缺省情况下，WebLogic Server 实例在启动时创建三个 Socket Reader 线程。如果群集系统在高峰期使用的 Socket Reader 线程超过三个，则增加 Socket Reader 线程的数量。 
<P>通常，Socket Reader 线程的数量应当较小。但是，如果 Weblogic Serve 充当正在挂起的服务器实例的客户端，则应当为每个 Weblogic Serve 配置一个线程。 
<P>如果使用 JDBC 连接池，确保池中已经配置的 JDBC 连接数量与同时请求（即执行线程）的数量相等。 
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A> 
<P><A name=Known_WebLogic_Server_Issues><U><STRONG>已知的 WebLogic 问题</STRONG></U></A><BR>JDBC 产生死锁问题的可能性存在。检查在 weblogic.log 开头找到的服务器的版本和 Service Pack 级别。然后对已经应用于服务器类路径的所有临时修补程序检查以上版本和 Service Pack 行。修补程序将指明已经解决了什么问题。 
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A> 
<P><A name=Collecting_Thread_Dumps><B><U>收集 Thread Dump</U></B></A> <BR>进行 Thread Dump 的方法取决于安装挂起服务器实例的操作系统。有关在不同的操作系统上进行 Thread Dump 的信息，可以在以下网址中找到：<A href="http://e-docs.bea.com/wls/docs81/cluster/trouble.html#gc">http://e-docs.bea.com/wls/docs81/cluster/trouble.html#gc</A>。 
<P><EM><STRONG>Unix 系统（Solaris、HP、AIX）</STRONG></EM><BR>使用 <FONT face="Courier New, Courier, mono">kill .3 &lt;weblogic process id&gt;</FONT> 创建诊断问题所需的 Thread Dump。确保在每个服务器上执行几次，每次间隔大约 5 到 10 秒，以帮助诊断死锁问题。为达到诊断目的，用 nohup 启动服务启进程（请参考解决方案 <A href="http://support.bea.com/application?namespace=askbea&amp;origin=ask_bea_answer.jsp&amp;event=link.view_answer_page_clfydoc&amp;answerpage=solution&amp;page=wls/S-12292.htm">S-12292</A> 和 <A href="http://support.bea.com/application?namespace=askbea&amp;origin=ask_bea_answer.jsp&amp;event=link.view_answer_page_clfydoc&amp;answerpage=solution&amp;page=wls/S-15924.htm">S-15924</A>）。 
<P><EM><STRONG>Windows、XP、NT</STRONG></EM><BR>每个服务器需要 <FONT face="Courier New, Courier, mono">&lt;Ctrl&gt;-&lt;Break&gt;</FONT> 来创建诊断问题所需的 Thread Dump。确保在每个服务器上执行几次，每次间隔大约 5 到 10 秒，以帮助诊断死锁问题。在 NT 上，在命令 shell 中输入 <FONT face="Courier New, Courier, mono">CTRL-Break</FONT>。 
<P><EM><STRONG>Linux</STRONG></EM><BR>Linux 操作系统查看线程的方式不同于其它操作系统。该操作系统将每个线程视为一个进程。若要在 Linux 上进行 Thread Dump，查找通过其启动所有其它进程的进程 ID。使用命令： 
<UL>
<LI>若要获得根 PID，使用： 
<BLOCKQUOTE>
<P><FONT face="Courier New, Courier, mono">ps -efHl | grep 'java' **. ** </FONT></P></BLOCKQUOTE></LI></UL>
<P>使用一个作为字符串的 grep 参数（可在与服务器启动命令匹配的进程堆栈中找到该字符串）。如果 ps 命令还没有管道传送到另一个例程，则报告的第一个 PID 将是根进程。</P>
<UL>
<LI>使用 weblogic.Admin 命令 <FONT face="Courier New, Courier, mono">THREAD_DUMP</FONT> </LI></UL>
<P>进行 Thread Dump 的另一种方法是使用 <FONT face="Courier New, Courier, mono">THREAD_DUMP</FONT> admin 命令。此方法与正在运行服务器实例的操作系统无关。</P>
<BLOCKQUOTE>
<P><FONT face="Courier New, Courier, mono">java weblogic.Admin -url ManagedHost:8001 -username weblogic -password weblogic THREAD_DUMP</FONT> </P></BLOCKQUOTE>
<P><STRONG>备注：</STRONG> 如果无法 ping 服务器实例，则不可以使用该命令。 
<P>如果正在使用的 JVM 是 Sun 开发的，则 Thread Dump 转为 stdout（标准输出文件）。Sun 已经增强了 JVM 1.3.1 和 1.4 之间的 Thread Dump 格式。若要获得 Sun JVM 1.4 的 Thread Dump 格式，将下列选项添加到启动 1.3.1 JVM 的 java 命令行中： 
<BLOCKQUOTE>
<P><FONT face="Courier New, Courier, mono">-XX:+JavaMonitorsInStackTrace</FONT></P></BLOCKQUOTE>
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A></P>
<P><A name=Analysis_of_Thread_Dump><B><U>Thread Dump 分析</U></B></A> <BR>分析服务器挂起的最有用的工具是一系列 Thread Dump。Thread Dump 提供关于每个线程在特定时刻正在执行什么操作的信息。一系列 Thread Dump（一般每隔 5 到 10 秒进行三个或更多 Thread Dump）可以帮助分析每个线程从一个 Thread Dump 到另一个 Thread Dump 过程中的状态变化或所缺少的变化。挂起服务器 Thread Dump 一般显示线程状态从第一个 Thread Dump 到最后一个 Thread Dump 中变化很小。 
<P><B>在 Thread Dump 中查看的内容</B> <BR>所有请求都通过 ListenThread 进入 WebLogic Server。如果 ListenThread 丢失，就无法接收任何工作，因此也无法完成任何工作。确认在 Thread Dump 中存在 ListenThread。ListenThread 应当在 socketAccept 方法中。下面示例说明监听线程 (Listen Thread) 的形式。 </P></TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px" cellSpacing=2 cellPadding=2 border=1>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(204,204,204)">
<P>"ListenThread.Default" prio=10 tid=0x00037888 nid=93 lwp_id=6888343 runnable [0x 1a81b000..0x1a81b530]at java.net.PlainSocketImpl.socketAccept(Native Method)<BR>at<BR>java.net.PlainSocketImpl.accept(PlainSocketImpl.java:353)<BR>- locked &lt;0x26d9d490&gt; (a java.net.PlainSocketImpl)<BR>at<BR>java.net.ServerSocket.implAccept(ServerSocket.java:439)<BR>at<BR>java.net.ServerSocket.accept(ServerSocket.java:410)<BR>at<BR>weblogic.socket.WeblogicServerSocket.accept(WeblogicServerSocket.java:24)<BR>at<BR>weblogic.t3.srvr.ListenThread.accept(ListenThread.java:713)<BR>at<BR>weblogic.t3.srvr.ListenThread.run(ListenThread.java:290) </P></TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top">Socket Reader 线程接受来自监听线程队列的传入请求，并将该请求放入执行线程队列。如果 Thread Dump 中没有 Socket Reader 线程，则在某个地方存在导致 Socket Reader 线程消失的错误。应当始终保持至少有三个 Socket Reader 线程。一个 Socket Reader 线程一般用于轮询功能，另外两个用于处理请求。下面是一个 Thread Dump 示例中的 Socket Reader 线程。</TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px" cellSpacing=2 cellPadding=2 border=1>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(204,204,204)">
<P>"ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'" daemon prio=10 tid=0x00036128 nid=75 lwp_id=6888070 waiting for monitor entry [0x1b12f000..0x1b12f530]<BR>at<BR>weblogic.socket.PosixSocketMuxer.processSockets(PosixSocketMuxer.java:92)<BR>- waiting to lock &lt;0x25c01198&gt; (a java.lang.String)<BR>at<BR>weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32)<BR>at<BR>weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:178)<BR>at<BR>weblogic.kernel.ExecuteThread.run(ExecuteThread.java:151) 
<P>"ExecuteThread: '1' for queue: 'weblogic.socket.Muxer'" daemon prio=10 tid=0x00035fc8 nid=74 lwp_id=6888067 runnable [0x1b1b0000..0x1b1b0530]at weblogic.socket.PosixSocketMuxer.poll(Native Method)<BR>at<BR>weblogic.socket.PosixSocketMuxer.processSockets(PosixSocketMuxer.java:99)<BR>&nbsp;- locked &lt;0x25c01198&gt; (a java.lang.String)<BR>at<BR>weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32)<BR>at<BR>weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:178)<BR>at<BR>weblogic.kernel.ExecuteThread.run(ExecuteThread.java:151) 
<P>"ExecuteThread: '0' for queue: 'weblogic.socket.Muxer'" daemon prio=10 tid=0x00035e68 nid=73 lwp_id=6888066 waiting for monitor entry [0x1b231000..0x1b231530]<BR>at<BR>weblogic.socket.PosixSocketMuxer.processSockets(PosixSocketMuxer.java:92)<BR>- waiting to lock &lt;0x25c01198&gt; (a java.lang.String)<BR>at<BR>weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32)<BR>at<BR>weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:178)<BR>at<BR>weblogic.kernel.ExecuteThread.run(ExecuteThread.java:151) </P></TD></TR></TBODY></TABLE><BR>
<TABLE style="WIDTH: 615px; TEXT-ALIGN: left" cellSpacing=2 cellPadding=2>
<TBODY>
<TR>
<TD class=px12none style="VERTICAL-ALIGN: top">
<P><FONT face="Courier New, Courier, mono">ThreadPoolPercentSocketReaders</FONT> 属性设定要用于从 java Socket 中读取消息的执行线程的最大百分比。此属性的最佳值是针对应用程序设定的。缺省值为 33，有效范围是 1 到 99。 
<P>分配执行线程充当 Socket Reader 线程可提高服务器接受客户端请求的速度和能力。必须平衡专门用于从 Socket 读取消息的执行线程和那些在服务器中执行实际运行任务的线程的数量。 
<P><B>后续步骤</B> <BR>后续步骤要求进一步分析 Thread Dump。检查 Thread Dump，了解每个线程在服务器挂起时正在执行的操作。这有助于分析下一个探查阶段。例如，如果 JSP 编译中涉及许多线程，参考<A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#Potential_Causes_of_Server_Hang">服务器挂起的可能原因</A>一节可了解进一步的诊断和测试操作。 
<P><A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html#TOP">返回页首</A> <BR><BR>文章出处：<A href="http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html">http://www.bea.com.cn/support_pattern/Generic_Server_Hang_Pattern.html</A></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.cnitblog.com/xiaoyaocao/aggbug/2912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xiaoyaocao/" target="_blank">逍遥草</a> 2005-09-27 16:42 <a href="http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2912.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取connection </title><link>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2904.html</link><dc:creator>逍遥草</dc:creator><author>逍遥草</author><pubDate>Tue, 27 Sep 2005 02:19:00 GMT</pubDate><guid>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2904.html</guid><wfw:comment>http://www.cnitblog.com/xiaoyaocao/comments/2904.html</wfw:comment><comments>http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2904.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/xiaoyaocao/comments/commentRss/2904.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xiaoyaocao/services/trackbacks/2904.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在工作中碰到这样一个问题，weblogic正常启动后，connection可以自由获取，但是在运行一段时间后，也许几小时，也许几天，weblogic服务就宕掉了。结果就是无法获取connection,但是在weblogic的console上,connection pools--&gt;Monitoring上显示的却是还有剩余。上网查到类似问题，但只有如下的回答，并没有真正说到问题所在啊。<BR><BR>&nbsp;&nbsp;&nbsp; statement是查询语句,connection是和数据库的连接.<BR>&nbsp;&nbsp;&nbsp; 释放顺序如下.<BR>&nbsp;&nbsp;&nbsp; finally{<BR>&nbsp;&nbsp;&nbsp; stmt.close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;conn.close();<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp; 对于系统中使用到比较耗费资源的东西，比如说:connection，jndi等等，往往是需要缓存，一次获得，重复使用的原则。<BR>对于connection来说，它本身是一个接口,ojdbc14.jar或classes12.zip等等都实现了这个接口，实现的close方法大都是强制关闭。weblogic的连接池的实现不一样，它的close并不是真正的关闭而是返回给连接池。所以在程序的结尾处一定要记住返回给连接池。<BR><BR>代码如下<BR>Connection conn = null;<BR>ResultSet rs = null;<BR>Statement stmt = null;<BR>try{<BR>//commit<BR>}catch(Exception e){<BR>//rollback;<BR>throw e;<BR>}finally{<BR>if(conn!=null) conn.close();<BR>if(rs!=null) rs.close();<BR>if(stmt!=null) rs.close();<BR>}<BR><BR><BR>&nbsp;&nbsp;&nbsp; 难道是statement没有释放，但是我已经释放了connection，这样不行？又或是我的connection pool size设置过小，但我已经改到200 了。不知道这个问题如何解决，头痛ing……&nbsp;<img src ="http://www.cnitblog.com/xiaoyaocao/aggbug/2904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xiaoyaocao/" target="_blank">逍遥草</a> 2005-09-27 10:19 <a href="http://www.cnitblog.com/xiaoyaocao/archive/2005/09/27/2904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>