﻿<?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>语源科技BlogJava-WOLF--执着</title><link>http://www.blogjava.net/sutao/</link><description>用文字记录学习的体验！</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 23:19:58 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 23:19:58 GMT</pubDate><ttl>60</ttl><item><title>tomcat6使用nio</title><link>http://www.blogjava.net/sutao/articles/162796.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Sat, 24 Nov 2007 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162796.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162796.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162796.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162796.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162796.html</trackback:ping><description><![CDATA[<span style="color: #0000ff">很早就听说tomcat6使用nio了，这几天突然想到一个问题，使用nio代替传统的bio，ThreadLocal岂不是会存在冲突？ <br />
　　 <br />
　　 <br />
　　 <br />
　　首先，何谓nio？ <br />
　　 <br />
　　如果读者有socket的编程基础，应该会接触过堵塞socket和非堵塞socket，堵塞socket就是在accept、read、write等IO操作的的时候，如果没有可用符合条件的资源，不马上返回，一直等待直到有资源为止。而非堵塞socket则是在执行select的时候，当没有资源的时候堵塞，当有符合资源的时候，返回一个信号，然后程序就可以执行accept、read、write等操作，这个时候，这些操作是马上完成，并且马上返回。而windows的winsock则有所不同，可以绑定到一个EventHandle里，也可以绑定到一个HWND里，当有资源到达时，发出事件，这时执行的io操作也是马上完成、马上返回的。一般来说，如果使用堵塞socket，通常我们时开一个线程accept socket，当有socket链接的时候，开一个单独的线程处理这个socket；如果使用非堵塞socket，通常是只有一个线程，一开始是select状态，当有信号的时候马上处理，然后继续select状态。 <br />
　　 <br />
　　按照大多数人的说法，堵塞socket比非堵塞socket的性能要好。不过也有小部分人并不是这样认为的，例如Indy项目（Delphi一个比较出色的网络包），它就是使用多线程＋堵塞socket模式的。另外，堵塞socket比非堵塞socket容易理解，符合一般人的思维，编程相对比较容易。 <br />
　　 <br />
　　nio其实也是类似上面的情况。在JDK1.4，sun公司大范围提升Java的性能，其中NIO就是其中一项。Java的IO操作集中在java.io这个包中，是基于流的阻塞API（即BIO，Block IO）。对于大多数应用来说，这样的API使用很方便，然而，一些对性能要求较高的应用，尤其是服务端应用，往往需要一个更为有效的方式来处理IO。从JDK 1.4起，NIO API作为一个基于缓冲区，并能提供非阻塞O操作的API（即NIO，non-blocking IO）被引入。 <br />
　　 <br />
　　BIO与NIO一个比较重要的不同，是我们使用BIO的时候往往会引入多线程，每个连接一个单独的线程；而NIO则是使用单线程或者只使用少量的多线程，每个连接共用一个线程。 <br />
　　 <br />
　　 <br />
　　 <br />
　　这个时候，问题就出来了：我们非常多的java应用是使用ThreadLocal的，例如JSF的FaceContext、Hibernate的session管理、Struts2的Context的管理等等，几乎所有框架都或多或少地应用ThreadLocal。如果存在冲突，那岂不惊天动地？ <br />
　　 <br />
　　后来终于在Tomcat6的文档（http://tomcat.apache.org/tomcat-6.0-doc/aio.html）找到答案。根据上面说明，应该Tomcat6应用nio只是用在处理发送、接收信息的时候用到，也就是说，tomcat6还是传统的多线程Servlet，我画了下面两个图来列出区别： <br />
　　 <br />
　　 <br />
　　 <br />
　　tomcat5：客户端连接到达 -&gt; 传统的SeverSocket.accept接收连接 -&gt; 从线程池取出一个线程 -&gt; 在该线程读取文本并且解析HTTP协议 -&gt; 在该线程生成ServletRequest、ServletResponse，取出请求的Servlet -&gt; 在该线程执行这个Servlet -&gt; 在该线程把ServletResponse的内容发送到客户端连接 -&gt; 关闭连接。 <br />
　　 <br />
　　我以前理解的使用nio后的tomcat6：客户端连接到达 -&gt; nio接收连接 -&gt; nio使用轮询方式读取文本并且解析HTTP协议（单线程） -&gt; 生成ServletRequest、ServletResponse，取出请求的Servlet -&gt; 直接在本线程执行这个Servlet -&gt; 把ServletResponse的内容发送到客户端连接 -&gt; 关闭连接。 <br />
　　 <br />
　　实际的tomcat6：客户端连接到达 -&gt; nio接收连接 -&gt; nio使用轮询方式读取文本并且解析HTTP协议（单线程） -&gt; 生成ServletRequest、ServletResponse，取出请求的Servlet -&gt; 从线程池取出线程，并在该线程执行这个Servlet -&gt; 把ServletResponse的内容发送到客户端连接 -&gt; 关闭连接。 <br />
　　 <br />
　　 <br />
　　 <br />
　　从上图可以看出，BIO与NIO的不同，也导致进入客户端处理线程的时刻有所不同：tomcat5在接受连接后马上进入客户端线程，在客户端线程里解析HTTP协议，而tomcat6则是解析完HTTP协议后才进入多线程，另外，tomcat6也比5早脱离客户端线程的环境。 <br />
　　 <br />
　　实际的tomcat6与我之前猜想的差别主要集中在如何处理servlet的问题上。实际上即使抛开ThreadLocal的问题，我之前理解tomcat6只使用一个线程处理的想法其实是行不同的。大家都有经验：servlet是基于BIO的，执行期间会存在堵塞的，例如读取文件、数据库操作等等。tomcat6使用了nio，但不可能要求servlet里面要使用nio，而一旦存在堵塞，效率自然会锐降。 <br />
　　 <br />
　　 <br />
　　 <br />
　　 <br />
　　所以，最终的结论当然是tomcat6的servlet里面，ThreadLocal照样可以使用，不存在冲突。 <br />
　　 </span>
<img src ="http://www.blogjava.net/sutao/aggbug/162796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-24 10:48 <a href="http://www.blogjava.net/sutao/articles/162796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高效java</title><link>http://www.blogjava.net/sutao/articles/162793.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Sat, 24 Nov 2007 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162793.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162793.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162793.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162793.html</trackback:ping><description><![CDATA[<font style="color: #0000ff" size="4">每一种语言都有其自身的特点，只有掌握了其自身的特点，才能用它编写出高效的程序。下面就我个人实践所知谈谈javaSE方面的性能问题，<br />
javaEE方面的性能暂不讨论，要是时间可以再写一javaEE方面的性能问题的帖子。<br />
<br />
1， 尽量不要使用+号来连接字符串，至少不要在隔行中使用+来连接字符串。因为有的java虚拟机可能对字符串连接+做了性能优化，在都同行的+字符串连接，转化为StringBuffer的append()方法来连接，所以在同行使用+和使用StringBuffer的append 来做连接性能上差不多。<br />
2， 对小数据int的Integer封装，尽量的使用Integer.valueOf()创建，而不要使用new来创建。因为Integer类缓存了从-128到256个 状态的Integer。<br />
3， 对Boolean类，要用valueOf()或使用Boolean.TRUE或Boolean.FALSE来创建对象。我个人觉得对Boolean类用private构造函数，可能就会避免不好的使用Boolean类了。<br />
4， 在设计类时应尽可能地避免在类的默认构造函数中创建，初始化大量的对象。<br />
5， 合理的申请数组空间，如果数组中所保存的元素占用内存空间较大或数组本身长度较长的情况，我们釆用可以釆用软引用的技术来引用数组，以&#8220;提醒&#8221;JVM及时的回收垃圾内存，维护系统的稳定性。<br />
6，&nbsp; 避免创建重复的对象，我们在编写一个方法的时候应该先考虑方法里的局部对象域能否改为private static final，从而避免创建重复的对象。<br />
7, 把try/catch块放入循环体内，会极大的影响性能，如果编译JIT被关闭或者你所使用的一个不带JIT的JVM，性能会将下降21%之多!<br />
8，StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中，如果超出这个大小，就会重新分配内存，创建一个更大的数组，并将原先的数组复制过来，再丢弃旧的数组。在大多数情况下，你可以在创建StringBuffer的时候指定大小，这样就避免了在容量不够的时候自动增长，以提高性能。<br />
9,&nbsp;&nbsp; 使用Java NIO提高服务端程序的性能。<br />
10，考虑用静态工厂方法替代构造函数。<br />
11，在对大量的数组拷贝时，可以考虑用Arrays.copyOf()来拷贝。<br />
12, 在并发的情况下，要合理的选择同步的策略，应该谨慎的控制synchronized块的大小，不可以将一个操作分解到多个synchronized 但也要尽量地从synchronized块中分离耗时的且不影响并发的操作。<br />
13，要合理的选择集合框架，例如：ArrayList和LinkedList在某些不同的场合，其性能相差很大。对要做大量的插入时， LinkedList 的性能比ArrayList的性能好。对要做大量随机查找的时候用ArrayList的性能比用LinkedList的性能好。还有在不需要并发操作的情况下，选择非线程安全的集合比线程安全的集合要好。如在非线程安全的要求下，选择ArrayList要比Vector好。<br />
14，不要在循环语句块中调用length()方法做为循环结束的条件。<br />
15，如果字符串特别长，不要釆用charAt()一一的获取特定位置的字符，而应该调用toCharArray()方法转化为字符数组，然后通过数组 索引值获取指定位置的字符。<br />
16，如果是想把数据封装成Double类型的，不要这样使用new Double("1.23")，而要应这样使用new Double(1.23),虽然二者都没有语法 的错误，也都能达到预期的结果，但其性能有着很大的差异。<br />
17, 应尽量的通过缓冲流类来提高I/O操作效率,但也要合理的选择缓冲大小 。<br />
&nbsp;&nbsp;&nbsp; 呵呵，好了，今天就写到这吧，以后要是有时间再继续写。小弟我初学java，不对之地，欢迎大家指正，补遗。</font>
<img src ="http://www.blogjava.net/sutao/aggbug/162793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-24 10:24 <a href="http://www.blogjava.net/sutao/articles/162793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat常识(apache)</title><link>http://www.blogjava.net/sutao/archive/2007/11/24/162781.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Sat, 24 Nov 2007 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/archive/2007/11/24/162781.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162781.html</wfw:comment><comments>http://www.blogjava.net/sutao/archive/2007/11/24/162781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162781.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162781.html</trackback:ping><description><![CDATA[<p><span style="color: #0000ff">一、小猫TOMCAT其实很可爱</span></p>
<p><span style="color: #0000ff">2003年底，我换公司了，同样也换了WEBAPP，TOMCAT出现在我的面前（以前使用weblogic），我有点茫然，免费的东西真的能用的好么？担心ING&#8230;&#8230;（其实是在火星呆太久）出门一打听，原来此猫出自名门－jakarta项目，2001年度最具创新的java产品(Most Innovative Java Product)，又有JAVA的老大SUN的力捧（官方推荐的servlet和jsp容器），以后就靠它吃饭了。不说二话，搞起来先：</span></p>
<p><span style="color: #0000ff">1、 安装</span></p>
<p><span style="color: #0000ff">TOMCAT最新版本是5.0.29（http://jakarta.apache.org/site/binindex.cgi）</span></p>
<p><span style="color: #0000ff">如果在WINDOWS下它可以自动找到你的JDK或者set JAVA_HOME=c:/jdk</span></p>
<p><span style="color: #0000ff">在LINUX下需要先解压，然后设置JAVA_HOME</span></p>
<p><span style="color: #0000ff">export JAVA_HOME=/usr/local/jdk</span></p>
<p><span style="color: #0000ff">2、 RUN</span></p>
<p><span style="color: #0000ff">设置完毕后就可以运行tomcat服务器了，进入tomcat的bin目录，WINDOWS下用startup启动tomcat，linux下用startup.sh，相应的关闭tomcat的命令为shutdown和shutdown.sh。</span></p>
<p><span style="color: #0000ff">启动服务后在浏览器里输入http://localhost:8080来测试一下</span></p>
<p><span style="color: #0000ff">3、 目录结构</span></p>
<p><span style="color: #0000ff">Bin：存放启动和关闭tomcat脚本。</span></p>
<p><span style="color: #0000ff">Conf：包含不同的配置文件,server.xml(Tomcat的主要配置文件)。</span></p>
<p><span style="color: #0000ff">Work：存放jsp编译后产生的class文件。</span></p>
<p><span style="color: #0000ff">Webapp：存放应用程序示例，以后你要部署的应用程序也要放到此目录。</span></p>
<p><span style="color: #0000ff">Logs：存放日志文件</span></p>
<p><span style="color: #0000ff">Comm./server/shared：这三个文件夹下的LIB文件夹放jar文件。</span></p>
<p><span style="color: #0000ff">1、 配置server.xml文件</span></p>
<p><span style="color: #0000ff">没有什么好说的，看TOMCAT的文档比较有用，这里提供一些主要的东西吧。</span></p>
<p><span style="color: #0000ff">元素名 <br />
属性 <br />
解释</span></p>
<p><span style="color: #0000ff">server <br />
port <br />
指定一个端口，这个端口负责监听关闭tomcat的请求</span></p>
<p><span style="color: #0000ff">shutdown <br />
指定向端口发送的命令字符串</span></p>
<p><span style="color: #0000ff">service <br />
name <br />
指定service的名字</span></p>
<p><span style="color: #0000ff">Connector(表示客户端和service之间的连接) <br />
port <br />
指定服务器端要创建的端口号，并在这个断口监听来自客户端的请求</span></p>
<p><span style="color: #0000ff">minProcessors <br />
服务器启动时创建的处理请求的线程数</span></p>
<p><span style="color: #0000ff">maxProcessors <br />
最大可以创建的处理请求的线程数</span></p>
<p><span style="color: #0000ff">enableLookups <br />
如果为true，则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名，若为false则不进行DNS查询，而是返回其ip地址</span></p>
<p><span style="color: #0000ff">redirectPort <br />
指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号</span></p>
<p><span style="color: #0000ff">acceptCount <br />
指定当所有可以使用的处理请求的线程数都被使用时，可以放到处理队列中的请求数，超过这个数的请求将不予处理</span></p>
<p><span style="color: #0000ff">connectionTimeout <br />
指定超时的时间数(以毫秒为单位)</span></p>
<p><span style="color: #0000ff">Engine(表示指定service中的请求处理机，接收和处理来自Connector的请求) <br />
defaultHost <br />
指定缺省的处理请求的主机名，它至少与其中的一个host元素的name属性值是一样的</span></p>
<p><span style="color: #0000ff">Context(表示一个web应用程序，通常为WAR文件，关于WAR的具体信息见servlet规范) <br />
docBase <br />
应用程序的路径或者是WAR文件存放的路径</span></p>
<p><span style="color: #0000ff">path <br />
表示此web应用程序的url的前缀，这样请求的url为http://localhost:8080/path/****</span></p>
<p><span style="color: #0000ff">reloadable <br />
这个属性非常重要，如果为true，则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化，自动装载新的应用程序，我们可以在不重起tomcat的情况下改变应用程序</span></p>
<p><span style="color: #0000ff">host(表示一个虚拟主机) <br />
name <br />
指定主机名</span></p>
<p><span style="color: #0000ff">appBase <br />
应用程序基本目录，即存放应用程序的目录</span></p>
<p><span style="color: #0000ff">unpackWARs <br />
如果为true，则tomcat会自动将WAR文件解压，否则不解压，直接从WAR文件中运行应用程序</span></p>
<p><span style="color: #0000ff">Logger(表示日志，调试和错误信息) <br />
className <br />
指定logger使用的类名，此类必须实现org.apache.catalina.Logger 接口</span></p>
<p><span style="color: #0000ff">prefix <br />
指定log文件的前缀</span></p>
<p><span style="color: #0000ff">suffix <br />
指定log文件的后缀</span></p>
<p><span style="color: #0000ff">timestamp <br />
如果为true，则log文件名中要加入时间，如下例:localhost_log.2001-10-04.txt</span></p>
<p><span style="color: #0000ff">Realm(表示存放用户名，密码及role的数据库) <br />
className <br />
指定Realm使用的类名，此类必须实现org.apache.catalina.Realm接口</span></p>
<p><span style="color: #0000ff">Valve(功能与Logger差不多，其prefix和suffix属性解释和Logger 中的一样) <br />
className <br />
指定Valve使用的类名，如用org.apache.catalina.valves.AccessLogValve类可以记录应用程序的访问信息</span></p>
<p><span style="color: #0000ff">directory <br />
指定log文件存放的位置</span></p>
<p><span style="color: #0000ff">pattern <br />
有两个值，common方式记录远程主机名或ip地址，用户名，日期，第一行请求的字符串，HTTP响应代码，发送的字节数。combined方式比common方式记录的值更多</span></p>
<p><span style="color: #0000ff">2、 管理</span></p>
<p><span style="color: #0000ff">TOMCAT管理能力很强大，进入http://localhost:8080/，自己慢慢管吧。实践出真知，我喜欢这样搞：</span></p>
<p><span style="color: #0000ff">^_^，一切尽在掌握http://localhost:8080/manager/html 。</span></p>
<p><span style="color: #0000ff">一、让数据库连接池转起来</span></p>
<p><span style="color: #0000ff">作为一个J2EE程序员大家手上可能会有现成的JDBC 数据库连接池，其实这没有太大的必要，因为象weblogic&#8230;&#8230;企业级WEBAPP都有自己的连接池，大家不要费力直接使用吧，效率也很不错，再也不用羡慕.NET的ADO了（以前作MS从来不担心数据连接，ADO确实用起来很爽），如果想实现一个 JDBC connection pool 的注意事项有：</span></p>
<p><span style="color: #0000ff">1. 有一个简单的函数从连接池中得到一个 Connection。</span></p>
<p><span style="color: #0000ff">2. close 函数必须将 connection 放回 数据库连接池。</span></p>
<p><span style="color: #0000ff">3. 当数据库连接池中没有空闲的 connection， 数据库连接池必须能够自动增加 connection 个数。</span></p>
<p><span style="color: #0000ff">4. 当数据库连接池中的 connection 个数在某一个特别的时间变得很大，但是以后很长时间只用其中一小部分，应该可以自动将多余的 connection 关闭掉。</span></p>
<p><span style="color: #0000ff">5. 如果可能，应该提供debug 信息报告没有关闭的 new Connection 。 </span></p>
<p><span style="color: #0000ff">网上有各种各样的连接池代码，抄过来改改吧，嘿嘿～</span></p>
<p><span style="color: #0000ff">这里介绍如何配置TOMCAT的连接池，以SQLSERVER为例：</span></p>
<p><span style="color: #0000ff">步骤1：安装SQLSERVER的JDBC驱动</span></p>
<p><span style="color: #0000ff">SQLSERVER的JDBC驱动其实就是三个JAR文件，msbase.jar/mssqlserver.jar/msutil.jar，将这三个文件拷贝到你的/tomcat_home/common/lib目录下去就可以了。</span></p>
<p><span style="color: #0000ff">步骤2：修改server.xml文件</span></p>
<p><span style="color: #0000ff">具体代码如下：</span></p>
<p><span style="color: #0000ff">&lt;Context path="test" docBase="F:\yourroot" debug="5" reloadable="true" crossContext="true"&gt;</span></p>
<p><span style="color: #0000ff">&lt;Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_DBTest_log." suffix=".txt" timestamp="true"/&gt; </span></p>
<p><span style="color: #0000ff">&lt;Resource name="jdbc/SqlServerDB" auth="Container" type="javax.sql.DataSource"/&gt; </span></p>
<p><span style="color: #0000ff">&lt;ResourceParams name="jdbc/SqlServerDB"&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;factory&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;!-- Maximum number of dB connections in pool. Make sure you configure your mysqld max_connections large enough to handle all of your db connections. Set to 0 for no limit.--&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;maxActive&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;50&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt;</span></p>
<p><span style="color: #0000ff">&lt;!-- Maximum number of idle dB connections to retain in pool. Set to 0 for no limit.--&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;maxIdle&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;20&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;!-- Maximum time to wait for a dB connection to become available in ms, in this example 0.5 seconds. An Exception is thrown if this timeout is exceeded. Set to -1 to wait indefinitely. --&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;maxWait&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;500&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;!-- msSQL dB username and password for dB connections --&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;username&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;sa&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt;</span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;password&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;sa&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;!-- Class name for SQLServer2000 JDBC driver --&gt; </span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;driverClassName&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;com.microsoft.jdbc.sqlserver.SQLServerDriver&lt;/value&gt; </span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;!-- The JDBC connection url for connecting to your MS SQL Server dB.The autoReconnect=true argument to the url makes sure that the mm.Sql Server JDBC Driver will automatically reconnect if mysqld closed the connection. mysqld by default closes idle connections after 8 hours.--&gt;</span></p>
<p><span style="color: #0000ff">&lt;parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;name&gt;url&lt;/name&gt; </span></p>
<p><span style="color: #0000ff">&lt;value&gt;jdbc:microsoft:sqlserver://10.0.254.11:1433;databaseName=yourdb&lt;/value&gt;</span></p>
<p><span style="color: #0000ff">&lt;!--must use &amp; not use &amp; --&gt;</span></p>
<p><span style="color: #0000ff">&lt;/parameter&gt; </span></p>
<p><span style="color: #0000ff">&lt;/ResourceParams&gt; </span></p>
<p><span style="color: #0000ff">&lt;/Context&gt;</span></p>
<p><span style="color: #0000ff">步骤三：程序调用</span></p>
<p><span style="color: #0000ff">package dbmanage;</span></p>
<p><span style="color: #0000ff">import java.sql.CallableStatement;</span></p>
<p><span style="color: #0000ff">import java.sql.Connection;</span></p>
<p><span style="color: #0000ff">import java.sql.Date;</span></p>
<p><span style="color: #0000ff">import java.sql.PreparedStatement;</span></p>
<p><span style="color: #0000ff">import java.sql.ResultSet;</span></p>
<p><span style="color: #0000ff">import java.sql.SQLException;</span></p>
<p><span style="color: #0000ff">import java.sql.Statement;</span></p>
<p><span style="color: #0000ff">import java.util.Enumeration;</span></p>
<p><span style="color: #0000ff">import java.util.Hashtable;</span></p>
<p><span style="color: #0000ff">import java.util.Vector;</span></p>
<p><span style="color: #0000ff">import javax.naming.Context;</span></p>
<p><span style="color: #0000ff">import javax.naming.InitialContext;</span></p>
<p><span style="color: #0000ff">import javax.sql.DataSource;</span></p>
<p><span style="color: #0000ff">import util.smartDateFormat;</span></p>
<p><span style="color: #0000ff">public class dbManager {</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* @param static private boolean VERBOSE ;</span></p>
<p><span style="color: #0000ff">* @param Statement theStatement;</span></p>
<p><span style="color: #0000ff">* @param PreparedStatement thePstmt;</span></p>
<p><span style="color: #0000ff">* @param Connection theConnection;</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">final static private boolean VERBOSE = true; //打印控制台控制</span></p>
<p><span style="color: #0000ff">//static Logger logger = Logger.getLogger(dbManager.class.getName());</span></p>
<p><span style="color: #0000ff">private Context initCtx = null;</span></p>
<p><span style="color: #0000ff">private Context ctx = null;</span></p>
<p><span style="color: #0000ff">private DataSource ds = null;</span></p>
<p><span style="color: #0000ff">private long timeout = 5000;</span></p>
<p><span style="color: #0000ff">private Statement theStatement = null;</span></p>
<p><span style="color: #0000ff">private PreparedStatement thePstmt = null;</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* 初试化initCtx</span></p>
<p><span style="color: #0000ff">* 取得数据源对象</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">public</span></p>
<p><span style="color: #0000ff">dbManager() {</span></p>
<p><span style="color: #0000ff">try {</span></p>
<p><span style="color: #0000ff">initCtx = new InitialContext();</span></p>
<p><span style="color: #0000ff">//init context，read config web.xml</span></p>
<p><span style="color: #0000ff">if (initCtx == null) {</span></p>
<p><span style="color: #0000ff">throw new Exception("Initial Failed!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">ctx = (Context) initCtx.lookup("java:comp/env");</span></p>
<p><span style="color: #0000ff">//find "jdbc/SqlServerDB" object this configruation in the SERVER.XML of Tomcat</span></p>
<p><span style="color: #0000ff">if (ctx != null) {</span></p>
<p><span style="color: #0000ff">ds = (DataSource) ctx.lookup("jdbc/SqlServerDB");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">if (ds == null) {</span></p>
<p><span style="color: #0000ff">throw new Exception("Look up DataSource Failed!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">catch (Exception e) {</span></p>
<p><span style="color: #0000ff">log(e, "Can't get the Context!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* get Connection</span></p>
<p><span style="color: #0000ff">* @return Connection</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">public synchronized</span></p>
<p><span style="color: #0000ff">Connection getConnection() {</span></p>
<p><span style="color: #0000ff">//get connection and set to delay time</span></p>
<p><span style="color: #0000ff">long startTime = new java.util.Date().getTime();</span></p>
<p><span style="color: #0000ff">Connection con = null;</span></p>
<p><span style="color: #0000ff">while (con == null) {</span></p>
<p><span style="color: #0000ff">con = newConnection();</span></p>
<p><span style="color: #0000ff">if (con != null) {</span></p>
<p><span style="color: #0000ff">//log("Create New Connection!");</span></p>
<p><span style="color: #0000ff">break;</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">try {</span></p>
<p><span style="color: #0000ff">log("连接超时，重新连接，等待" + timeout + "ms");</span></p>
<p><span style="color: #0000ff">wait(timeout);</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">catch (InterruptedException e) {</span></p>
<p><span style="color: #0000ff">log(e, "连接超时!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">if ( (new java.util.Date().getTime() - startTime) &gt;= timeout) {</span></p>
<p><span style="color: #0000ff">log("Connection timeout!");</span></p>
<p><span style="color: #0000ff">break;</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">return con;</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">private</span></p>
<p><span style="color: #0000ff">Connection newConnection() {</span></p>
<p><span style="color: #0000ff">Connection con = null;</span></p>
<p><span style="color: #0000ff">try {</span></p>
<p><span style="color: #0000ff">con = ds.getConnection();</span></p>
<p><span style="color: #0000ff">if (con == null) {</span></p>
<p><span style="color: #0000ff">throw new Exception("Create Connection Failed!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">catch (Exception e) {</span></p>
<p><span style="color: #0000ff">log("Create Connection Failed!");</span></p>
<p><span style="color: #0000ff">System.out.println(e.getMessage());</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">return con;</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* release the connection</span></p>
<p><span style="color: #0000ff">* @param conn Connection</span></p>
<p><span style="color: #0000ff">* @param stmt Statement</span></p>
<p><span style="color: #0000ff">* @param pstmt PreparedStatement</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">public synchronized</span></p>
<p><span style="color: #0000ff">void freeConnection(Connection conn,</span></p>
<p><span style="color: #0000ff">Statement stmt,</span></p>
<p><span style="color: #0000ff">PreparedStatement pstmt) {</span></p>
<p><span style="color: #0000ff">try {</span></p>
<p><span style="color: #0000ff">//close Statement</span></p>
<p><span style="color: #0000ff">if (stmt != null) {</span></p>
<p><span style="color: #0000ff">stmt.close();</span></p>
<p><span style="color: #0000ff">stmt = null;</span></p>
<p><span style="color: #0000ff">//log("Close Statement......");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">//close PreparedStatement</span></p>
<p><span style="color: #0000ff">if (pstmt != null) {</span></p>
<p><span style="color: #0000ff">pstmt.close();</span></p>
<p><span style="color: #0000ff">pstmt = null;</span></p>
<p><span style="color: #0000ff">//log("Close PreparedStatement......");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">catch (Exception e) {</span></p>
<p><span style="color: #0000ff">System.out.println(e.getMessage());</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">try {</span></p>
<p><span style="color: #0000ff">//close Connection</span></p>
<p><span style="color: #0000ff">if (conn != null) {</span></p>
<p><span style="color: #0000ff">conn.close();</span></p>
<p><span style="color: #0000ff">conn = null;</span></p>
<p><span style="color: #0000ff">//log("Close Connection......");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">catch (SQLException e) {</span></p>
<p><span style="color: #0000ff">log(e, "释放资源出错!");</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* write log file.</span></p>
<p><span style="color: #0000ff">* @param s String</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">private</span></p>
<p><span style="color: #0000ff">void log(String s) {</span></p>
<p><span style="color: #0000ff">if (VERBOSE) {</span></p>
<p><span style="color: #0000ff">System.out.println(new java.util.Date() + ":" + s);</span></p>
<p><span style="color: #0000ff">//logger.info(new java.util.Date()+s);</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* write log file.</span></p>
<p><span style="color: #0000ff">* @param ex Object</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">private</span></p>
<p><span style="color: #0000ff">void logerr(Object ex) {</span></p>
<p><span style="color: #0000ff">if (VERBOSE) {</span></p>
<p><span style="color: #0000ff">//System.out.println(new java.util.Date()+":"+s);</span></p>
<p><span style="color: #0000ff">//logger.error(ex);</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">/************************************</span></p>
<p><span style="color: #0000ff">* write log file.</span></p>
<p><span style="color: #0000ff">* @param e Throwable</span></p>
<p><span style="color: #0000ff">* @param msg String</span></p>
<p><span style="color: #0000ff">************************************/</span></p>
<p><span style="color: #0000ff">private</span></p>
<p><span style="color: #0000ff">void log(Throwable e, String msg) {</span></p>
<p><span style="color: #0000ff">System.out.println(new java.util.Date() + ": " + msg);</span></p>
<p><span style="color: #0000ff">//logger.info(new java.util.Date() + ": " + msg, e);</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">&#8230;&#8230;</span></p>
<p><span style="color: #0000ff">}</span></p>
<p><span style="color: #0000ff">OK，你现在可以方便的使用连接池了，想要一个得一个，记得要释放哦，连接池的数量总是有限的。</span></p>
<p><span style="color: #0000ff">二、中文问题照样很简单</span></p>
<p><span style="color: #0000ff">每个国家（或区域）都规定了计算机信息交换用的字符编码集，如美国的扩展 ASCII码, 中国的 GB2312-80，日本的 JIS 等，作为该国家/区域内信息处理的基础，有着统一编码的重要作用。字符编码集按长度分为 SBCS（单字节字符集），DBCS（双字节字符集）两大类。早期的软件（尤其是操作系统），为了解决本地字符信息的计算机处理，出现了各种本地化版本（L10N），为了区分，引进了 LANG, Codepage 等概念。但是由于各个本地字符集代码范围重叠，相互间信息交换困难；软件各个本地化版本独立维护成本较高。因此有必要将本地化工作中的共性抽取出来，作一致处理，将特别的本地化处理内容降低到最少。这也就是所谓的国际化（I18N）。各种语言信息被进一步规范为 Locale 信息。处理的底层字符集变成了几乎包含了所有字形的 Unicode。</span></p>
<p><span style="color: #0000ff">现在大部分具有国际化特征的软件核心字符处理都是以 Unicode 为基础的，在软件运行时根据当时的 Locale/Lang/Codepage 设置确定相应的本地字符编码设置，并依此处理本地字符。在处理过程中需要实现 Unicode 和本地字符集的相互转换，甚或以 Unicode 为中间的两个不同本地字符集的相互转换。这种方式在网络环境下被进一步延伸，任何网络两端的字符信息也需要根据字符集的设置转换成可接受的内容。</span></p>
<p><span style="color: #0000ff">Java 语言内部是用 Unicode 表示字符的，遵守 Unicode V2.0。Java 程序无论是从/往文件系统以字符流读/写文件，还是往 URL 连接写 HTML 信息，或从 URL 连接读取参数值，都会有字符编码的转换。这样做虽然增加了编程的复杂度，容易引起混淆，但却是符合国际化的思想的。从理论上来说，这些根据字符集设置而进行的字符转换不应该产生太多问题。而事实是由于应用程序的实际运行环境不同，Unicode 和各个本地字符集的补充、完善，以及系统或应用程序实现的不规范，转码时出现的问题时时困扰着程序员和用户。</span></p>
<p><span style="color: #0000ff">其实解决 JAVA 程序中的汉字编码问题的方法往往很简单，但理解其背后的原因，定位问题，还需要了解现有的汉字编码和编码转换。相信这样的东西大家都见过了</span></p>
<p><span style="color: #0000ff">new String(request.getParameter("test").getBytes("iso-8859-1"),"GBK")</span></p>
<p><span style="color: #0000ff">但这样的代码相信不是一个解决的办法，这样会增加程序的复杂度，写数据库，提交表单，URL中传中文参数，到处都是中文问题！作为一个连走路都要算计最短距离的懒人，当然不愿天天叨念着new String(request.getParameter("test").getBytes("iso-8859-1"),"GBK")，然汉战战兢兢的处理各种字符转换的问题，我跋山涉水，翻山越岭，终于找到了完美的解决方式，在TOMCAT中只需要简单的配置，引入2个文件就可以轻松搞定。</span></p>
<p><span style="color: #0000ff">前提条件，每个页面使用</span></p>
<p><span style="color: #0000ff">&lt;%@ page contentType="text/html; CHARSET=utf8" language="java" import="java.sql.*" errorPage="" %&gt;</span></p>
<p><span style="color: #0000ff">&lt;meta http-equiv="Content-Type" content="text/html; CHARSET=utf8"&gt;</span></p>
<p><span style="color: #0000ff">地球人都知道的东西。</span></p>
<p><span style="color: #0000ff">步骤1：添加过滤器</span></p>
<p><span style="color: #0000ff">在TOMCAT中找到这2个文件RequestDumperFilter.java， SetCharacterEncodingFilter.java，他们位于D:\Tomcat5.0.27\webapps\jsp-examples \WEB-INF\classes\filters，加到你的工程文件里去，编译他们。</span></p>
<p><span style="color: #0000ff">步骤2：配置WEB.XML</span></p>
<p><span style="color: #0000ff">在web.xml里加入这一段</span></p>
<p><span style="color: #0000ff">&#8230;&#8230;</span></p>
<p><span style="color: #0000ff">&lt;filter&gt;</span></p>
<p><span style="color: #0000ff">&lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;</span></p>
<p><span style="color: #0000ff">&lt;filter-class&gt;filters.SetCharacterEncodingFilter&lt;/filter-class&gt;</span></p>
<p><span style="color: #0000ff">&lt;init-param&gt;</span></p>
<p><span style="color: #0000ff">&lt;param-name&gt;encoding&lt;/param-name&gt;</span></p>
<p><span style="color: #0000ff">&lt;param-value&gt;GBK&lt;/param-value&gt;</span></p>
<p><span style="color: #0000ff">&lt;/init-param&gt;</span></p>
<p><span style="color: #0000ff">&lt;/filter&gt;</span></p>
<p><span style="color: #0000ff">&lt;filter-mapping&gt;</span></p>
<p><span style="color: #0000ff">&lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;</span></p>
<p><span style="color: #0000ff">&lt;url-pattern&gt;/*&lt;/url-pattern&gt;</span></p>
<p><span style="color: #0000ff">&lt;/filter-mapping&gt;</span></p>
<p><span style="color: #0000ff">&#8230;&#8230;</span></p>
<p><span style="color: #0000ff">看到没有？这样你就不用写那些麻烦的转换代码了，当然这样还不足以解决问题。</span></p>
<p><span style="color: #0000ff">步骤3：修改server.xml</span></p>
<p><span style="color: #0000ff">在server.xml修改2个地方</span></p>
<p><span style="color: #0000ff">&lt;Connector port="8080"</span></p>
<p><span style="color: #0000ff">maxThreads="150" minSpareThreads="25" maxSpareThreads="75"</span></p>
<p><span style="color: #0000ff">enableLookups="false" redirectPort="8443" acceptCount="100"</span></p>
<p><span style="color: #0000ff">debug="0" connectionTimeout="20000" </span></p>
<p><span style="color: #0000ff">disableUploadTimeout="true" URIEncoding='GBK'/&gt;</span></p>
<p><span style="color: #0000ff">&lt;Connector className="org.apache.coyote.tomcat5.CoyoteConnector"</span></p>
<p><span style="color: #0000ff">port="8009" minProcessors="5" maxProcessors="75"</span></p>
<p><span style="color: #0000ff">enableLookups="true" redirectPort="8443"</span></p>
<p><span style="color: #0000ff">acceptCount="10" debug="0" connectionTimeout="0"</span></p>
<p><span style="color: #0000ff">useURIValidationHack="false" protocol="AJP/1.3"</span></p>
<p><span style="color: #0000ff">protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler" </span></p>
<p><span style="color: #0000ff">URIEncoding='GBK'/&gt;</span></p>
<p><span style="color: #0000ff">OK，搞定！</span></p>
<p><span style="color: #0000ff">三、APACHE和TOMCAT他们俩关系非同一般</span></p>
<p><span style="color: #0000ff">Apache和tomcat都是很优秀的软件，更可贵的是它们是免费的。其实他们2个都是jakarta项目的重要组成部分。按辈分来讲， TOMCAT是APACHE的儿子，APACHE的专长是解析静态文件，CGI,PHP&#8230;&#8230;图片&#8230;&#8230;，儿子当然不能抢了老爹的饭碗，所以TOMCAT只有在J2EE这个上面发愤图强，其实TOMCAT并非不能干他老爹的活，只是稳定性差点而已（偶没有明显的感觉，可能是商业炒作吧），现在大家明白为什么把他们2个扯一起了吧，上阵还靠父子兵呢～</span></p>
<p><span style="color: #0000ff">把2个家伙整一起有大致有2种方法，一种是利用mod_jk2.so，一种是利用mod_jk_1.2.5_2.0.47.dll。这2个东东叫联接器（TOMCAT就是通过这家伙与apache勾搭上的）</span></p>
<p><span style="color: #0000ff">1、 利用mod_jk_1.2.5_2.0.47.dll在WINDOWS下整合</span></p>
<p><span style="color: #0000ff">步骤1：准备材料</span></p>
<p><span style="color: #0000ff">apache2.0.52</span></p>
<p><a href="http://apache.te8.com/dist/httpd/binaries/win32/apache_2.0.52-win32-x86-no_ssl.msi" target="blank"><span style="color: #0000ff">http://apache.te8.com/dist/httpd/binaries/win32/apache_2.0.52-win32-x86-no_ssl.msi</span></a></p>
<p><span style="color: #0000ff">tomcat5.0.27</span></p>
<p><a href="http://apache.linuxforum.net/dist/jakarta/tomcat-5/v5.0.19/bin/jakarta-tomcat-5.0.27.exe" target="blank"><span style="color: #0000ff">http://apache.linuxforum.net/dist/jakarta/tomcat-5/v5.0.19/bin/jakarta-tomcat-5.0.27.exe</span></a></p>
<p><span style="color: #0000ff">JDK（这个不用说了吧^_^）</span></p>
<p><span style="color: #0000ff">mod_jk_1.2.5_2.0.47.dll（关键是这个东东啊，找了我N久），据说在下面连接可以下到，最后在我同事那找到的。</span></p>
<p><a href="http://apache.linuxforum.net/dist/jakarta/tomcat-connectors/jk/binaries/win32/mod_jk_1.2.5_2.0.47.dll" target="blank"><span style="color: #0000ff">http://apache.linuxforum.net/dist/jakarta/tomcat-connectors/jk/binaries/win32/mod_jk_1.2.5_2.0.47.dll</span></a></p>
<p><span style="color: #0000ff">安装apache\ tomcat\JDK。</span></p>
<p><span style="color: #0000ff">步骤2：安装后设置环境变量</span></p>
<p><span style="color: #0000ff">设置我的电脑\属性\高级\环境变量\新建系统变量　变量名：JAVA_HOME 变量值：C:\JBuilderX\jdk1.4 (指向JDK的实际安装路径)；TOMCAT_HMOM 变量值：Tomcat5.0.27；lasspath 编辑变量值中加上　&#8230;&#8230;;%JAVA_HOME%\bin;%JAVA_HOME%\lib;%TOMCAT_HOME%\bin;.;</span></p>
<p><span style="color: #0000ff">测试一下，访问http://localhost和http://localhost:8080，默认安装是不会有什么错误的^_^</span></p>
<p><span style="color: #0000ff">把连接器mod_jk_1.2.5_2.0.47.dll　COPY到D:\Apache2\modules\下。</span></p>
<p><span style="color: #0000ff">步骤3：apache配置</span></p>
<p><span style="color: #0000ff">在d:\Apache2\conf下找到httpd.conf，找到DirectoryIndex，在index.html后添加index.jsp；查找&#8220;listen&#8221;用于本机测试时：Listen 127.0.0.1:80，我的是这样设置的Listen *:80</span></p>
<p><span style="color: #0000ff">查找AddDefaultCharset设置为AddDefaultCharset off，这样APACHE将以你页面定义的字符集解析页面。</span></p>
<p><span style="color: #0000ff">在最后添加如下代码：</span></p>
<p><span style="color: #0000ff">&lt;VirtualHost *:80&gt; #localhost为本机，你可用本机ip</span></p>
<p><span style="color: #0000ff">ServerAdmin darkxie@hotmail.com #你的mail地址</span></p>
<p><span style="color: #0000ff">DocumentRoot F:/uutang/uutang #你的项目组根目录</span></p>
<p><span style="color: #0000ff">ServerName dark #你的服务名，若你的机器有域名，设为域名</span></p>
<p><span style="color: #0000ff">ErrorLog logs/ErrorLog.txt #错误日志</span></p>
<p><span style="color: #0000ff">CustomLog logs/CustomLog.txt common #访问日志</span></p>
<p><span style="color: #0000ff">JkMount /servlet/* ajp13 #让Apache支持对servlet传送，用以Tomcat解析</span></p>
<p><span style="color: #0000ff">JkMount /*.jsp ajp13 #让Apache支持对jsp传送，用以Tomcat解析</span></p>
<p><span style="color: #0000ff">JkMount /*.do ajp13 #让Apache支持对struts的action传送，用以Tomcat解析</span></p>
<p><span style="color: #0000ff">&lt;/VirtualHost&gt;</span></p>
<p><span style="color: #0000ff">LoadModule jk_module modules/mod_jk_1.2.5_2.0.47.dll</span></p>
<p><span style="color: #0000ff">JkWorkersFile "D:/Tomcat5.0.27/conf/workers.properties"</span></p>
<p><span style="color: #0000ff">JkLogFile "D:/Tomcat5.0.27/logs/mod_jk2.log"</span></p>
<p><span style="color: #0000ff">JkLogLevel info</span></p>
<p><span style="color: #0000ff">步骤4：tomcat配置</span></p>
<p><span style="color: #0000ff">在d:\Tomcat5\conf下新建一个workers.properties文件 .内容如下: </span></p>
<p><span style="color: #0000ff">workers.tomcat_home=d:\Tomcat5 #让mod_jk模块知道Tomcat</span></p>
<p><span style="color: #0000ff">workers.java_home=d:\jdk1.3 #让mod_jk模块知道j2sdk</span></p>
<p><span style="color: #0000ff">ps=\ </span></p>
<p><span style="color: #0000ff">worker.list=ajp13 #模块版本,现有ajp13了,不要修改</span></p>
<p><span style="color: #0000ff">worker.ajp13.port=8009 #工作端口,若没占用则不用修改</span></p>
<p><span style="color: #0000ff">worker.ajp13.host=localhost #主机,若上面的Apache主机不为localhost,作相应修改</span></p>
<p><span style="color: #0000ff">worker.ajp13.type=ajp13 #类型</span></p>
<p><span style="color: #0000ff">worker.ajp13.lbfactor=1 #代理数,不用修改</span></p>
<p><span style="color: #0000ff">修改TOMCAT的server.xml文件：</span></p>
<p><span style="color: #0000ff">&lt;!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 --&gt;</span></p>
<p><span style="color: #0000ff">&lt;Connector className="org.apache.coyote.tomcat5.CoyoteConnector"</span></p>
<p><span style="color: #0000ff">port="8009" minProcessors="5" maxProcessors="75"</span></p>
<p><span style="color: #0000ff">enableLookups="true" redirectPort="8443"</span></p>
<p><span style="color: #0000ff">acceptCount="10" debug="0" connectionTimeout="0"</span></p>
<p><span style="color: #0000ff">useURIValidationHack="false" protocol="AJP/1.3"</span></p>
<p><span style="color: #0000ff">protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler" </span></p>
<p><span style="color: #0000ff">URIEncoding='GBK'/&gt;</span></p>
<p><span style="color: #0000ff">让TOMCAT知道ajp13协议，apache和tomcat俩父子间靠这个协议沟通。</span></p>
<p><span style="color: #0000ff">测试一下，访问http://localhost和http://localhost:8080，看到相同的页面没有？细心点，其实很简单，看看E文的帮助，搞定不成问题。</span></p>
<p><span style="color: #0000ff">2、 利用mod_jk2.so（也叫JK2）整合</span></p>
<p><span style="color: #0000ff">jk2是一个jakarta-tomcat-connectors-jk2.0.4-win32-apache2.0.49.zip文件，主要用的是其中的mod_jk2.so。其实利用mod_jk2.so整合和利用mod_jk_1.2.5_2.0.47.dll整合大同小异，只是换了个联接器而已，现在一步一步整起来～</span></p>
<p><span style="color: #0000ff">步骤1：没有多说的，安装好TOMCAT和APACHE</span></p>
<p><span style="color: #0000ff">下载jakarta-tomcat-connectors-jk2.0.4-win32-apache2.0.49.zip，解压，将mod_jk2放到apache的安装文件夹下的modules文件夹中。</span></p>
<p><span style="color: #0000ff">步骤2：apache配置</span></p>
<p><span style="color: #0000ff">在/conf中加入一个work.properties文件，其内容如下：</span></p>
<p><span style="color: #0000ff">&lt;!--这个文件的作用不是很清楚，总之路径设置正确就行了。我的apache装在D:/Apache2，根据情况自己修改。--&gt;</span></p>
<p><span style="color: #0000ff">[shm]</span></p>
<p><span style="color: #0000ff">file=D:/ /Apache2/logs/shm.file</span></p>
<p><span style="color: #0000ff">size=1048576</span></p>
<p><span style="color: #0000ff">&lt;!--这个socket channel是必须的，port和host对应于tomcat端的设置。--&gt;</span></p>
<p><span style="color: #0000ff">#The socket channel</span></p>
<p><span style="color: #0000ff">[channel.socket:localhost:8009]</span></p>
<p><span style="color: #0000ff">port=8009</span></p>
<p><span style="color: #0000ff">host=localhost</span></p>
<p><span style="color: #0000ff">&lt;!--worker，必须的。--&gt;</span></p>
<p><span style="color: #0000ff">#define the worker</span></p>
<p><span style="color: #0000ff">[ajp13:localhost:8009]</span></p>
<p><span style="color: #0000ff">channel=channel.socket:localhost:8009</span></p>
<p><span style="color: #0000ff">&lt;!--url mapping，我的主要是.jsp和struts的.do，servlet的话设置成[uri:/xxx/*]之类的。--&gt;</span></p>
<p><span style="color: #0000ff">#uri mapping</span></p>
<p><span style="color: #0000ff">[uri:/*] #和第一种方式一样吧^_^</span></p>
<p><span style="color: #0000ff">[uri:/*.jsp]</span></p>
<p><span style="color: #0000ff">[uri:/*.do]</span></p>
<p><span style="color: #0000ff">worker=ajp13:localhost:8009</span></p>
<p><span style="color: #0000ff">在httpd.conf中，在LoadModule那里加入这句：</span></p>
<p><span style="color: #0000ff">LoadModule jk2_module modules/mod_jk2.so </span></p>
<p><span style="color: #0000ff">在最后加入这句：</span></p>
<p><span style="color: #0000ff">JkSet config.file "conf/work.properties"</span></p>
<p><span style="color: #0000ff">这是告诉apache去哪里找jk的配置的，根据具体情况修改。</span></p>
<p><span style="color: #0000ff">还要修改一下DirectoryIndex，DirectoryIndex index.html index.html.var index.jsp查找&#8220;listen&#8221;用于本机测试时：Listen 127.0.0.1:80，我的是这样设置的Listen *:80。</span></p>
<p><span style="color: #0000ff">当然还有我们的虚拟目录：</span></p>
<p><span style="color: #0000ff">&lt;VirtualHost *:80&gt;</span></p>
<p><span style="color: #0000ff">ServerAdmin darkxie@hotmail.com</span></p>
<p><span style="color: #0000ff">DocumentRoot F:/uutang/uutang</span></p>
<p><span style="color: #0000ff">ServerName dark</span></p>
<p><span style="color: #0000ff">ErrorLog logs/ErrorLog.txt</span></p>
<p><span style="color: #0000ff">CustomLog logs/CustomLog.txt common</span></p>
<p><span style="color: #0000ff">#JkMount /servlet/* ajp13</span></p>
<p><span style="color: #0000ff">#JkMount /*.jsp ajp13</span></p>
<p><span style="color: #0000ff">#JkMount /*.do ajp13</span></p>
<p><span style="color: #0000ff">&lt;/VirtualHost&gt;</span></p>
<p><span style="color: #0000ff">步骤3：tomcat配置</span></p>
<p><span style="color: #0000ff">Tomcat的端口设置为8080。</span></p>
<p><span style="color: #0000ff">在/conf文件夹加入jk2.properties文件，其内容如下：</span></p>
<p><span style="color: #0000ff"># Set the desired handler list</span></p>
<p><span style="color: #0000ff">handler.list=apr,request,channelSocket</span></p>
<p><span style="color: #0000ff">#</span></p>
<p><span style="color: #0000ff"># Override the default port for the socketChannel</span></p>
<p><span style="color: #0000ff">channelSocket.port=8009</span></p>
<p><span style="color: #0000ff">TOMCAT自己已经生成了这个文件，找到相关的地方把注视去掉改一下就成。</span></p>
<p><span style="color: #0000ff">注意：用这种方式整合最好是自己编译mod_jk2.so文件，特别是在unix/linux下,我没有环境，制作mod_webapp.so没有自己作过。具体方法，自己去找吧</span></p>
<img src ="http://www.blogjava.net/sutao/aggbug/162781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-24 09:10 <a href="http://www.blogjava.net/sutao/archive/2007/11/24/162781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat性能调整</title><link>http://www.blogjava.net/sutao/articles/162665.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Fri, 23 Nov 2007 08:27:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162665.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162665.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162665.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162665.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162665.html</trackback:ping><description><![CDATA[<div class="postTitle"><a href="http://blog.csdn.net/avery_leo/archive/2007/11/16/1889227.aspx"><span style="color: #0000ff">Tomcat性能调整 </span></a><span style="color: #0000ff">&nbsp;&nbsp; <script src="http://blog.csdn.net/count.aspx?ID=1889227&amp;Type=Rank"></script><img title="文章指数:0" alt="文章指数:0" src="http://blog.csdn.net/images/star_0.gif" border="0" />&nbsp;&nbsp;<img title="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" alt="CSDN Blog推出文章指数概念，文章指数是对Blog文章综合评分后推算出的，综合评分项分别是该文章的点击量，回复次数，被网摘收录数量，文章长度和文章类型；满分100，每月更新一次。" src="http://blog.csdn.net/images/ask.gif" border="0" /> </span></div>
<div class="postText">
<p><br />
<span style="color: #0000ff">一. 引言<br />
性能测试与分析是软件开发过程中介于架构和调整的一个广泛并比较不容易理解的领域，更是一项较为复杂的活动。就像下棋游戏一样，有效的性能测试和分析只能在一个良好的计划策略和具备了对不可预料事件的处理能力的条件下顺利地完成。一个下棋高手赢得比赛靠的不仅仅是对游戏规则的认识，更是靠他的自己的能力和不断地专注于分析自己对手的实力来更加有效地利用和发挥规则的作用。同样一个优秀的性能测试和分析人员将要面对的是来自一个全新的应用程序和环境下带来的整个项目的挑战。本文中作者结合自己的使用经验和参考文档，对Tomcat性能方面的调整做一简要的介绍，并给出Tomcat性能的测试、分析和调整优化的一些方法。</span></p>
<p><span style="color: #0000ff">二. 测量Web服务器的性能<br />
测量web服务器的性能是一项让人感到畏缩的任务，但是我们在这里将给出一些需要注意的地方并且指点你了解其中更多的细节性的内容。它不像一些简单的任务，如测量CPU的速率或者是测量程序占用CPU的比例，web服务器的性能优化中包括许调整许多变量来达到目标。许多的测量策略中都包含了一个看似简单的浏览实际上是在向服务器发送大量的请求，我们称之为客户端的程序，来测量响应时间。客户端和服务器端是在同一台机器上吗？服务器在测试的时候还运行着其它的什么程序吗？客户端和服务器端的通讯是通过局域网，100baseT，10baseT还是使用调制解调器？客户端是否一直重复请求相同的页面，还是随机地访问不同的页面？（这些影响到了服务缓存的性能）客户端发送请求的有规律的还是突发的？你是在最终的配置环境下运行服务的还是在调试的配置环境下运行服务的？客户端请求中包含图片还是只有HTML页面？是否有请求是通过servlets和 JSP的，CGI程序，服务端包含（Server-Side Includes ，SSI是一个可以让你使用动态HTML文件的技术）？所有这些都将是我们要关心的，并且几乎我们不可能精确地把所有的问题都清楚地列出来。</span></p>
<p><span style="color: #0000ff">1.压力测试工具</span></p>
<p><span style="color: #0000ff">&#8220;工欲善其事，必先利其器&#8221;，压力测试只有借助于一些工具才可得以实施。</span></p>
<p><span style="color: #0000ff">大多数web压力测试工具的实现原理都是通过重复的大量的页面请求来模拟多用户对被测系统的并发访问，以此达到产生压力的目的。产生压力的手段都是通过录制或者是编写压力脚本，这些脚本以多个进程或者线程的形式在客户端运行，这样通过人为制造各种类型的压力，我们可以观察被测系统在各种压力状况下的表现，从而定位系统瓶颈，作为系统调优的基础。目前已经存在的性能测试工具林林总总，数量不下一百种，从单一的开放源码的免费小工具如 Aapache 自带的 web 性能测试工具 Apache Benchmark、开源的Jmeter 到大而全的商业性能测试软件如 Mercury 的 LoadRunner 等等。任何性能测试工具都有其优缺点，我们可以根据实际情况挑选用最合适的工具。您可以在这里找到一些web压力测试工具</span><a href="http://www.softwareqatest.com/qatweb1.html#LOAD"><span style="color: #0000ff">http://www.softwareqatest.com/qatweb1.html#LOAD</span></a></p>
<p><span style="color: #0000ff">这里我们所使用的工具要支持web应用服务认证才可以，要支持接收发送cookies，不仅如此Tomcat支持多种认证方式，比如基本认证、基于表单的认证、相互认证和客户端认证，而一些工具仅仅支持HTTP基本认证。真实地模拟用户认证是性能测试工具的一个重要的部分，因为认证机制将对一个web站点的性能特征产生重要的影响。基于你在产品中使用的不同的认证方式，你需要从上面的工具列表中选择使用这种特性的测试工具。</span></p>
<p><span style="color: #0000ff">Apache Benchmark和http_load是命令行形式的工具，非常易于使用。Apache Benchmark可以模仿单独的URL请求并且重复地执行，可以使用不同的命令行参数来控制执行迭代的次数，并发用户数等等。它的一个特点是可以周期性地打印出处理过程的信息，而其它工具只能给出一个全局的报告。</span></p>
<p><span style="color: #0000ff">2.压力测试工具介绍</span></p>
<p><span style="color: #0000ff">三. 外部环境的调整<br />
在Tomcat 和应用程序进行了压力测试后，如果您对应用程序的性能结果不太满意，就可以采取一些性能调整措施了，当然了前提是应用程序没有问题，我们这里只讲 Tomcat的调整。由于Tomcat的运行依赖于JVM，所以在这里我们把Tomcat的调整可以分为两类来详细描述：</span></p>
<p><span style="color: #0000ff">　　外部环境调整 </span></p>
<p><span style="color: #0000ff">　　调整非Tomcat组件，例如Tomcat运行的操作系统和运行Tomcat的java虚拟机。</span></p>
<p><span style="color: #0000ff">　　自身调整 </span></p>
<p><span style="color: #0000ff">　　修改Tomcat自身的参数，调整Tomcat配置文件中的参数。</span></p>
<p><span style="color: #0000ff">　　下面我们将详细讲解外部环境调整的有关内容，Tomcat自身调整的内容将在第2部分中阐述。1.JAVA虚拟机性能优化</span></p>
<p><span style="color: #0000ff">　　Tomcat本身不能直接在计算机上运行，需要依赖于硬件基础之上的操作系统和一个java虚拟机。您可以选择自己的需要选择不同的操作系统和对应的 JDK的版本（只要是符合Sun发布的Java规范的），但我们推荐您使用Sun公司发布的JDK。确保您所使用的版本是最新的，因为Sun公司和其它一些公司一直在为提高性能而对java虚拟机做一些升级改进。一些报告显示JDK1.4在性能上比JDK1.3提高了将近10%到20%。</span></p>
<p><span style="color: #0000ff">　　可以给Java虚拟机设置使用的内存，但是如果你的选择不对的话，虚拟机不会补偿。可通过命令行的方式改变虚拟机使用内存的大小。如下表所示有两个参数用来设置虚拟机使用内存的大小。<br />
参数<br />
&nbsp;描述<br />
&nbsp;<br />
-Xms&lt;size&gt;<br />
&nbsp;JVM初始化堆的大小<br />
&nbsp;<br />
-Xmx&lt;size&gt;<br />
&nbsp;JVM堆的最大值<br />
&nbsp;</span></p>
<p><br />
<span style="color: #0000ff">　　这两个值的大小一般根据需要进行设置。初始化堆的大小执行了虚拟机在启动时向系统申请的内存的大小。一般而言，这个参数不重要。但是有的应用程序在大负载的情况下会急剧地占用更多的内存，此时这个参数就是显得非常重要，如果虚拟机启动时设置使用的内存比较小而在这种情况下有许多对象进行初始化，虚拟机就必须重复地增加内存来满足使用。由于这种原因，我们一般把-Xms和-Xmx设为一样大，而堆的最大值受限于系统使用的物理内存。一般使用数据量较大的应用程序会使用持久对象，内存使用有可能迅速地增长。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出，并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值的80%。</span></p>
<p><span style="color: #0000ff">　　Tomcat默认可以使用的内存为128MB，在较大型的应用项目中，这点内存是不够的，需要调大。</span></p>
<p><span style="color: #0000ff">　　Windows下，在文件{tomcat_home}/bin/catalina.bat，Unix下，在文件{tomcat_home}/bin/catalina.sh的前面，增加如下设置：</span></p>
<p><span style="color: #0000ff">　　JAVA_OPTS='-Xms【初始化内存大小】 -Xmx【可以使用的最大内存】'</span></p>
<p><span style="color: #0000ff">　　需要把这个两个参数值调大。例如：</span></p>
<p><span style="color: #0000ff">　　JAVA_OPTS='-Xms256m -Xmx512m'</span></p>
<p><span style="color: #0000ff">　　表示初始化内存为256MB，可以使用的最大内存为512MB。</span></p>
<p><span style="color: #0000ff">　　另外需要考虑的是Java提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾可以接受的速度与应用有关，应该通过分析实际的垃圾收集的时间和频率来调整。如果堆的大小很大，那么完全垃圾收集就会很慢，但是频度会降低。如果你把堆的大小和内存的需要一致，完全收集就很快，但是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间，以在特定的时间内最大化处理客户的请求。在基准测试的时候，为保证最好的性能，要把堆的大小设大，保证垃圾收集不在整个基准测试的过程中出现。</span></p>
<p><span style="color: #0000ff">　　如果系统花费很多的时间收集垃圾，请减小堆大小。一次完全的垃圾收集应该不超过 3-5 秒。如果垃圾收集成为瓶颈，那么需要指定代的大小，检查垃圾收集的详细输出，研究 垃圾收集参数对性能的影响。一般说来，你应该使用物理内存的 80% 作为堆大小。当增加处理器时，记得增加内存，因为分配可以并行进行，而垃圾收集不是并行的。</span></p>
<p><span style="color: #0000ff">2.操作系统性能优化</span></p>
<p><span style="color: #0000ff">　　这里说的操作系统是指运行web服务器的系统软件，当然，不同的操作系统是为不同的目的而设计的。比如OpenBSD是面向安全的，因此在它的内核中有许多的限制来防止不同形式的服务攻击（OpenBSD的一句座右铭是&#8220;默认是最安全的&#8221;）。这些限制或许更多地用来运行活跃的web服务器。</span></p>
<p><span style="color: #0000ff">　　而我们常用的Linux操作系统的目标是易用使用，因此它有着更高的限制。使用BSD内核的系统都带有一个名为&#8220;Generic&#8221;的内核，表明所有的驱动器都静态地与之相连。这样就使系统易于使用，但是如果你要创建一个自定义的内核来加强其中某些限制，那就需要排除不需要的设备。Linux内核中的许多驱动都是动态地加载的。但是换而言之，内存现在变得越来越便宜，所以因为加载额外的设备驱动就显得不是很重要的。重要的是要有更多的内存，并且在服务器上腾出更多的可用内存。</span></p>
<p><span style="color: #0000ff">　　小提示：虽然现在内存已经相当的便宜，但还是尽量不要购买便宜的内存。那些有牌子的内存虽然是贵一点，但是从可靠性上来说，性价比会更高一些。</span></p>
<p><span style="color: #0000ff">　　如果是在Windows操作系统上使用Tomcat，那么最好选择服务器版本。因为在非服务器版本上，最终用户授权数或者操作系统本身所能承受的用户数、可用的网络连接数或其它方面的一些方面都是有限制的。并且基于安全性的考虑，必须经常给操作系统打上最新的补丁。</span></p>
<p><span style="color: #0000ff">　　3.Tomcat与其它web服务器整合使用</span></p>
<p><span style="color: #0000ff">　　虽然tomcat也可以作web服务器,但其处理静态html的速度比不上apache,且其作为web服务器的功能远不如apache,因此我们想把 apache和tomcat集成起来，将html与jsp的功能部分进行明确分工，让tomcat只处理jsp部分，其它的由apache,IIS等这些 web服务器处理，由此大大节省了tomcat有限的工作&#8220;线程&#8221;。</span></p>
<p><span style="color: #0000ff">　　4.负载均衡</span></p>
<p><span style="color: #0000ff">　　在负载均衡的思路下，多台服务器为对称方式，每台服务器都具有同等的地位，可以单独对外提供服务而无须其他服务器的辅助。通过负载分担技术，将外部发送来的请求按一定规则分配到对称结构中的某一台服务器上，而接收到请求的服务器都独立回应客户机的请求。</span></p>
<p><span style="color: #0000ff">　　提供服务的一组服务器组成了一个应用服务器集群(cluster)，并对外提供一个统一的地址。当一个服务请求被发至该集群时，根据一定规则选择一台服务器，并将服务转定向给该服务器承担，即将负载进行均衡分摊。</span></p>
<p><span style="color: #0000ff">　　通过应用负载均衡技术，使应用服务超过了一台服务器只能为有限用户提供服务的限制，可以利用多台服务器同时为大量用户提供服务。当某台服务器出现故障时，负载均衡服务器会自动进行检测并停止将服务请求分发至该服务器，而由其他工作正常的服务器继续提供服务，从而保证了服务的可靠性。</span></p>
<p><span style="color: #0000ff">　　负载均衡实现的方式大概有四种：第一是通过DNS，但只能实现简单的轮流分配，不能处理故障，第二如果是基于MS IIS，Windows 2003 server本身就带了负载均衡服务，第三是硬件方式，通过交换机的功能或专门的负载均衡设备可以实现，第四种是软件方式，通过一台负载均衡服务器进行，上面安装软件。使用Apache Httpd Server做负载平衡器，Tomcat集群节点使用Tomcat就可以做到以上第四种方式。这种方式比较灵活，成本相对也较低。另外一个很大的优点就是可以根据应用的情况和服务器的情况采取一些策略。 </span></p>
<p><span style="color: #0000ff">四. 自身调整<br />
本节将向您详细介绍一些加速可使Tomcat实例加速运行的技巧和方法，无论是在什么操作系统或者何种Java虚拟机上。在有些情况下，您可能没有控制部署环境上的操作系统或者Java虚拟机。在这种情况下，您就需要逐行了解以下的的一些建议，然而你应该在修改后使之生效。我认为以下方法是Tomcat性能自身调整的最佳方式。</span></p>
<p><span style="color: #0000ff">　　1.禁用DNS查询</span></p>
<p><span style="color: #0000ff">　　当web应用程序向要记录客户端的信息时，它也会记录客户端的IP地址或者通过域名服务器查找机器名转换为IP地址。DNS查询需要占用网络，并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程，这样会消耗一定的时间。为了消除DNS查询对性能的影响我们可以关闭DNS查询，方式是修改server.xml文件中的enableLookups参数值：</span></p>
<p><br />
<span style="color: #0000ff">Tomcat4</span></p>
<p><span style="color: #0000ff">&lt;Connector className="org.apache.coyote.tomcat4.CoyoteConnector" port="80" minProcessors="5" maxProcessors="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" useURIValidationHack="false" disableUploadTimeout="true" /&gt;</span></p>
<p><span style="color: #0000ff">Tomcat5</span></p>
<p><span style="color: #0000ff">&lt;Connector port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true"/&gt;</span></p>
<p><br />
<span style="color: #0000ff">　　除非你需要连接到站点的每个HTTP客户端的机器名，否则我们建议在生产环境上关闭DNS查询功能。可以通过Tomcat以外的方式来获取机器名。这样不仅节省了网络带宽、查询时间和内存，而且更小的流量会使日志数据也会变得更少，显而易见也节省了硬盘空间。对流量较小的站点来说禁用DNS查询可能没有大流量站点的效果明显，但是此举仍不失为一良策。谁又见到一个低流量的网站一夜之间就流量大增呢？</span></p>
<p><span style="color: #0000ff">　　2.调整线程数</span></p>
<p><span style="color: #0000ff">　　另外一个可通过应用程序的连接器（Connector）进行性能控制的的参数是创建的处理请求的线程数。Tomcat使用线程池加速响应速度来处理请求。在 Java中线程是程序运行时的路径，是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序，使空闲时间保持最低，从而接受更多的请求。</span></p>
<p><span style="color: #0000ff">　　Tomcat4中可以通过修改minProcessors和 maxProcessors的值来控制线程数。这些值在安装后就已经设定为默认值并且是足够使用的，但是随着站点的扩容而改大这些值。 minProcessors服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载。也就是说，如果一天内每秒仅发生5次单击事件，并且每个请求任务处理需要1秒钟，那么预先设置线程数为5就足够了。但在你的站点访问量较大时就需要设置更大的线程数，指定为参数maxProcessors的值。 maxProcessors的值也是有上限的，应防止流量不可控制（或者恶意的服务攻击），从而导致超出了虚拟机使用内存的大小。如果要加大并发连接数，应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置，通常Windows是2000个左右，Linux是1000个左右。</span></p>
<p><span style="color: #0000ff">　　在Tomcat5对这些参数进行了调整，请看下表：<br />
属性名<br />
&nbsp;描述<br />
&nbsp;<br />
maxThreads<br />
&nbsp;Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。<br />
&nbsp;<br />
acceptCount <br />
&nbsp;指定当所有可以使用的处理请求的线程数都被使用时，可以放到处理队列中的请求数，超过这个数的请求将不予处理。<br />
&nbsp;<br />
connnectionTimeout <br />
&nbsp;网络连接超时，单位：毫秒。设置为0表示永不超时，这样设置有隐患的。通常可设置为30000毫秒。<br />
&nbsp;<br />
minSpareThreads <br />
&nbsp;Tomcat初始化时创建的线程数。<br />
&nbsp;<br />
maxSpareThreads <br />
&nbsp;一旦创建的线程超过这个值，Tomcat就会关闭不再需要的socket线程。<br />
&nbsp;</span></p>
<p><br />
<span style="color: #0000ff">　　最好的方式是多设置几次并且进行测试，观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同，而且并不是所有人的web站点的流量都是一样的，因此没有一刀切的方案来确定线程数的值。</span></p>
<p><br />
<span style="color: #0000ff">3.加速JSP编译速度</span></p>
<p><span style="color: #0000ff">　　当第一次访问一个JSP文件时，它会被转换为Java serverlet源码，接着被编译成Java字节码。你可以控制使用哪个编译器，默认情况下，Tomcat使用使用命令行javac进行使用的编译器。也可以使用更快的编译器，但是这里我们将介绍如何优化它们。</span></p>
<p><span style="color: #0000ff">　　另外一种方法是不要把所有的实现都使用JSP页面，而是使用一些不同的java模板引擎变量。显然这是一个跨越很大的决定，但是事实证明至少这种方法是只得研究的。如果你想了解更多有关在Tomcat可使用的模板语言，你可以参考Jason Hunter和William Crawford合著的《Java Servlet Programming 》一书（O'Reilly公司出版）。</span></p>
<p><span style="color: #0000ff">　　在Tomcat 4.0中可以使用流行而且免费的Jikes编译器。Jikes编译器的速度要由于Sun的Java编译器。首先要安装Jikes（可访问</span><a href="http://oss.software.ibm.com/pub/jikes"><span style="color: #0000ff">http://oss.software.ibm.com/pub/jikes</span></a><span style="color: #0000ff"> 获得更多的信息），接着需要在环境变量中设置JIKESPATH包含系统运行时所需的JAR文件。装好Jikes以后还需要设置让JSP编译servlet使用Jikes，需要修改web.xml文件中jspCompilerPlugin的值：</span></p>
<p><br />
<span style="color: #0000ff">&lt;servlet&gt;<br />
&lt;servlet-name&gt;jsp&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;<br />
org.apache.jasper.servlet.JspServlet<br />
&lt;/servlet-class&gt;&lt;init-param&gt;<br />
&lt;param-name&gt;logVerbosityLevel&lt;/param-name&gt;<br />
&lt;param-value&gt;WARNING&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;jspCompilerPlugin&lt;/param-name&gt;<br />
&lt;param-value&gt;<br />
org.apache.jasper.compiler.JikesJavaCompiler<br />
&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;!-- &lt;param-name&gt;<br />
org.apache.catalina.jsp_classpath<br />
&lt;/param-name&gt; --&gt;<br />
&lt;param-name&gt;classpath&lt;/param-name&gt;<br />
&lt;param-value&gt;<br />
/usr/local/jdk1.3.1-linux/jre/lib/rt.jar:<br />
/usr/local/lib/java/servletapi/servlet.ja<br />
r&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;load-on-startup&gt;3&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;</span></p>
<p><br />
<span style="color: #0000ff">　　在Tomcat 4.1（或更高版本），JSP的编译由包含在Tomcat里面的Ant程序控制器直接执行。这听起来有一点点奇怪，但这正是Ant有意为之的一部分，有一个API文档指导开发者在没有启动一个新的JVM的情况下，使用Ant。这是使用Ant进行Java开发的一大优势。另外，这也意味着你现在能够在Ant 中使用任何javac支持的编译方式，这里有一个关于Apache Ant使用手册的javac page列表。使用起来是容易的，因为你只需要在元素中定义一个名字叫&#8220;compiler&#8221;，并且在value中有一个支持编译的编译器名字，示例如下：</span></p>
<p><br />
<span style="color: #0000ff">&lt;servlet&gt;<br />
&lt;servlet-name&gt;jsp&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;<br />
org.apache.jasper.servlet.JspServlet<br />
&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;logVerbosityLevel&lt;/param-name&gt;<br />
&lt;param-value&gt;WARNING&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;compiler&lt;/param-name&gt;<br />
&lt;param-value&gt;jikes&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;load-on-startup&gt;3&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;</span></p>
<p><span style="color: #0000ff">&nbsp;</span></p>
<p><span style="color: #0000ff">Ant可用的编译器<br />
名称<br />
&nbsp;别名<br />
&nbsp;调用的编译器<br />
&nbsp;<br />
classic <br />
&nbsp;javac1.1, javac1.2 <br />
&nbsp;Standard JDK 1.1/1.2 compiler <br />
&nbsp;<br />
modern <br />
&nbsp;javac1.3, javac1.4 <br />
&nbsp;Standard JDK 1.3/1.4 compiler <br />
&nbsp;<br />
jikes <br />
&nbsp;　　 The Jikes compiler <br />
&nbsp;<br />
JVC Microsoft <br />
&nbsp;Microsoft command-line compiler from the Microsoft SDK for Java/Visual J++ <br />
&nbsp;<br />
KJC 　　 The kopi compiler <br />
&nbsp;<br />
GCJ 　　 The gcj compiler (included as part of gcc) <br />
&nbsp;<br />
SJ Symantec <br />
&nbsp;Symantec's Java compiler <br />
&nbsp;<br />
extJavac<br />
&nbsp;　　 Runs either the modern or classic compiler in a JVM of its own <br />
&nbsp;</span></p>
<p><br />
<span style="color: #0000ff">　　由于JSP页面在第一次使用时已经被编译，那么你可能希望在更新新的jsp页面后马上对它进行编译。实际上，这个过程完全可以自动化，因为可以确认的是新的JSP页面在生产服务器和在测试服务器上的运行效果是一样的。 </span></p>
<p><span style="color: #0000ff">在Tomcat4的bin目录下有一个名为jspc的脚本。它仅仅是运行翻译阶段，而不是编译阶段，使用它可以在当前目录生成Java源文件。它是调试JSP页面的一种有力的手段。</span></p>
<p><span style="color: #0000ff">　　可以通过浏览器访问再确认一下编译的结果。这样就确保了文件被转换成serverlet，被编译了可直接执行。这样也准确地模仿了真实用户访问JSP页面，可以看到给用户提供的功能。也抓紧这最后一刻修改出现的bug并且修改它J</span></p>
<p><span style="color: #0000ff">　　Tomcat提供了一种通过请求来编译JSP页面的功能。例如，你可以在浏览器地址栏中输入</span><a href="http://localhost:8080/examples/jsp/dates/date.jsp?jsp_precompile=true"><span style="color: #0000ff">http://localhost:8080/examples/jsp/dates/date.jsp?jsp_precompile=true</span></a><span style="color: #0000ff">，这样Tomcat就会编译data.jsp而不是执行它。此举唾手可得，不失为一种检验页面正确性的捷径。</span></p>
<p><span style="color: #0000ff">　　4. 其它</span></p>
<p><span style="color: #0000ff">　　前面我们提到过操作系统通过一些限制手段来防止恶意的服务攻击，同样Tomcat也提供了防止恶意攻击或禁止某些机器访问的设置。</span></p>
<p><span style="color: #0000ff">　　Tomcat提供了两个参数供你配置：RemoteHostValve 和RemoteAddrValve。 </span></p>
<p><span style="color: #0000ff">　　通过配置这两个参数，可以让你过滤来自请求的主机或IP地址，并允许或拒绝哪些主机/IP。与之类似的，在Apache的httpd文件里有对每个目录的允许/拒绝指定。 </span></p>
<p><span style="color: #0000ff">　　例如你可以把Admin Web application设置成只允许本地访问，设置如下：</span></p>
<p><br />
<span style="color: #0000ff">&lt;Context path="/path/to/secret_files" ...&gt; <br />
&lt;Valve className="org.apache.catalina.valves.RemoteAddrValve" </span></p>
<p><span style="color: #0000ff">allow="127.0.0.1" deny=""/&gt; <br />
&lt;/Context&gt;</span></p>
<p><br />
<span style="color: #0000ff">　　如果没有给出允许主机的指定，那么与拒绝主机匹配的主机就会被拒绝，除此之外的都是允许的。与之类似，如果没有给出拒绝主机的指定，那么与允许主机匹配的主机就会被允许，除此之外的都是拒绝的。</span></p>
<p><span style="color: #0000ff">五. 容量计划<br />
　容量计划是在生产环境中使用Tomcat不得不提的提高性能的另一个重要的话题。如果你没有对预期的网络流量下的硬件和带宽做考虑的话那么无论你如何做配置修改和测试都无济于事。</span></p>
<p><span style="color: #0000ff">　　这里先对提及的容量计划作一个简要的定义：容量计划是指评估硬件、操作系统和网络带宽，确定应用服务的服务范围，寻求适合需求和软件特性的软硬件的一项活动。因此这里所说的软件不仅包括Tomcat，也包括与Tomcat结合使用的任何第三方web服务器软件。</span></p>
<p><span style="color: #0000ff">　　如果在购买软硬件或部署系统前你对容量计划一无所知，不知道现有的软硬件环境能够支撑多少的访问量，甚至更糟直到你已经交付并且在生产环境上部署产品后才意识到配置有问题时再进行变更可能为时已晚。此时只能增加硬件投入，增加硬盘容量甚至购买更好的服务器。如果事先做了容量计划那么就不会搞的如此焦头烂额了。</span></p>
<p><span style="color: #0000ff">　　我们这里只介绍与Tomcat相关的内容。</span></p>
<p><span style="color: #0000ff">　　首先为了确定Tomcat使用机器的容量计划，你应该从一下列表项目种着手研究和计划：</span></p>
<p><span style="color: #0000ff">　　1. 硬件</span></p>
<p><span style="color: #0000ff">　　采用什么样的硬件体系？需要多少台计算机？使用一个大型的，还是使用多台小型机？每个计算机上使用几个CPU？使用多少内存？使用什么样的存储设备， I/O的处理速度有什么要求？怎样维护这些计算机？不同的JVM在这些硬件上运行的效果如何（比如IBM AIX系统只能在其设计的硬件系统上运行）？</span></p>
<p><span style="color: #0000ff">　　2. 网络带宽</span></p>
<p><span style="color: #0000ff">　　带宽的使用极限是多少？web应用程序如何处理过多的请求？</span></p>
<p><span style="color: #0000ff">　　3. 服务端操作系统</span></p>
<p><span style="color: #0000ff">　　采用哪种操作系统作为站点服务器最好？在确定的操作系统上使用哪个JVM最好？例如，JVM在这种系统上是否支持本地多线程，对称多处理？哪种系统可使web服务器更快、更稳定，并且更便宜。是否支持多CPU？ <br />
4. Tomcat容量计划</span></p>
<p><span style="color: #0000ff">　　以下介绍针对Tomcat做容量计划的步骤：</span></p>
<p><span style="color: #0000ff">　　1） 量化负载。如果站点已经建立并运行，可以使用前面介绍的工具模仿用户访问，确定资源的需求量。</span></p>
<p><span style="color: #0000ff">　　2） 针对测试结果或测试过程中进行分析。需要知道那些请求造成了负载过重或者使用过多的资源，并与其它请求做比较，这样就确定了系统的瓶颈所在。例如：如果servlet在查询数据库的步骤上耗用较长的时间，那么就需要考虑使用缓冲池来降低响应时间。</span></p>
<p><span style="color: #0000ff">　　3）确定性能最低标准。例如，你不想让用户花20秒来等待结果页面的返回，也就是说甚至在达到访问量的极限时，用户等待的时间也不能超过20秒种（从点击链接到看到返第一条返回数据）。这个时间中包含了数据库查询时间和文件访问时间。同类产品性能在不同的公司可能有不同的标准，一般最好采取同行中的最低标准或对这个标准做出评估。</span></p>
<p><span style="color: #0000ff">　　4）确定如何合理使用底层资源，并逐一进行测试。底层资源包括CPU、内存、存储器、带宽、操作系统、JVM等等。在各种生产环境上都按顺序进行部署和测试，观察是否符合需求。在测试Tomcat时尽量多采用几种JVM，并且调整JVM使用内存和Tomcat线程池的大小进行测试。同时为了达到资源充分合理稳定地使用的效果，还需针对测试过程中出现的硬件系统瓶颈进行处理确定合理的资源配置。这个过程最为复杂，而且一般由于没有可参考的值所以只能靠理论推断和经验总结。</span></p>
<p><span style="color: #0000ff">　　5） 如果通过第4步的反复测试如果达到了最优的组合，就可以在相同的生产环境上部署产品了。</span></p>
<p><span style="color: #0000ff">　　此外应牢记一定要文档化你的测试过程和结果，因为此后可能还会进行测试，这样就可以拿以前的测试结果做为参考。另外测试过程要反复多次进行，每次的条件可能都不一样，因此只有记录下来才能进行结果比较和最佳条件的选择。</span></p>
<p><span style="color: #0000ff">　　这样我们通过测试找到了最好的组合方式，各种资源得到了合理的配置，系统的性能得到了极大的提升。</span></p>
<p><span style="color: #0000ff">六. 附加资料<br />
　很显然本文也很难全面而详尽地阐述性能优化过程。如果你进行更多研究的话可能会把性能调优做的更好，比如Java程序的性能调整、操作系统的调整、各种复杂环境与应用系统和其它所有与应用程序相关的东西。在这里提供一些文中提到的一些资源、文中提到的相关内容的链接以及本文的一些参考资料。</span></p>
<p><span style="color: #0000ff">　　1. Web性能测试资料及工具</span></p>
<p><span style="color: #0000ff">　　1） Jmeter Wiki首页，Jmeter为一个开源的100%Java开发的性能测试工具<br />
　　</span><a href="http://wiki.apache.org/jakarta-jmeter/"><span style="color: #0000ff">http://wiki.apache.org/jakarta-jmeter/</span></a></p>
<p><span style="color: #0000ff">　　2） Apache Benchmark使用说明<br />
　　</span><a href="http://httpd.apache.org/docs-2.0/programs/ab.html"><span style="color: #0000ff">http://httpd.apache.org/docs-2.0/programs/ab.html</span></a></p>
<p><span style="color: #0000ff">　　3） 一些Java相关测试工具的介绍，包含可以与Tomcat集成进行测试的工具<br />
　　</span><a href="http://blog.csdn.net/wyingquan/"><span style="color: #0000ff">http://blog.csdn.net/wyingquan/</span></a></p>
<p><span style="color: #0000ff">　　4） LoadRunner? 是一种预测系统行为和性能的工业标准级负载测试工具。它通过模拟数据以千万计用户来实施并发负载来对整个企业架构进行测试，来帮助您更快的查找和发现问题。<br />
　　</span><a href="http://www.mercury.com/us/products/performance-center/loadrunner/"><span style="color: #0000ff">http://www.mercury.com/us/products/performance-center/loadrunner/</span></a></p>
<p><br />
<span style="color: #0000ff">　　2. 文中介绍的相关内容的介绍</span></p>
<p><span style="color: #0000ff">　　1） Apache 2.x + Tomcat 4.x做负载均衡，描述了如何利用jk配置集群的负载均衡。<br />
　　</span><a href="http://raibledesigns.com/tomcat/index.html"><span style="color: #0000ff">http://raibledesigns.com/tomcat/index.html</span></a></p>
<p><span style="color: #0000ff">　　2） 容量计划的制定，收集了许多有关制定web站点容量计划的例子：<br />
　　</span><a href="http://www.capacityplanning.com/"><span style="color: #0000ff">http://www.capacityplanning.com/</span></a></p>
<p><span style="color: #0000ff">　　3） 评测Tomcat5负载平衡与集群，<br />
　　</span><a href="http://www.javaresearch.org/article/showarticle.jsp?column=556&amp;thread=19777"><span style="color: #0000ff">http://www.javaresearch.org/article/showarticle.jsp?column=556&amp;thread=19777</span></a></p>
<p><span style="color: #0000ff">　　4） Apache与Tomcat的安装与整合之整合篇<br />
　　</span><a href="http://www.javaresearch.org/article/showarticle.jsp?column=23&amp;thread=18139"><span style="color: #0000ff">http://www.javaresearch.org/article/showarticle.jsp?column=23&amp;thread=18139</span></a></p>
<p><span style="color: #0000ff">　　5） 性能测试工具之研究，介绍了性能测试工具的原理与思路<br />
　　</span><a href="http://www.51testing.com/emagzine/No2_2.htm"><span style="color: #0000ff">http://www.51testing.com/emagzine/No2_2.htm</span></a></p>
<p><span style="color: #0000ff">　　6） Java的内存泄漏<br />
　　</span><a href="http://www.matrix.org.cn/resource/article/409.html"><span style="color: #0000ff">http://www.matrix.org.cn/resource/article/409.html</span></a></p>
<p><span style="color: #0000ff">　　7） Web服务器和应用程序服务器有什么区别？<br />
　　</span><a href="http://www.matrix.org.cn/resource/article/1429.html"><span style="color: #0000ff">http://www.matrix.org.cn/resource/article/1429.html</span></a></p>
<p><span style="color: #0000ff">　　8） 详细讲解性能中数据库集群的问题<br />
　　</span><a href="http://www.theserverside.com/articles/article.tss?l=DB_Break"><span style="color: #0000ff">http://www.theserverside.com/articles/article.tss?l=DB_Break</span></a><span style="color: #0000ff">&nbsp; </span></p>
</div>
<img src ="http://www.blogjava.net/sutao/aggbug/162665.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-23 16:27 <a href="http://www.blogjava.net/sutao/articles/162665.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL语句调优技巧</title><link>http://www.blogjava.net/sutao/articles/162375.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 22 Nov 2007 06:37:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162375.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162375.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162375.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162375.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: SQL Server SQL语句调优技巧                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;www.InnovateDigital.com 整理                                                 &nbsp;&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/sutao/articles/162375.html'>阅读全文</a><img src ="http://www.blogjava.net/sutao/aggbug/162375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-22 14:37 <a href="http://www.blogjava.net/sutao/articles/162375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存泄漏</title><link>http://www.blogjava.net/sutao/articles/162368.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 22 Nov 2007 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162368.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162368.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162368.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162368.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162368.html</trackback:ping><description><![CDATA[<h1 style="color: rgb(0,0,0)"><span style="color: #0000ff">【转自IBM】Java的内存泄漏</span></h1>
<p style="color: rgb(0,0,0)"><font size="2"><a href="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/#author"><span style="color: #0000ff">欧阳辰</span></a><span style="color: #0000ff">, <br />
</span><a href="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/#author"><span style="color: #0000ff">周欣</span></a><span style="color: #0000ff">, </span></font></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">2002 年 10 月 21 日</span></p>
<blockquote style="color: rgb(0,0,0)"><span style="color: #0000ff">Java的一个重要优点就是通过垃圾收集器(Garbage Collection，GC)自动管理内存的回收，程序员不需要通过调用函数来释放内存。因此，很多程序员认为Java不存在内存泄漏问题，或者认为即使有内存泄漏也不是程序的责任，而是GC或JVM的问题。其实，这种想法是不正确的，因为Java也存在内存泄露，但它的表现与C++不同。</span></blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p style="color: rgb(0,0,0)"><span style="color: #0000ff"><a name="1"><span class="atitle">问题的提出</span></a></span></p>
<p style="color: rgb(0,0,0)"></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">Java 的一个重要优点就是通过垃圾收集器(Garbage Collection，GC)自动管理内存的回收，程序员不需要通过调用函数来释放内存。因此，很多程序员认为Java不存在内存泄漏问题，或者认为即使有内存泄漏也不是程序的责任，而是GC或JVM的问题。其实，这种想法是不正确的，因为Java也存在内存泄露，但它的表现与C++不同。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">随着越来越多的服务器程序采用Java技术，例如JSP，Servlet， EJB等，服务器程序往往长期运行。另外，在很多嵌入式系统中，内存的总量非常有限。内存泄露问题也就变得十分关键，即使每次运行少量泄漏，长期运行之后，系统也是面临崩溃的危险。</span></p>
<font style="color: rgb(0,0,0)" size="2"><br />
</font>
<table style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><span style="color: #0000ff"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="550" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
        </tr>
    </tbody>
</table>
<table class="no-print" style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><span style="color: #0000ff"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="4" /><br />
            </span>
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><span style="color: #0000ff"><br />
                        </span></td>
                        <td valign="top" align="right"><span style="color: #0000ff"><br />
                        </span></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<font style="color: rgb(0,0,0)" size="2"><br />
<br />
</font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff"><a name="2"><span class="atitle">Java是如何管理内存</span></a></span></p>
<p style="color: rgb(0,0,0)"></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">为了判断Java中是否有内存泄露，我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中，程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外)，所有的对象都在堆 (Heap)中分配空间。另外，对象的释放是由GC决定和执行的。在Java中，内存的分配是由程序完成的，而内存的释放是有GC完成的，这种收支两条线的方法确实简化了程序员的工作。但同时，它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为，GC为了能够正确释放对象，GC必须监控每一个对象的运行状态，包括对象的申请、引用、被引用、赋值等，GC都需要进行监控。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">监视对象状态是为了更加准确地、及时地释放对象，而释放对象的根本原则就是该对象不再被引用。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">为了更好理解GC的工作原理，我们可以将对象考虑为有向图的顶点，将引用关系考虑为图的有向边，有向边从引用者指向被引对象。另外，每个线程对象可以作为一个图的起始顶点，例如大多程序从main进程开始执行，那么该图就是以main进程顶点开始的一棵根树。在这个有向图中，根顶点可达的对象都是有效对象， GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意，该图为有向图)，那么我们认为这个(这些)对象不再被引用，可以被GC回收。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">以下，我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻，我们都有一个有向图表示JVM的内存分配情况。以下右图，就是左边程序运行到第6行的示意图。</span></p>
<font style="color: rgb(0,0,0)" size="2"><br />
<span style="color: #0000ff"><img height="201" alt="图1" src="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/1.gif" width="582" /><br />
</span></font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">Java 使用有向图的方式进行内存管理，可以消除引用循环的问题，例如有三个对象，相互引用，只要它们和根进程不可达的，那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高，但是效率较低。另外一种常用的内存管理技术是使用计数器，例如COM模型采用计数器方式管理构件，它与有向图相比，精度行低 (很难处理循环引用的问题)，但执行效率很高。</span></p>
<font style="color: rgb(0,0,0)" size="2"><br />
</font>
<table style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><span style="color: #0000ff"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="550" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
        </tr>
    </tbody>
</table>
<table class="no-print" style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><span style="color: #0000ff"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="4" /><br />
            </span>
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><span style="color: #0000ff"><br />
                        </span></td>
                        <td valign="top" align="right"><span style="color: #0000ff"><br />
                        </span></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<font style="color: rgb(0,0,0)" size="2"><br />
</font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff"><a name="3"><span class="atitle">什么是Java中的内存泄露</span></a></span></p>
<p style="color: rgb(0,0,0)"></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">下面，我们就可以描述什么是内存泄漏。在Java中，内存泄漏就是存在一些被分配的对象，这些对象有下面两个特点，首先，这些对象是可达的，即在有向图中，存在通路可以与其相连；其次，这些对象是无用的，即程序以后不会再使用这些对象。如果对象满足这两个条件，这些对象就可以判定为Java中的内存泄漏，这些对象不会被GC所回收，然而它却占用内存。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">在C++中，内存泄漏的范围更大一些。有些对象被分配了内存空间，然后却不可达，由于C++中没有GC，这些内存将永远收不回来。在Java中，这些不可达的对象都由GC负责回收，因此程序员不需要考虑这部分的内存泄露。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">通过分析，我们得知，对于C++，程序员需要自己管理边和顶点，而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式，Java提高了编程的效率。</span></p>
<font style="color: rgb(0,0,0)" size="2"><br />
<span style="color: #0000ff"><img height="231" alt="图2" src="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/2.gif" width="507" /> <br />
</span></font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">因此，通过以上分析，我们知道在Java中也有内存泄漏，但范围比C++要小一些。因为Java从语言上保证，任何对象都是可达的，所有的不可达对象都由GC管理。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">对于程序员来说，GC基本是透明的，不可见的。虽然，我们只有几个函数可以访问GC，例如运行GC的函数System.gc()，但是根据Java语言规范定义，该函数不保证JVM的垃圾收集器一定会执行。因为，不同的JVM实现者可能使用不同的算法管理GC。通常，GC的线程的优先级别较低。JVM调用GC的策略也有很多种，有的是内存使用到达一定程度时，GC才开始工作，也有定时执行的，有的是平缓执行GC，有的是中断式执行GC。但通常来说，我们不需要关心这些。除非在一些特定的场合，GC的执行影响应用程序的性能，例如对于基于Web的实时系统，如网络游戏等，用户不希望GC突然中断应用程序执行而进行垃圾回收，那么我们需要调整GC的参数，让GC能够通过平缓的方式释放内存，例如将垃圾回收分解为一系列的小步骤执行，Sun提供的HotSpot JVM就支持这一特性。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">下面给出了一个简单的内存泄露的例子。在这个例子中，我们循环申请Object对象，并将所申请的对象放入一个Vector中，如果我们仅仅释放引用本身，那么Vector仍然引用该对象，所以这个对象对GC来说是不可回收的。因此，如果对象加入到Vector后，还必须从Vector中删除，最简单的方法就是将Vector对象设置为null。</span></p>
<table style="color: rgb(0,0,0)" cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td>
            <pre><font size="2"><code class="section"><br />
            <span style="color: #0000ff">Vector v=new Vector(10);<br />
            for (int i=1;i&lt;100; i++)<br />
            {<br />
            Object o=new Object();<br />
            v.add(o);<br />
            o=null;	<br />
            }</span></code></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<font style="color: rgb(0,0,0)" size="2"><br />
<span style="color: #0000ff">//此时，所有的Object对象都没有被释放，因为变量v引用这些对象。 <br />
</span></font>
<table style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><span style="color: #0000ff"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="550" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
        </tr>
    </tbody>
</table>
<table class="no-print" style="color: rgb(0,0,0)" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><span style="color: #0000ff"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="4" /><br />
            </span>
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><span style="color: #0000ff"><br />
                        </span></td>
                        <td valign="top" align="right"><span style="color: #0000ff"><br />
                        </span></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<font style="color: rgb(0,0,0)" size="2"><br />
<br />
</font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff"><a name="4"><span class="atitle">如何检测内存泄漏</span></a></span></p>
<p style="color: rgb(0,0,0)"></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">最后一个重要的问题，就是如何检测Java的内存泄漏。目前，我们通常使用一些工具来检查Java程序的内存泄漏问题。市场上已有几种专业检查Java内存泄漏的工具，它们的基本工作原理大同小异，都是通过监测Java程序运行时，所有对象的申请、释放等动作，将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。这些工具包括Optimizeit Profiler，JProbe Profiler，JinSight , Rational 公司的Purify等。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">下面，我们将简单介绍Optimizeit的基本功能和工作原理。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">Optimizeit Profiler版本4.11支持Application，Applet，Servlet和Romote Application四类应用，并且可以支持大多数类型的JVM，包括SUN JDK系列，IBM的JDK系列，和Jbuilder的JVM等。并且，该软件是由Java编写，因此它支持多种操作系统。Optimizeit系列还包括Thread Debugger和Code Coverage两个工具，分别用于监测运行时的线程状态和代码覆盖面。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">当设置好所有的参数了，我们就可以在OptimizeIt环境下运行被测程序，在程序运行过程中，Optimizeit可以监视内存的使用曲线(如下图)，包括JVM申请的堆(heap)的大小，和实际使用的内存大小。另外，在运行过程中，我们可以随时暂停程序的运行，甚至强行调用GC，让GC进行内存回收。通过内存使用曲线，我们可以整体了解程序使用内存的情况。这种监测对于长期运行的应用程序非常有必要，也很容易发现内存泄露。</span></p>
<font style="color: rgb(0,0,0)" size="2"><br />
<span style="color: #0000ff"><img height="354" alt="图3" src="http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/3.gif" width="521" /> <br />
</span></font>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">在运行过程中，我们还可以从不同视角观查内存的使用情况，Optimizeit提供了四种方式：</span></p>
<ul style="color: rgb(0,0,0)">
    <li><span style="color: #0000ff">堆视角。 这是一个全面的视角，我们可以了解堆中的所有的对象信息(数量和种类)，并进行统计、排序，过滤。了解相关对象的变化情况。</span></li>
    <li><span style="color: #0000ff">方法视角。通过方法视角，我们可以得知每一种类的对象，都分配在哪些方法中，以及它们的数量。</span></li>
    <li><span style="color: #0000ff">对象视角。给定一个对象，通过对象视角，我们可以显示它的所有出引用和入引用对象，我们可以了解这个对象的所有引用关系。</span></li>
    <li><span style="color: #0000ff">引用图。 给定一个根，通过引用图，我们可以显示从该顶点出发的所有出引用。</span></li>
</ul>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">在运行过程中，我们可以随时观察内存的使用情况，通过这种方式，我们可以很快找到那些长期不被释放，并且不再使用的对象。我们通过检查这些对象的生存周期，确认其是否为内存泄露。在实践当中，寻找内存泄露是一件非常麻烦的事情，它需要程序员对整个程序的代码比较清楚，并且需要丰富的调试经验，但是这个过程对于很多关键的Java程序都是十分重要的。</span></p>
<p style="color: rgb(0,0,0)"><span style="color: #0000ff">综上所述，Java也存在内存泄露问题，其原因主要是一些对象虽然不再被使用，但它们仍然被引用。为了解决这些问题，我们可以通过软件工具来检查内存泄露，检查的主要原理就是暴露出所有堆中的对象，让程序员寻找那些无用但仍被引用的对象。</span></p>
<img src ="http://www.blogjava.net/sutao/aggbug/162368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-22 14:13 <a href="http://www.blogjava.net/sutao/articles/162368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Heap </title><link>http://www.blogjava.net/sutao/articles/162296.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 22 Nov 2007 02:30:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162296.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162296.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162296.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162296.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162296.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/sutao/articles/162296.html'>阅读全文</a><img src ="http://www.blogjava.net/sutao/aggbug/162296.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-22 10:30 <a href="http://www.blogjava.net/sutao/articles/162296.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java heap详细介绍</title><link>http://www.blogjava.net/sutao/articles/162288.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Thu, 22 Nov 2007 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/162288.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/162288.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/162288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/162288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/162288.html</trackback:ping><description><![CDATA[<div class="postText">
<p><span style="color: #0000ff">1、<br />
</span></p>
<p><span style="color: #0000ff">PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出，解决方法也一定是加大内存。说说为什么会内存益出：这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域，它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理，所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。</span></p>
<span style="color: #0000ff">改正方法：-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m </span></div>
<div class="entry-more" id="more">
<p><span style="color: #0000ff">2、</span></p>
<p><span style="color: #0000ff">在tomcat中redeploy时出现outofmemory的错误.</span></p>
<p><span style="color: #0000ff">可以有以下几个方面的原因:</span></p>
<p><span style="color: #0000ff">１,使用了<u><font color="#800080">proxool,因为proxool内部包含了一个老版本的cglib.</font></u></span></p>
<p><u><span style="color: #0000ff">2, log4j,最好不用,只用common-logging</span></u></p>
<p><u><span style="color: #0000ff">3, 老版本的cglib,快点更新到最新版。</span></u></p>
<p><span style="color: #0000ff"><u><font color="#800080">４，更新到最新的hibernate3.2</font></u><br />
</span></p>
<span style="color: #0000ff">3、<br />
<br />
这里以tomcat环境为例，其它WEB服务器如jboss,weblogic等是同一个道理。<br />
一、java.lang.OutOfMemoryError: PermGen space </span>
<p><span style="color: #0000ff">PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,<br />
这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,<br />
它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对<br />
PermGen space进行清理，所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误,<br />
这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小<br />
超过了jvm默认的大小(4M)那么就会产生此错误信息了。<br />
解决方法： 手动设置MaxPermSize大小</span></p>
<p><span style="color: #0000ff">修改TOMCAT_HOME/bin/catalina.sh<br />
在&#8220;echo "Using CATALINA_BASE:&nbsp;&nbsp; $CATALINA_BASE"&#8221;上面加入以下行：<br />
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m<br />
建议：将相同的第三方jar文件移置到tomcat/shared/lib目录下，这样可以达到减少jar 文档重复占用内存的目的。</span></p>
<p><span style="color: #0000ff">二、java.lang.OutOfMemoryError: Java heap space<br />
Heap size 设置<br />
JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值，<br />
其初始空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可<br />
进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。<br />
提示：在JVM中如果98％的时间是用于GC且可用的Heap size 不足2％的时候将抛出此异常信息。<br />
提示：Heap Size 最大不要超过可用物理内存的80％，一般的要将-Xms和-Xmx选项设置为相同，而-Xmn为1/4的-Xmx值。 <br />
解决方法：手动设置Heap size<br />
修改TOMCAT_HOME/bin/catalina.sh<br />
在&#8220;echo "Using CATALINA_BASE:&nbsp;&nbsp; $CATALINA_BASE"&#8221;上面加入以下行：<br />
JAVA_OPTS="-server -Xms800m -Xmx800m&nbsp;&nbsp; -XX:MaxNewSize=256m"</span></p>
<p><span style="color: #0000ff">三、实例，以下给出1G内存环境下java jvm 的参数设置参考：</span></p>
<p><span style="color: #0000ff">JAVA_OPTS="-server -Xms800m -Xmx800m&nbsp; -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "</span></p>
<p><br />
<span style="color: #0000ff">三、相关资料</span></p>
<p><a href="http://www.tot.name/show/3/7/20061112220131.htm"><span style="color: #0000ff">/show/3/7/20061112220131.htm</span></a></p>
<p><a href="http://www.tot.name/show/3/7/20061112220054.htm"><span style="color: #0000ff">/show/3/7/20061112220054.htm</span></a></p>
<p><a href="http://www.tot.name/show/3/7/20061112220201.htm"><span style="color: #0000ff">/show/3/7/20061112220201.htm</span></a></p>
<span style="color: #0000ff">题外话：经常看到网友抱怨tomcat的性能不如...，不稳定等，其实根据笔者几年的经验，从"互联星空&#8220;到现在的房产门户网，我们<br />
均使用tomcat作为WEB服务器，每天访问量百万多，tomcat仍然运行良好。建议大家有问题多从自己程序入手，多看看java的DOC文档<br />
并详细了解JVM的知识。这样开发的程序才会健壮。<br />
<br />
<font style="font-weight: bold" size="4"><span style="color: rgb(153,204,0)">延伸阅读：</span></font> </span>
<h3 class="entry-header"><a href="http://www.wujianrong.com/archives/2007/02/jvm_1.html#more"><span style="color: #0000ff">JVM 性能调整的一些基本概念</span></a></h3>
<h2 class="r"></h2>
<h2 class="r"><a href="http://www.wujianrong.com/archives/2006/11/apachetomcat.html"><span class="l"><span style="color: #0000ff">apache+Tomcat负载平衡设置详解[转]</span></span></a></h2>
<h1><span style="color: #0000ff"><a href="http://java.sun.com/j2se/1.3/docs/tooldocs/linux/java.html">java - the Java application launcher</a></span><br />
</h1>
<h3 class="entry-header"><a href="http://www.wujianrong.com/archives/2006/11/jvm.html"><span style="color: #0000ff">JVM调优[转]</span></a></h3>
</div>
<img src ="http://www.blogjava.net/sutao/aggbug/162288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-22 10:20 <a href="http://www.blogjava.net/sutao/articles/162288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详细讲解在Hibernate中检索策略的应用</title><link>http://www.blogjava.net/sutao/articles/161879.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Tue, 20 Nov 2007 07:59:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/161879.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/161879.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/161879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/161879.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/161879.html</trackback:ping><description><![CDATA[<h1 id="pageName">详细讲解在Hibernate中检索策略的应用</h1>
<div class="feature">&nbsp;</div>
<div class="story">
<p>　　<a href="http://www.pcdog.com/special/1202/index.html" target="_blank">Hibernate</a>的检索<nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">策略</nobr>包括类级别检索策略和关联级别检索策略。</p>
<div class="ad0">　　类级别检索策略有立即检索和延迟检索，默认的检索策略是立即检索。在Hibernate映射文件中，通过在&lt;不着class&gt;上配置lazy属性来确定检索策略。对于Session的检索方式，类级别检索策略仅适用于load方法；也就说，对于get、 qurey检索，持久化对象都会被立即加载而不管lazy是false还是true.一般来说，我们检索对象就是要访问它，因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常（立即检索的情况下），因此我个人并不建议使用load检索；而由于&lt; class&gt;中的lazy属性还影响到多对一及一对一的检索策略，因此使用load方法就更没必要了。</div>
<p>　　关联级别检索策略有立即检索、延迟检索和迫切左外连接检索。对于关联级别检索，又可分为一对多和多对多、多对一和一对一两种情况讨论。</p>
<p>　　一对多和多对多关联关系一般使用&lt; set&gt;配置。&lt; set&gt;有lazy和outer-join属性，它们的不同取值绝对了检索策略。</p>
<p>　　1）立即检索：这是一对多默认的检索策略，此时lazy=false，outer-join=false.尽管这是默认的检索策略，但如果关联的集合是无用的，那么就不要使用这种检索方式。</p>
<p>　　2）延迟检索：此时lazy=true，outer-join=false（outer-join=true是无意义的），这是优先考虑的检索方式。</p>
<p>　　3）迫切左外连接检索：此时 lazy=false，outer-join=true，这种检索策略只适用于依靠id检索方式（load、get），而不适用于query的集合检索（它会采用立即检索策略）。相比于立即检索，这种检索策略减少了一条sql语句，但在Hibernate中，只能有一个配置成 outer-join=true.</p>
<p>　　多对一和一对一检索策略一般使用&lt; many-to-one&gt;、&lt; one-to-one&gt;配置。&lt; many-to-one&gt;中需要配置的属性是 outer-join，同时还需要配置one端关联的&lt; class&gt;的lazy属性（配置的可不是&lt; many-to-one&gt;中的lazy哦），它们的组合后的检索策略如下：</p>
<p>　　1） outer-join=auto：这是默认值，如果lazy=true为延迟检索，如果lazy=false为迫切左外连接检索。</p>
<p>　　2） outer-join=true，无关于lazy，都为迫切左外连接检索。</p>
<p>　　3） outer-join=false，如果lazy=true为延迟检索，否则为立即检索。</p>
<p>　　可以看到，在默认的情况下（outer-join=auto，lazy=false），对关联的one端对象Hibernate采用的迫切左外连接检索。依我看，很多情况下，我们并不需要加载one端关联的对象（很可能我们需要的仅仅是关联对象的id）；另外，如果关联对象也采用了迫切左外连接检索，就会出现select语句中有多个外连接表，如果个数多的话会影响检索性能，这也是为什么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索，query的集合检索并不适用，它会采用立即检索策略。</p>
<p>　　对于检索策略，需要根据实际情况进行选择。对于立即检索和延迟检索，它们的优点在于select语句简单（每张表一条语句）、查询速度快，缺点在于关联表时需要多条select语句，增加了访问<a href="http://www.pcdog.com/special/1229/index.html" target="_blank">数据库</a>的频率。因此在选择即检索和延迟检索时，可以考虑使用批量检索策略来<nobr oncontextmenu="return false;" onmousemove="kwM(4);" id="key3" onmouseover="kwE(event,4, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">减少</nobr>select语句的数量（配置batch-size属性）。对于切左外连接检索，优点在于select较少，但缺点是select语句的复杂度提高，多表之间的关联会是很耗时的操作。另外，配置文件是死的，但<nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">程序</nobr>是活的，可以根据需要在程序里显示的指定检索策略（可能经常需要在程序中显示指定迫切左外连接检索）。为了清楚检索策略的配置<nobr oncontextmenu="return false;" onmousemove="kwM(0);" id="key0" onmouseover="kwE(event,0, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">效果</nobr>如何，可以配置show_sql属性查看程序运行时Hibernate执行的sql语句。</p>
</div>
<img src ="http://www.blogjava.net/sutao/aggbug/161879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-20 15:59 <a href="http://www.blogjava.net/sutao/articles/161879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详细讲解在Hibernate中检索策略的应用</title><link>http://www.blogjava.net/sutao/articles/161878.html</link><dc:creator>苏醄</dc:creator><author>苏醄</author><pubDate>Tue, 20 Nov 2007 07:59:00 GMT</pubDate><guid>http://www.blogjava.net/sutao/articles/161878.html</guid><wfw:comment>http://www.blogjava.net/sutao/comments/161878.html</wfw:comment><comments>http://www.blogjava.net/sutao/articles/161878.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sutao/comments/commentRss/161878.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sutao/services/trackbacks/161878.html</trackback:ping><description><![CDATA[<h1 id="pageName">详细讲解在Hibernate中检索策略的应用</h1>
<div class="feature">&nbsp;</div>
<div class="story">
<p>　　<a href="http://www.pcdog.com/special/1202/index.html" target="_blank">Hibernate</a>的检索<nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">策略</nobr>包括类级别检索策略和关联级别检索策略。</p>
<div class="ad0">　　类级别检索策略有立即检索和延迟检索，默认的检索策略是立即检索。在Hibernate映射文件中，通过在&lt;不着class&gt;上配置lazy属性来确定检索策略。对于Session的检索方式，类级别检索策略仅适用于load方法；也就说，对于get、 qurey检索，持久化对象都会被立即加载而不管lazy是false还是true.一般来说，我们检索对象就是要访问它，因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常（立即检索的情况下），因此我个人并不建议使用load检索；而由于&lt; class&gt;中的lazy属性还影响到多对一及一对一的检索策略，因此使用load方法就更没必要了。</div>
<p>　　关联级别检索策略有立即检索、延迟检索和迫切左外连接检索。对于关联级别检索，又可分为一对多和多对多、多对一和一对一两种情况讨论。</p>
<p>　　一对多和多对多关联关系一般使用&lt; set&gt;配置。&lt; set&gt;有lazy和outer-join属性，它们的不同取值绝对了检索策略。</p>
<p>　　1）立即检索：这是一对多默认的检索策略，此时lazy=false，outer-join=false.尽管这是默认的检索策略，但如果关联的集合是无用的，那么就不要使用这种检索方式。</p>
<p>　　2）延迟检索：此时lazy=true，outer-join=false（outer-join=true是无意义的），这是优先考虑的检索方式。</p>
<p>　　3）迫切左外连接检索：此时 lazy=false，outer-join=true，这种检索策略只适用于依靠id检索方式（load、get），而不适用于query的集合检索（它会采用立即检索策略）。相比于立即检索，这种检索策略减少了一条sql语句，但在Hibernate中，只能有一个配置成 outer-join=true.</p>
<p>　　多对一和一对一检索策略一般使用&lt; many-to-one&gt;、&lt; one-to-one&gt;配置。&lt; many-to-one&gt;中需要配置的属性是 outer-join，同时还需要配置one端关联的&lt; class&gt;的lazy属性（配置的可不是&lt; many-to-one&gt;中的lazy哦），它们的组合后的检索策略如下：</p>
<p>　　1） outer-join=auto：这是默认值，如果lazy=true为延迟检索，如果lazy=false为迫切左外连接检索。</p>
<p>　　2） outer-join=true，无关于lazy，都为迫切左外连接检索。</p>
<p>　　3） outer-join=false，如果lazy=true为延迟检索，否则为立即检索。</p>
<p>　　可以看到，在默认的情况下（outer-join=auto，lazy=false），对关联的one端对象Hibernate采用的迫切左外连接检索。依我看，很多情况下，我们并不需要加载one端关联的对象（很可能我们需要的仅仅是关联对象的id）；另外，如果关联对象也采用了迫切左外连接检索，就会出现select语句中有多个外连接表，如果个数多的话会影响检索性能，这也是为什么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索，query的集合检索并不适用，它会采用立即检索策略。</p>
<p>　　对于检索策略，需要根据实际情况进行选择。对于立即检索和延迟检索，它们的优点在于select语句简单（每张表一条语句）、查询速度快，缺点在于关联表时需要多条select语句，增加了访问<a href="http://www.pcdog.com/special/1229/index.html" target="_blank">数据库</a>的频率。因此在选择即检索和延迟检索时，可以考虑使用批量检索策略来<nobr oncontextmenu="return false;" onmousemove="kwM(4);" id="key3" onmouseover="kwE(event,4, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">减少</nobr>select语句的数量（配置batch-size属性）。对于切左外连接检索，优点在于select较少，但缺点是select语句的复杂度提高，多表之间的关联会是很耗时的操作。另外，配置文件是死的，但<nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">程序</nobr>是活的，可以根据需要在程序里显示的指定检索策略（可能经常需要在程序中显示指定迫切左外连接检索）。为了清楚检索策略的配置<nobr oncontextmenu="return false;" onmousemove="kwM(0);" id="key0" onmouseover="kwE(event,0, this);" style="color: rgb(102,0,255); border-bottom: rgb(102,0,255) 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">效果</nobr>如何，可以配置show_sql属性查看程序运行时Hibernate执行的sql语句。</p>
</div>
<img src ="http://www.blogjava.net/sutao/aggbug/161878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sutao/" target="_blank">苏醄</a> 2007-11-20 15:59 <a href="http://www.blogjava.net/sutao/articles/161878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>