亚洲国产精品第一区二区三区,亚洲午夜成人精品电影在线观看,亚洲人成77777在线观看网http://www.tkk7.com/sutao/用文字記錄學習的體驗!zh-cnSat, 10 May 2025 12:30:13 GMTSat, 10 May 2025 12:30:13 GMT60tomcat6使用niohttp://www.tkk7.com/sutao/articles/162796.html蘇醄蘇醄Sat, 24 Nov 2007 02:48:00 GMThttp://www.tkk7.com/sutao/articles/162796.htmlhttp://www.tkk7.com/sutao/comments/162796.htmlhttp://www.tkk7.com/sutao/articles/162796.html#Feedback1http://www.tkk7.com/sutao/comments/commentRss/162796.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162796.html很早就聽說tomcat6使用nio了,這幾天突然想到一個問題,使用nio代替傳統的bio,ThreadLocal豈不是會存在沖突?
  
  
  
  首先,何謂nio?
  
  如果讀者有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狀態。
  
  按照大多數人的說法,堵塞socket比非堵塞socket的性能要好。不過也有小部分人并不是這樣認為的,例如Indy項目(Delphi一個比較出色的網絡包),它就是使用多線程+堵塞socket模式的。另外,堵塞socket比非堵塞socket容易理解,符合一般人的思維,編程相對比較容易。
  
  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)被引入。
  
  BIO與NIO一個比較重要的不同,是我們使用BIO的時候往往會引入多線程,每個連接一個單獨的線程;而NIO則是使用單線程或者只使用少量的多線程,每個連接共用一個線程。
  
  
  
  這個時候,問題就出來了:我們非常多的java應用是使用ThreadLocal的,例如JSF的FaceContext、Hibernate的session管理、Struts2的Context的管理等等,幾乎所有框架都或多或少地應用ThreadLocal。如果存在沖突,那豈不驚天動地?
  
  后來終于在Tomcat6的文檔(http://tomcat.apache.org/tomcat-6.0-doc/aio.html)找到答案。根據上面說明,應該Tomcat6應用nio只是用在處理發送、接收信息的時候用到,也就是說,tomcat6還是傳統的多線程Servlet,我畫了下面兩個圖來列出區別:
  
  
  
  tomcat5:客戶端連接到達 -> 傳統的SeverSocket.accept接收連接 -> 從線程池取出一個線程 -> 在該線程讀取文本并且解析HTTP協議 -> 在該線程生成ServletRequest、ServletResponse,取出請求的Servlet -> 在該線程執行這個Servlet -> 在該線程把ServletResponse的內容發送到客戶端連接 -> 關閉連接。
  
  我以前理解的使用nio后的tomcat6:客戶端連接到達 -> nio接收連接 -> nio使用輪詢方式讀取文本并且解析HTTP協議(單線程) -> 生成ServletRequest、ServletResponse,取出請求的Servlet -> 直接在本線程執行這個Servlet -> 把ServletResponse的內容發送到客戶端連接 -> 關閉連接。
  
  實際的tomcat6:客戶端連接到達 -> nio接收連接 -> nio使用輪詢方式讀取文本并且解析HTTP協議(單線程) -> 生成ServletRequest、ServletResponse,取出請求的Servlet -> 從線程池取出線程,并在該線程執行這個Servlet -> 把ServletResponse的內容發送到客戶端連接 -> 關閉連接。
  
  
  
  從上圖可以看出,BIO與NIO的不同,也導致進入客戶端處理線程的時刻有所不同:tomcat5在接受連接后馬上進入客戶端線程,在客戶端線程里解析HTTP協議,而tomcat6則是解析完HTTP協議后才進入多線程,另外,tomcat6也比5早脫離客戶端線程的環境。
  
  實際的tomcat6與我之前猜想的差別主要集中在如何處理servlet的問題上。實際上即使拋開ThreadLocal的問題,我之前理解tomcat6只使用一個線程處理的想法其實是行不同的。大家都有經驗:servlet是基于BIO的,執行期間會存在堵塞的,例如讀取文件、數據庫操作等等。tomcat6使用了nio,但不可能要求servlet里面要使用nio,而一旦存在堵塞,效率自然會銳降。
  
  
  
  
  所以,最終的結論當然是tomcat6的servlet里面,ThreadLocal照樣可以使用,不存在沖突。
  

蘇醄 2007-11-24 10:48 發表評論
]]>
高效javahttp://www.tkk7.com/sutao/articles/162793.html蘇醄蘇醄Sat, 24 Nov 2007 02:24:00 GMThttp://www.tkk7.com/sutao/articles/162793.htmlhttp://www.tkk7.com/sutao/comments/162793.htmlhttp://www.tkk7.com/sutao/articles/162793.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162793.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162793.html每一種語言都有其自身的特點,只有掌握了其自身的特點,才能用它編寫出高效的程序。下面就我個人實踐所知談談javaSE方面的性能問題,
javaEE方面的性能暫不討論,要是時間可以再寫一javaEE方面的性能問題的帖子。

1, 盡量不要使用+號來連接字符串,至少不要在隔行中使用+來連接字符串。因為有的java虛擬機可能對字符串連接+做了性能優化,在都同行的+字符串連接,轉化為StringBuffer的append()方法來連接,所以在同行使用+和使用StringBuffer的append 來做連接性能上差不多。
2, 對小數據int的Integer封裝,盡量的使用Integer.valueOf()創建,而不要使用new來創建。因為Integer類緩存了從-128到256個 狀態的Integer。
3, 對Boolean類,要用valueOf()或使用Boolean.TRUE或Boolean.FALSE來創建對象。我個人覺得對Boolean類用private構造函數,可能就會避免不好的使用Boolean類了。
4, 在設計類時應盡可能地避免在類的默認構造函數中創建,初始化大量的對象。
5, 合理的申請數組空間,如果數組中所保存的元素占用內存空間較大或數組本身長度較長的情況,我們釆用可以釆用軟引用的技術來引用數組,以“提醒”JVM及時的回收垃圾內存,維護系統的穩定性。
6,  避免創建重復的對象,我們在編寫一個方法的時候應該先考慮方法里的局部對象域能否改為private static final,從而避免創建重復的對象。
7, 把try/catch塊放入循環體內,會極大的影響性能,如果編譯JIT被關閉或者你所使用的一個不帶JIT的JVM,性能會將下降21%之多!
8,StringBuffer的構造器會創建一個默認大小(通常是16)的字符數組。在使用中,如果超出這個大小,就會重新分配內存,創建一個更大的數組,并將原先的數組復制過來,再丟棄舊的數組。在大多數情況下,你可以在創建StringBuffer的時候指定大小,這樣就避免了在容量不夠的時候自動增長,以提高性能。
9,   使用Java NIO提高服務端程序的性能。
10,考慮用靜態工廠方法替代構造函數。
11,在對大量的數組拷貝時,可以考慮用Arrays.copyOf()來拷貝。
12, 在并發的情況下,要合理的選擇同步的策略,應該謹慎的控制synchronized塊的大小,不可以將一個操作分解到多個synchronized 但也要盡量地從synchronized塊中分離耗時的且不影響并發的操作。
13,要合理的選擇集合框架,例如:ArrayList和LinkedList在某些不同的場合,其性能相差很大。對要做大量的插入時, LinkedList 的性能比ArrayList的性能好。對要做大量隨機查找的時候用ArrayList的性能比用LinkedList的性能好。還有在不需要并發操作的情況下,選擇非線程安全的集合比線程安全的集合要好。如在非線程安全的要求下,選擇ArrayList要比Vector好。
14,不要在循環語句塊中調用length()方法做為循環結束的條件。
15,如果字符串特別長,不要釆用charAt()一一的獲取特定位置的字符,而應該調用toCharArray()方法轉化為字符數組,然后通過數組 索引值獲取指定位置的字符。
16,如果是想把數據封裝成Double類型的,不要這樣使用new Double("1.23"),而要應這樣使用new Double(1.23),雖然二者都沒有語法 的錯誤,也都能達到預期的結果,但其性能有著很大的差異。
17, 應盡量的通過緩沖流類來提高I/O操作效率,但也要合理的選擇緩沖大小 。
    呵呵,好了,今天就寫到這吧,以后要是有時間再繼續寫。小弟我初學java,不對之地,歡迎大家指正,補遺。

蘇醄 2007-11-24 10:24 發表評論
]]>
tomcat常識(apache)http://www.tkk7.com/sutao/archive/2007/11/24/162781.html蘇醄蘇醄Sat, 24 Nov 2007 01:10:00 GMThttp://www.tkk7.com/sutao/archive/2007/11/24/162781.htmlhttp://www.tkk7.com/sutao/comments/162781.htmlhttp://www.tkk7.com/sutao/archive/2007/11/24/162781.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162781.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162781.html一、小貓TOMCAT其實很可愛

2003年底,我換公司了,同樣也換了WEBAPP,TOMCAT出現在我的面前(以前使用weblogic),我有點茫然,免費的東西真的能用的好么?擔心ING……(其實是在火星呆太久)出門一打聽,原來此貓出自名門-jakarta項目,2001年度最具創新的java產品(Most Innovative Java Product),又有JAVA的老大SUN的力捧(官方推薦的servlet和jsp容器),以后就靠它吃飯了。不說二話,搞起來先:

1、 安裝

TOMCAT最新版本是5.0.29(http://jakarta.apache.org/site/binindex.cgi)

如果在WINDOWS下它可以自動找到你的JDK或者set JAVA_HOME=c:/jdk

在LINUX下需要先解壓,然后設置JAVA_HOME

export JAVA_HOME=/usr/local/jdk

2、 RUN

設置完畢后就可以運行tomcat服務器了,進入tomcat的bin目錄,WINDOWS下用startup啟動tomcat,linux下用startup.sh,相應的關閉tomcat的命令為shutdown和shutdown.sh。

啟動服務后在瀏覽器里輸入http://localhost:8080來測試一下

3、 目錄結構

Bin:存放啟動和關閉tomcat腳本。

Conf:包含不同的配置文件,server.xml(Tomcat的主要配置文件)。

Work:存放jsp編譯后產生的class文件。

Webapp:存放應用程序示例,以后你要部署的應用程序也要放到此目錄。

Logs:存放日志文件

Comm./server/shared:這三個文件夾下的LIB文件夾放jar文件。

1、 配置server.xml文件

沒有什么好說的,看TOMCAT的文檔比較有用,這里提供一些主要的東西吧。

元素名
屬性
解釋

server
port
指定一個端口,這個端口負責監聽關閉tomcat的請求

shutdown
指定向端口發送的命令字符串

service
name
指定service的名字

Connector(表示客戶端和service之間的連接)
port
指定服務器端要創建的端口號,并在這個斷口監聽來自客戶端的請求

minProcessors
服務器啟動時創建的處理請求的線程數

maxProcessors
最大可以創建的處理請求的線程數

enableLookups
如果為true,則可以通過調用request.getRemoteHost()進行DNS查詢來得到遠程客戶端的實際主機名,若為false則不進行DNS查詢,而是返回其ip地址

redirectPort
指定服務器正在處理http請求時收到了一個SSL傳輸請求后重定向的端口號

acceptCount
指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理

connectionTimeout
指定超時的時間數(以毫秒為單位)

Engine(表示指定service中的請求處理機,接收和處理來自Connector的請求)
defaultHost
指定缺省的處理請求的主機名,它至少與其中的一個host元素的name屬性值是一樣的

Context(表示一個web應用程序,通常為WAR文件,關于WAR的具體信息見servlet規范)
docBase
應用程序的路徑或者是WAR文件存放的路徑

path
表示此web應用程序的url的前綴,這樣請求的url為http://localhost:8080/path/****

reloadable
這個屬性非常重要,如果為true,則tomcat會自動檢測應用程序的/WEB-INF/lib 和/WEB-INF/classes目錄的變化,自動裝載新的應用程序,我們可以在不重起tomcat的情況下改變應用程序

host(表示一個虛擬主機)
name
指定主機名

appBase
應用程序基本目錄,即存放應用程序的目錄

unpackWARs
如果為true,則tomcat會自動將WAR文件解壓,否則不解壓,直接從WAR文件中運行應用程序

Logger(表示日志,調試和錯誤信息)
className
指定logger使用的類名,此類必須實現org.apache.catalina.Logger 接口

prefix
指定log文件的前綴

suffix
指定log文件的后綴

timestamp
如果為true,則log文件名中要加入時間,如下例:localhost_log.2001-10-04.txt

Realm(表示存放用戶名,密碼及role的數據庫)
className
指定Realm使用的類名,此類必須實現org.apache.catalina.Realm接口

Valve(功能與Logger差不多,其prefix和suffix屬性解釋和Logger 中的一樣)
className
指定Valve使用的類名,如用org.apache.catalina.valves.AccessLogValve類可以記錄應用程序的訪問信息

directory
指定log文件存放的位置

pattern
有兩個值,common方式記錄遠程主機名或ip地址,用戶名,日期,第一行請求的字符串,HTTP響應代碼,發送的字節數。combined方式比common方式記錄的值更多

2、 管理

TOMCAT管理能力很強大,進入http://localhost:8080/,自己慢慢管吧。實踐出真知,我喜歡這樣搞:

^_^,一切盡在掌握http://localhost:8080/manager/html 。

一、讓數據庫連接池轉起來

作為一個J2EE程序員大家手上可能會有現成的JDBC 數據庫連接池,其實這沒有太大的必要,因為象weblogic……企業級WEBAPP都有自己的連接池,大家不要費力直接使用吧,效率也很不錯,再也不用羨慕.NET的ADO了(以前作MS從來不擔心數據連接,ADO確實用起來很爽),如果想實現一個 JDBC connection pool 的注意事項有:

1. 有一個簡單的函數從連接池中得到一個 Connection。

2. close 函數必須將 connection 放回 數據庫連接池。

3. 當數據庫連接池中沒有空閑的 connection, 數據庫連接池必須能夠自動增加 connection 個數。

4. 當數據庫連接池中的 connection 個數在某一個特別的時間變得很大,但是以后很長時間只用其中一小部分,應該可以自動將多余的 connection 關閉掉。

5. 如果可能,應該提供debug 信息報告沒有關閉的 new Connection 。

網上有各種各樣的連接池代碼,抄過來改改吧,嘿嘿~

這里介紹如何配置TOMCAT的連接池,以SQLSERVER為例:

步驟1:安裝SQLSERVER的JDBC驅動

SQLSERVER的JDBC驅動其實就是三個JAR文件,msbase.jar/mssqlserver.jar/msutil.jar,將這三個文件拷貝到你的/tomcat_home/common/lib目錄下去就可以了。

步驟2:修改server.xml文件

具體代碼如下:

<Context path="test" docBase="F:\yourroot" debug="5" reloadable="true" crossContext="true">

<Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_DBTest_log." suffix=".txt" timestamp="true"/>

<Resource name="jdbc/SqlServerDB" auth="Container" type="javax.sql.DataSource"/>

<ResourceParams name="jdbc/SqlServerDB">

<parameter>

<name>factory</name>

<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

</parameter>

<!-- 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.-->

<parameter>

<name>maxActive</name>

<value>50</value>

</parameter>

<!-- Maximum number of idle dB connections to retain in pool. Set to 0 for no limit.-->

<parameter>

<name>maxIdle</name>

<value>20</value>

</parameter>

<!-- 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. -->

<parameter>

<name>maxWait</name>

<value>500</value>

</parameter>

<!-- msSQL dB username and password for dB connections -->

<parameter>

<name>username</name>

<value>sa</value>

</parameter>

<parameter>

<name>password</name>

<value>sa</value>

</parameter>

<!-- Class name for SQLServer2000 JDBC driver -->

<parameter>

<name>driverClassName</name>

<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>

</parameter>

<!-- 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.-->

<parameter>

<name>url</name>

<value>jdbc:microsoft:sqlserver://10.0.254.11:1433;databaseName=yourdb</value>

<!--must use & not use & -->

</parameter>

</ResourceParams>

</Context>

步驟三:程序調用

package dbmanage;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.Date;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.Vector;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.sql.DataSource;

import util.smartDateFormat;

public class dbManager {

/************************************

* @param static private boolean VERBOSE ;

* @param Statement theStatement;

* @param PreparedStatement thePstmt;

* @param Connection theConnection;

************************************/

final static private boolean VERBOSE = true; //打印控制臺控制

//static Logger logger = Logger.getLogger(dbManager.class.getName());

private Context initCtx = null;

private Context ctx = null;

private DataSource ds = null;

private long timeout = 5000;

private Statement theStatement = null;

private PreparedStatement thePstmt = null;

/************************************

* 初試化initCtx

* 取得數據源對象

************************************/

public

dbManager() {

try {

initCtx = new InitialContext();

//init context,read config web.xml

if (initCtx == null) {

throw new Exception("Initial Failed!");

}

ctx = (Context) initCtx.lookup("java:comp/env");

//find "jdbc/SqlServerDB" object this configruation in the SERVER.XML of Tomcat

if (ctx != null) {

ds = (DataSource) ctx.lookup("jdbc/SqlServerDB");

}

if (ds == null) {

throw new Exception("Look up DataSource Failed!");

}

}

catch (Exception e) {

log(e, "Can't get the Context!");

}

}

/************************************

* get Connection

* @return Connection

************************************/

public synchronized

Connection getConnection() {

//get connection and set to delay time

long startTime = new java.util.Date().getTime();

Connection con = null;

while (con == null) {

con = newConnection();

if (con != null) {

//log("Create New Connection!");

break;

}

try {

log("連接超時,重新連接,等待" + timeout + "ms");

wait(timeout);

}

catch (InterruptedException e) {

log(e, "連接超時!");

}

if ( (new java.util.Date().getTime() - startTime) >= timeout) {

log("Connection timeout!");

break;

}

}

return con;

}

private

Connection newConnection() {

Connection con = null;

try {

con = ds.getConnection();

if (con == null) {

throw new Exception("Create Connection Failed!");

}

}

catch (Exception e) {

log("Create Connection Failed!");

System.out.println(e.getMessage());

}

return con;

}

/************************************

* release the connection

* @param conn Connection

* @param stmt Statement

* @param pstmt PreparedStatement

************************************/

public synchronized

void freeConnection(Connection conn,

Statement stmt,

PreparedStatement pstmt) {

try {

//close Statement

if (stmt != null) {

stmt.close();

stmt = null;

//log("Close Statement......");

}

//close PreparedStatement

if (pstmt != null) {

pstmt.close();

pstmt = null;

//log("Close PreparedStatement......");

}

}

catch (Exception e) {

System.out.println(e.getMessage());

}

try {

//close Connection

if (conn != null) {

conn.close();

conn = null;

//log("Close Connection......");

}

}

catch (SQLException e) {

log(e, "釋放資源出錯!");

}

}

/************************************

* write log file.

* @param s String

************************************/

private

void log(String s) {

if (VERBOSE) {

System.out.println(new java.util.Date() + ":" + s);

//logger.info(new java.util.Date()+s);

}

}

/************************************

* write log file.

* @param ex Object

************************************/

private

void logerr(Object ex) {

if (VERBOSE) {

//System.out.println(new java.util.Date()+":"+s);

//logger.error(ex);

}

}

/************************************

* write log file.

* @param e Throwable

* @param msg String

************************************/

private

void log(Throwable e, String msg) {

System.out.println(new java.util.Date() + ": " + msg);

//logger.info(new java.util.Date() + ": " + msg, e);

}

……

}

OK,你現在可以方便的使用連接池了,想要一個得一個,記得要釋放哦,連接池的數量總是有限的。

二、中文問題照樣很簡單

每個國家(或區域)都規定了計算機信息交換用的字符編碼集,如美國的擴展 ASCII碼, 中國的 GB2312-80,日本的 JIS 等,作為該國家/區域內信息處理的基礎,有著統一編碼的重要作用。字符編碼集按長度分為 SBCS(單字節字符集),DBCS(雙字節字符集)兩大類。早期的軟件(尤其是操作系統),為了解決本地字符信息的計算機處理,出現了各種本地化版本(L10N),為了區分,引進了 LANG, Codepage 等概念。但是由于各個本地字符集代碼范圍重疊,相互間信息交換困難;軟件各個本地化版本獨立維護成本較高。因此有必要將本地化工作中的共性抽取出來,作一致處理,將特別的本地化處理內容降低到最少。這也就是所謂的國際化(I18N)。各種語言信息被進一步規范為 Locale 信息。處理的底層字符集變成了幾乎包含了所有字形的 Unicode。

現在大部分具有國際化特征的軟件核心字符處理都是以 Unicode 為基礎的,在軟件運行時根據當時的 Locale/Lang/Codepage 設置確定相應的本地字符編碼設置,并依此處理本地字符。在處理過程中需要實現 Unicode 和本地字符集的相互轉換,甚或以 Unicode 為中間的兩個不同本地字符集的相互轉換。這種方式在網絡環境下被進一步延伸,任何網絡兩端的字符信息也需要根據字符集的設置轉換成可接受的內容。

Java 語言內部是用 Unicode 表示字符的,遵守 Unicode V2.0。Java 程序無論是從/往文件系統以字符流讀/寫文件,還是往 URL 連接寫 HTML 信息,或從 URL 連接讀取參數值,都會有字符編碼的轉換。這樣做雖然增加了編程的復雜度,容易引起混淆,但卻是符合國際化的思想的。從理論上來說,這些根據字符集設置而進行的字符轉換不應該產生太多問題。而事實是由于應用程序的實際運行環境不同,Unicode 和各個本地字符集的補充、完善,以及系統或應用程序實現的不規范,轉碼時出現的問題時時困擾著程序員和用戶。

其實解決 JAVA 程序中的漢字編碼問題的方法往往很簡單,但理解其背后的原因,定位問題,還需要了解現有的漢字編碼和編碼轉換。相信這樣的東西大家都見過了

new String(request.getParameter("test").getBytes("iso-8859-1"),"GBK")

但這樣的代碼相信不是一個解決的辦法,這樣會增加程序的復雜度,寫數據庫,提交表單,URL中傳中文參數,到處都是中文問題!作為一個連走路都要算計最短距離的懶人,當然不愿天天叨念著new String(request.getParameter("test").getBytes("iso-8859-1"),"GBK"),然漢戰戰兢兢的處理各種字符轉換的問題,我跋山涉水,翻山越嶺,終于找到了完美的解決方式,在TOMCAT中只需要簡單的配置,引入2個文件就可以輕松搞定。

前提條件,每個頁面使用

<%@ page contentType="text/html; CHARSET=utf8" language="java" import="java.sql.*" errorPage="" %>

<meta http-equiv="Content-Type" content="text/html; CHARSET=utf8">

地球人都知道的東西。

步驟1:添加過濾器

在TOMCAT中找到這2個文件RequestDumperFilter.java, SetCharacterEncodingFilter.java,他們位于D:\Tomcat5.0.27\webapps\jsp-examples \WEB-INF\classes\filters,加到你的工程文件里去,編譯他們。

步驟2:配置WEB.XML

在web.xml里加入這一段

……

<filter>

<filter-name>Set Character Encoding</filter-name>

<filter-class>filters.SetCharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>GBK</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>Set Character Encoding</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

……

看到沒有?這樣你就不用寫那些麻煩的轉換代碼了,當然這樣還不足以解決問題。

步驟3:修改server.xml

在server.xml修改2個地方

<Connector port="8080"

maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

enableLookups="false" redirectPort="8443" acceptCount="100"

debug="0" connectionTimeout="20000"

disableUploadTimeout="true" URIEncoding='GBK'/>

<Connector className="org.apache.coyote.tomcat5.CoyoteConnector"

port="8009" minProcessors="5" maxProcessors="75"

enableLookups="true" redirectPort="8443"

acceptCount="10" debug="0" connectionTimeout="0"

useURIValidationHack="false" protocol="AJP/1.3"

protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"

URIEncoding='GBK'/>

OK,搞定!

三、APACHE和TOMCAT他們倆關系非同一般

Apache和tomcat都是很優秀的軟件,更可貴的是它們是免費的。其實他們2個都是jakarta項目的重要組成部分。按輩分來講, TOMCAT是APACHE的兒子,APACHE的專長是解析靜態文件,CGI,PHP……圖片……,兒子當然不能搶了老爹的飯碗,所以TOMCAT只有在J2EE這個上面發憤圖強,其實TOMCAT并非不能干他老爹的活,只是穩定性差點而已(偶沒有明顯的感覺,可能是商業炒作吧),現在大家明白為什么把他們2個扯一起了吧,上陣還靠父子兵呢~

把2個家伙整一起有大致有2種方法,一種是利用mod_jk2.so,一種是利用mod_jk_1.2.5_2.0.47.dll。這2個東東叫聯接器(TOMCAT就是通過這家伙與apache勾搭上的)

1、 利用mod_jk_1.2.5_2.0.47.dll在WINDOWS下整合

步驟1:準備材料

apache2.0.52

http://apache.te8.com/dist/httpd/binaries/win32/apache_2.0.52-win32-x86-no_ssl.msi

tomcat5.0.27

http://apache.linuxforum.net/dist/jakarta/tomcat-5/v5.0.19/bin/jakarta-tomcat-5.0.27.exe

JDK(這個不用說了吧^_^)

mod_jk_1.2.5_2.0.47.dll(關鍵是這個東東啊,找了我N久),據說在下面連接可以下到,最后在我同事那找到的。

http://apache.linuxforum.net/dist/jakarta/tomcat-connectors/jk/binaries/win32/mod_jk_1.2.5_2.0.47.dll

安裝apache\ tomcat\JDK。

步驟2:安裝后設置環境變量

設置我的電腦\屬性\高級\環境變量\新建系統變量 變量名:JAVA_HOME 變量值:C:\JBuilderX\jdk1.4 (指向JDK的實際安裝路徑);TOMCAT_HMOM 變量值:Tomcat5.0.27;lasspath 編輯變量值中加上 ……;%JAVA_HOME%\bin;%JAVA_HOME%\lib;%TOMCAT_HOME%\bin;.;

測試一下,訪問http://localhost和http://localhost:8080,默認安裝是不會有什么錯誤的^_^

把連接器mod_jk_1.2.5_2.0.47.dll COPY到D:\Apache2\modules\下。

步驟3:apache配置

在d:\Apache2\conf下找到httpd.conf,找到DirectoryIndex,在index.html后添加index.jsp;查找“listen”用于本機測試時:Listen 127.0.0.1:80,我的是這樣設置的Listen *:80

查找AddDefaultCharset設置為AddDefaultCharset off,這樣APACHE將以你頁面定義的字符集解析頁面。

在最后添加如下代碼:

<VirtualHost *:80> #localhost為本機,你可用本機ip

ServerAdmin darkxie@hotmail.com #你的mail地址

DocumentRoot F:/uutang/uutang #你的項目組根目錄

ServerName dark #你的服務名,若你的機器有域名,設為域名

ErrorLog logs/ErrorLog.txt #錯誤日志

CustomLog logs/CustomLog.txt common #訪問日志

JkMount /servlet/* ajp13 #讓Apache支持對servlet傳送,用以Tomcat解析

JkMount /*.jsp ajp13 #讓Apache支持對jsp傳送,用以Tomcat解析

JkMount /*.do ajp13 #讓Apache支持對struts的action傳送,用以Tomcat解析

</VirtualHost>

LoadModule jk_module modules/mod_jk_1.2.5_2.0.47.dll

JkWorkersFile "D:/Tomcat5.0.27/conf/workers.properties"

JkLogFile "D:/Tomcat5.0.27/logs/mod_jk2.log"

JkLogLevel info

步驟4:tomcat配置

在d:\Tomcat5\conf下新建一個workers.properties文件 .內容如下:

workers.tomcat_home=d:\Tomcat5 #讓mod_jk模塊知道Tomcat

workers.java_home=d:\jdk1.3 #讓mod_jk模塊知道j2sdk

ps=\

worker.list=ajp13 #模塊版本,現有ajp13了,不要修改

worker.ajp13.port=8009 #工作端口,若沒占用則不用修改

worker.ajp13.host=localhost #主機,若上面的Apache主機不為localhost,作相應修改

worker.ajp13.type=ajp13 #類型

worker.ajp13.lbfactor=1 #代理數,不用修改

修改TOMCAT的server.xml文件:

<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->

<Connector className="org.apache.coyote.tomcat5.CoyoteConnector"

port="8009" minProcessors="5" maxProcessors="75"

enableLookups="true" redirectPort="8443"

acceptCount="10" debug="0" connectionTimeout="0"

useURIValidationHack="false" protocol="AJP/1.3"

protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"

URIEncoding='GBK'/>

讓TOMCAT知道ajp13協議,apache和tomcat倆父子間靠這個協議溝通。

測試一下,訪問http://localhost和http://localhost:8080,看到相同的頁面沒有?細心點,其實很簡單,看看E文的幫助,搞定不成問題。

2、 利用mod_jk2.so(也叫JK2)整合

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整合大同小異,只是換了個聯接器而已,現在一步一步整起來~

步驟1:沒有多說的,安裝好TOMCAT和APACHE

下載jakarta-tomcat-connectors-jk2.0.4-win32-apache2.0.49.zip,解壓,將mod_jk2放到apache的安裝文件夾下的modules文件夾中。

步驟2:apache配置

在/conf中加入一個work.properties文件,其內容如下:

<!--這個文件的作用不是很清楚,總之路徑設置正確就行了。我的apache裝在D:/Apache2,根據情況自己修改。-->

[shm]

file=D:/ /Apache2/logs/shm.file

size=1048576

<!--這個socket channel是必須的,port和host對應于tomcat端的設置。-->

#The socket channel

[channel.socket:localhost:8009]

port=8009

host=localhost

<!--worker,必須的。-->

#define the worker

[ajp13:localhost:8009]

channel=channel.socket:localhost:8009

<!--url mapping,我的主要是.jsp和struts的.do,servlet的話設置成[uri:/xxx/*]之類的。-->

#uri mapping

[uri:/*] #和第一種方式一樣吧^_^

[uri:/*.jsp]

[uri:/*.do]

worker=ajp13:localhost:8009

在httpd.conf中,在LoadModule那里加入這句:

LoadModule jk2_module modules/mod_jk2.so

在最后加入這句:

JkSet config.file "conf/work.properties"

這是告訴apache去哪里找jk的配置的,根據具體情況修改。

還要修改一下DirectoryIndex,DirectoryIndex index.html index.html.var index.jsp查找“listen”用于本機測試時:Listen 127.0.0.1:80,我的是這樣設置的Listen *:80。

當然還有我們的虛擬目錄:

<VirtualHost *:80>

ServerAdmin darkxie@hotmail.com

DocumentRoot F:/uutang/uutang

ServerName dark

ErrorLog logs/ErrorLog.txt

CustomLog logs/CustomLog.txt common

#JkMount /servlet/* ajp13

#JkMount /*.jsp ajp13

#JkMount /*.do ajp13

</VirtualHost>

步驟3:tomcat配置

Tomcat的端口設置為8080。

在/conf文件夾加入jk2.properties文件,其內容如下:

# Set the desired handler list

handler.list=apr,request,channelSocket

#

# Override the default port for the socketChannel

channelSocket.port=8009

TOMCAT自己已經生成了這個文件,找到相關的地方把注視去掉改一下就成。

注意:用這種方式整合最好是自己編譯mod_jk2.so文件,特別是在unix/linux下,我沒有環境,制作mod_webapp.so沒有自己作過。具體方法,自己去找吧



蘇醄 2007-11-24 09:10 發表評論
]]>
Tomcat性能調整http://www.tkk7.com/sutao/articles/162665.html蘇醄蘇醄Fri, 23 Nov 2007 08:27:00 GMThttp://www.tkk7.com/sutao/articles/162665.htmlhttp://www.tkk7.com/sutao/comments/162665.htmlhttp://www.tkk7.com/sutao/articles/162665.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162665.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162665.htmlTomcat性能調整    文章指數:0  CSDN Blog推出文章指數概念,文章指數是對Blog文章綜合評分后推算出的,綜合評分項分別是該文章的點擊量,回復次數,被網摘收錄數量,文章長度和文章類型;滿分100,每月更新一次。


一. 引言
性能測試與分析是軟件開發過程中介于架構和調整的一個廣泛并比較不容易理解的領域,更是一項較為復雜的活動。就像下棋游戲一樣,有效的性能測試和分析只能在一個良好的計劃策略和具備了對不可預料事件的處理能力的條件下順利地完成。一個下棋高手贏得比賽靠的不僅僅是對游戲規則的認識,更是靠他的自己的能力和不斷地專注于分析自己對手的實力來更加有效地利用和發揮規則的作用。同樣一個優秀的性能測試和分析人員將要面對的是來自一個全新的應用程序和環境下帶來的整個項目的挑戰。本文中作者結合自己的使用經驗和參考文檔,對Tomcat性能方面的調整做一簡要的介紹,并給出Tomcat性能的測試、分析和調整優化的一些方法。

二. 測量Web服務器的性能
測量web服務器的性能是一項讓人感到畏縮的任務,但是我們在這里將給出一些需要注意的地方并且指點你了解其中更多的細節性的內容。它不像一些簡單的任務,如測量CPU的速率或者是測量程序占用CPU的比例,web服務器的性能優化中包括許調整許多變量來達到目標。許多的測量策略中都包含了一個看似簡單的瀏覽實際上是在向服務器發送大量的請求,我們稱之為客戶端的程序,來測量響應時間。客戶端和服務器端是在同一臺機器上嗎?服務器在測試的時候還運行著其它的什么程序嗎?客戶端和服務器端的通訊是通過局域網,100baseT,10baseT還是使用調制解調器?客戶端是否一直重復請求相同的頁面,還是隨機地訪問不同的頁面?(這些影響到了服務緩存的性能)客戶端發送請求的有規律的還是突發的?你是在最終的配置環境下運行服務的還是在調試的配置環境下運行服務的?客戶端請求中包含圖片還是只有HTML頁面?是否有請求是通過servlets和 JSP的,CGI程序,服務端包含(Server-Side Includes ,SSI是一個可以讓你使用動態HTML文件的技術)?所有這些都將是我們要關心的,并且幾乎我們不可能精確地把所有的問題都清楚地列出來。

1.壓力測試工具

“工欲善其事,必先利其器”,壓力測試只有借助于一些工具才可得以實施。

大多數web壓力測試工具的實現原理都是通過重復的大量的頁面請求來模擬多用戶對被測系統的并發訪問,以此達到產生壓力的目的。產生壓力的手段都是通過錄制或者是編寫壓力腳本,這些腳本以多個進程或者線程的形式在客戶端運行,這樣通過人為制造各種類型的壓力,我們可以觀察被測系統在各種壓力狀況下的表現,從而定位系統瓶頸,作為系統調優的基礎。目前已經存在的性能測試工具林林總總,數量不下一百種,從單一的開放源碼的免費小工具如 Aapache 自帶的 web 性能測試工具 Apache Benchmark、開源的Jmeter 到大而全的商業性能測試軟件如 Mercury 的 LoadRunner 等等。任何性能測試工具都有其優缺點,我們可以根據實際情況挑選用最合適的工具。您可以在這里找到一些web壓力測試工具http://www.softwareqatest.com/qatweb1.html#LOAD

這里我們所使用的工具要支持web應用服務認證才可以,要支持接收發送cookies,不僅如此Tomcat支持多種認證方式,比如基本認證、基于表單的認證、相互認證和客戶端認證,而一些工具僅僅支持HTTP基本認證。真實地模擬用戶認證是性能測試工具的一個重要的部分,因為認證機制將對一個web站點的性能特征產生重要的影響。基于你在產品中使用的不同的認證方式,你需要從上面的工具列表中選擇使用這種特性的測試工具。

Apache Benchmark和http_load是命令行形式的工具,非常易于使用。Apache Benchmark可以模仿單獨的URL請求并且重復地執行,可以使用不同的命令行參數來控制執行迭代的次數,并發用戶數等等。它的一個特點是可以周期性地打印出處理過程的信息,而其它工具只能給出一個全局的報告。

2.壓力測試工具介紹

三. 外部環境的調整
在Tomcat 和應用程序進行了壓力測試后,如果您對應用程序的性能結果不太滿意,就可以采取一些性能調整措施了,當然了前提是應用程序沒有問題,我們這里只講 Tomcat的調整。由于Tomcat的運行依賴于JVM,所以在這里我們把Tomcat的調整可以分為兩類來詳細描述:

  外部環境調整

  調整非Tomcat組件,例如Tomcat運行的操作系統和運行Tomcat的java虛擬機。

  自身調整

  修改Tomcat自身的參數,調整Tomcat配置文件中的參數。

  下面我們將詳細講解外部環境調整的有關內容,Tomcat自身調整的內容將在第2部分中闡述。1.JAVA虛擬機性能優化

  Tomcat本身不能直接在計算機上運行,需要依賴于硬件基礎之上的操作系統和一個java虛擬機。您可以選擇自己的需要選擇不同的操作系統和對應的 JDK的版本(只要是符合Sun發布的Java規范的),但我們推薦您使用Sun公司發布的JDK。確保您所使用的版本是最新的,因為Sun公司和其它一些公司一直在為提高性能而對java虛擬機做一些升級改進。一些報告顯示JDK1.4在性能上比JDK1.3提高了將近10%到20%。

  可以給Java虛擬機設置使用的內存,但是如果你的選擇不對的話,虛擬機不會補償。可通過命令行的方式改變虛擬機使用內存的大小。如下表所示有兩個參數用來設置虛擬機使用內存的大小。
參數
 描述
 
-Xms<size>
 JVM初始化堆的大小
 
-Xmx<size>
 JVM堆的最大值
 


  這兩個值的大小一般根據需要進行設置。初始化堆的大小執行了虛擬機在啟動時向系統申請的內存的大小。一般而言,這個參數不重要。但是有的應用程序在大負載的情況下會急劇地占用更多的內存,此時這個參數就是顯得非常重要,如果虛擬機啟動時設置使用的內存比較小而在這種情況下有許多對象進行初始化,虛擬機就必須重復地增加內存來滿足使用。由于這種原因,我們一般把-Xms和-Xmx設為一樣大,而堆的最大值受限于系統使用的物理內存。一般使用數據量較大的應用程序會使用持久對象,內存使用有可能迅速地增長。當應用程序需要的內存超出堆的最大值時虛擬機就會提示內存溢出,并且導致應用服務崩潰。因此一般建議堆的最大值設置為可用內存的最大值的80%。

  Tomcat默認可以使用的內存為128MB,在較大型的應用項目中,這點內存是不夠的,需要調大。

  Windows下,在文件{tomcat_home}/bin/catalina.bat,Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下設置:

  JAVA_OPTS='-Xms【初始化內存大小】 -Xmx【可以使用的最大內存】'

  需要把這個兩個參數值調大。例如:

  JAVA_OPTS='-Xms256m -Xmx512m'

  表示初始化內存為256MB,可以使用的最大內存為512MB。

  另外需要考慮的是Java提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應用有關,應該通過分析實際的垃圾收集的時間和頻率來調整。如果堆的大小很大,那么完全垃圾收集就會很慢,但是頻度會降低。如果你把堆的大小和內存的需要一致,完全收集就很快,但是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。在基準測試的時候,為保證最好的性能,要把堆的大小設大,保證垃圾收集不在整個基準測試的過程中出現。

  如果系統花費很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應該不超過 3-5 秒。如果垃圾收集成為瓶頸,那么需要指定代的大小,檢查垃圾收集的詳細輸出,研究 垃圾收集參數對性能的影響。一般說來,你應該使用物理內存的 80% 作為堆大小。當增加處理器時,記得增加內存,因為分配可以并行進行,而垃圾收集不是并行的。

2.操作系統性能優化

  這里說的操作系統是指運行web服務器的系統軟件,當然,不同的操作系統是為不同的目的而設計的。比如OpenBSD是面向安全的,因此在它的內核中有許多的限制來防止不同形式的服務攻擊(OpenBSD的一句座右銘是“默認是最安全的”)。這些限制或許更多地用來運行活躍的web服務器。

  而我們常用的Linux操作系統的目標是易用使用,因此它有著更高的限制。使用BSD內核的系統都帶有一個名為“Generic”的內核,表明所有的驅動器都靜態地與之相連。這樣就使系統易于使用,但是如果你要創建一個自定義的內核來加強其中某些限制,那就需要排除不需要的設備。Linux內核中的許多驅動都是動態地加載的。但是換而言之,內存現在變得越來越便宜,所以因為加載額外的設備驅動就顯得不是很重要的。重要的是要有更多的內存,并且在服務器上騰出更多的可用內存。

  小提示:雖然現在內存已經相當的便宜,但還是盡量不要購買便宜的內存。那些有牌子的內存雖然是貴一點,但是從可靠性上來說,性價比會更高一些。

  如果是在Windows操作系統上使用Tomcat,那么最好選擇服務器版本。因為在非服務器版本上,最終用戶授權數或者操作系統本身所能承受的用戶數、可用的網絡連接數或其它方面的一些方面都是有限制的。并且基于安全性的考慮,必須經常給操作系統打上最新的補丁。

  3.Tomcat與其它web服務器整合使用

  雖然tomcat也可以作web服務器,但其處理靜態html的速度比不上apache,且其作為web服務器的功能遠不如apache,因此我們想把 apache和tomcat集成起來,將html與jsp的功能部分進行明確分工,讓tomcat只處理jsp部分,其它的由apache,IIS等這些 web服務器處理,由此大大節省了tomcat有限的工作“線程”。

  4.負載均衡

  在負載均衡的思路下,多臺服務器為對稱方式,每臺服務器都具有同等的地位,可以單獨對外提供服務而無須其他服務器的輔助。通過負載分擔技術,將外部發送來的請求按一定規則分配到對稱結構中的某一臺服務器上,而接收到請求的服務器都獨立回應客戶機的請求。

  提供服務的一組服務器組成了一個應用服務器集群(cluster),并對外提供一個統一的地址。當一個服務請求被發至該集群時,根據一定規則選擇一臺服務器,并將服務轉定向給該服務器承擔,即將負載進行均衡分攤。

  通過應用負載均衡技術,使應用服務超過了一臺服務器只能為有限用戶提供服務的限制,可以利用多臺服務器同時為大量用戶提供服務。當某臺服務器出現故障時,負載均衡服務器會自動進行檢測并停止將服務請求分發至該服務器,而由其他工作正常的服務器繼續提供服務,從而保證了服務的可靠性。

  負載均衡實現的方式大概有四種:第一是通過DNS,但只能實現簡單的輪流分配,不能處理故障,第二如果是基于MS IIS,Windows 2003 server本身就帶了負載均衡服務,第三是硬件方式,通過交換機的功能或專門的負載均衡設備可以實現,第四種是軟件方式,通過一臺負載均衡服務器進行,上面安裝軟件。使用Apache Httpd Server做負載平衡器,Tomcat集群節點使用Tomcat就可以做到以上第四種方式。這種方式比較靈活,成本相對也較低。另外一個很大的優點就是可以根據應用的情況和服務器的情況采取一些策略。

四. 自身調整
本節將向您詳細介紹一些加速可使Tomcat實例加速運行的技巧和方法,無論是在什么操作系統或者何種Java虛擬機上。在有些情況下,您可能沒有控制部署環境上的操作系統或者Java虛擬機。在這種情況下,您就需要逐行了解以下的的一些建議,然而你應該在修改后使之生效。我認為以下方法是Tomcat性能自身調整的最佳方式。

  1.禁用DNS查詢

  當web應用程序向要記錄客戶端的信息時,它也會記錄客戶端的IP地址或者通過域名服務器查找機器名轉換為IP地址。DNS查詢需要占用網絡,并且包括可能從很多很遠的服務器或者不起作用的服務器上去獲取對應的IP的過程,這樣會消耗一定的時間。為了消除DNS查詢對性能的影響我們可以關閉DNS查詢,方式是修改server.xml文件中的enableLookups參數值:


Tomcat4

<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" />

Tomcat5

<Connector port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true"/>


  除非你需要連接到站點的每個HTTP客戶端的機器名,否則我們建議在生產環境上關閉DNS查詢功能。可以通過Tomcat以外的方式來獲取機器名。這樣不僅節省了網絡帶寬、查詢時間和內存,而且更小的流量會使日志數據也會變得更少,顯而易見也節省了硬盤空間。對流量較小的站點來說禁用DNS查詢可能沒有大流量站點的效果明顯,但是此舉仍不失為一良策。誰又見到一個低流量的網站一夜之間就流量大增呢?

  2.調整線程數

  另外一個可通過應用程序的連接器(Connector)進行性能控制的的參數是創建的處理請求的線程數。Tomcat使用線程池加速響應速度來處理請求。在 Java中線程是程序運行時的路徑,是在一個程序中與其它控制線程無關的、能夠獨立運行的代碼段。它們共享相同的地址空間。多線程幫助程序員寫出CPU最大利用率的高效程序,使空閑時間保持最低,從而接受更多的請求。

  Tomcat4中可以通過修改minProcessors和 maxProcessors的值來控制線程數。這些值在安裝后就已經設定為默認值并且是足夠使用的,但是隨著站點的擴容而改大這些值。 minProcessors服務器啟動時創建的處理請求的線程數應該足夠處理一個小量的負載。也就是說,如果一天內每秒僅發生5次單擊事件,并且每個請求任務處理需要1秒鐘,那么預先設置線程數為5就足夠了。但在你的站點訪問量較大時就需要設置更大的線程數,指定為參數maxProcessors的值。 maxProcessors的值也是有上限的,應防止流量不可控制(或者惡意的服務攻擊),從而導致超出了虛擬機使用內存的大小。如果要加大并發連接數,應同時加大這兩個參數。web server允許的最大連接數還受制于操作系統的內核參數設置,通常Windows是2000個左右,Linux是1000個左右。

  在Tomcat5對這些參數進行了調整,請看下表:
屬性名
 描述
 
maxThreads
 Tomcat使用線程來處理接收的每個請求。這個值表示Tomcat可創建的最大的線程數。
 
acceptCount
 指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理。
 
connnectionTimeout
 網絡連接超時,單位:毫秒。設置為0表示永不超時,這樣設置有隱患的。通常可設置為30000毫秒。
 
minSpareThreads
 Tomcat初始化時創建的線程數。
 
maxSpareThreads
 一旦創建的線程超過這個值,Tomcat就會關閉不再需要的socket線程。
 


  最好的方式是多設置幾次并且進行測試,觀察響應時間和內存使用情況。在不同的機器、操作系統或虛擬機組合的情況下可能會不同,而且并不是所有人的web站點的流量都是一樣的,因此沒有一刀切的方案來確定線程數的值。


3.加速JSP編譯速度

  當第一次訪問一個JSP文件時,它會被轉換為Java serverlet源碼,接著被編譯成Java字節碼。你可以控制使用哪個編譯器,默認情況下,Tomcat使用使用命令行javac進行使用的編譯器。也可以使用更快的編譯器,但是這里我們將介紹如何優化它們。

  另外一種方法是不要把所有的實現都使用JSP頁面,而是使用一些不同的java模板引擎變量。顯然這是一個跨越很大的決定,但是事實證明至少這種方法是只得研究的。如果你想了解更多有關在Tomcat可使用的模板語言,你可以參考Jason Hunter和William Crawford合著的《Java Servlet Programming 》一書(O'Reilly公司出版)。

  在Tomcat 4.0中可以使用流行而且免費的Jikes編譯器。Jikes編譯器的速度要由于Sun的Java編譯器。首先要安裝Jikes(可訪問http://oss.software.ibm.com/pub/jikes 獲得更多的信息),接著需要在環境變量中設置JIKESPATH包含系統運行時所需的JAR文件。裝好Jikes以后還需要設置讓JSP編譯servlet使用Jikes,需要修改web.xml文件中jspCompilerPlugin的值:


<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class><init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>jspCompilerPlugin</param-name>
<param-value>
org.apache.jasper.compiler.JikesJavaCompiler
</param-value>
</init-param>
<init-param>
<!-- <param-name>
org.apache.catalina.jsp_classpath
</param-name> -->
<param-name>classpath</param-name>
<param-value>
/usr/local/jdk1.3.1-linux/jre/lib/rt.jar:
/usr/local/lib/java/servletapi/servlet.ja
r</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>


  在Tomcat 4.1(或更高版本),JSP的編譯由包含在Tomcat里面的Ant程序控制器直接執行。這聽起來有一點點奇怪,但這正是Ant有意為之的一部分,有一個API文檔指導開發者在沒有啟動一個新的JVM的情況下,使用Ant。這是使用Ant進行Java開發的一大優勢。另外,這也意味著你現在能夠在Ant 中使用任何javac支持的編譯方式,這里有一個關于Apache Ant使用手冊的javac page列表。使用起來是容易的,因為你只需要在元素中定義一個名字叫“compiler”,并且在value中有一個支持編譯的編譯器名字,示例如下:


<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>compiler</param-name>
<param-value>jikes</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>

 

Ant可用的編譯器
名稱
 別名
 調用的編譯器
 
classic
 javac1.1, javac1.2
 Standard JDK 1.1/1.2 compiler
 
modern
 javac1.3, javac1.4
 Standard JDK 1.3/1.4 compiler
 
jikes
    The Jikes compiler
 
JVC Microsoft
 Microsoft command-line compiler from the Microsoft SDK for Java/Visual J++
 
KJC    The kopi compiler
 
GCJ    The gcj compiler (included as part of gcc)
 
SJ Symantec
 Symantec's Java compiler
 
extJavac
    Runs either the modern or classic compiler in a JVM of its own
 


  由于JSP頁面在第一次使用時已經被編譯,那么你可能希望在更新新的jsp頁面后馬上對它進行編譯。實際上,這個過程完全可以自動化,因為可以確認的是新的JSP頁面在生產服務器和在測試服務器上的運行效果是一樣的。

在Tomcat4的bin目錄下有一個名為jspc的腳本。它僅僅是運行翻譯階段,而不是編譯階段,使用它可以在當前目錄生成Java源文件。它是調試JSP頁面的一種有力的手段。

  可以通過瀏覽器訪問再確認一下編譯的結果。這樣就確保了文件被轉換成serverlet,被編譯了可直接執行。這樣也準確地模仿了真實用戶訪問JSP頁面,可以看到給用戶提供的功能。也抓緊這最后一刻修改出現的bug并且修改它J

  Tomcat提供了一種通過請求來編譯JSP頁面的功能。例如,你可以在瀏覽器地址欄中輸入http://localhost:8080/examples/jsp/dates/date.jsp?jsp_precompile=true,這樣Tomcat就會編譯data.jsp而不是執行它。此舉唾手可得,不失為一種檢驗頁面正確性的捷徑。

  4. 其它

  前面我們提到過操作系統通過一些限制手段來防止惡意的服務攻擊,同樣Tomcat也提供了防止惡意攻擊或禁止某些機器訪問的設置。

  Tomcat提供了兩個參數供你配置:RemoteHostValve 和RemoteAddrValve。

  通過配置這兩個參數,可以讓你過濾來自請求的主機或IP地址,并允許或拒絕哪些主機/IP。與之類似的,在Apache的httpd文件里有對每個目錄的允許/拒絕指定。

  例如你可以把Admin Web application設置成只允許本地訪問,設置如下:


<Context path="/path/to/secret_files" ...>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"

allow="127.0.0.1" deny=""/>
</Context>


  如果沒有給出允許主機的指定,那么與拒絕主機匹配的主機就會被拒絕,除此之外的都是允許的。與之類似,如果沒有給出拒絕主機的指定,那么與允許主機匹配的主機就會被允許,除此之外的都是拒絕的。

五. 容量計劃
 容量計劃是在生產環境中使用Tomcat不得不提的提高性能的另一個重要的話題。如果你沒有對預期的網絡流量下的硬件和帶寬做考慮的話那么無論你如何做配置修改和測試都無濟于事。

  這里先對提及的容量計劃作一個簡要的定義:容量計劃是指評估硬件、操作系統和網絡帶寬,確定應用服務的服務范圍,尋求適合需求和軟件特性的軟硬件的一項活動。因此這里所說的軟件不僅包括Tomcat,也包括與Tomcat結合使用的任何第三方web服務器軟件。

  如果在購買軟硬件或部署系統前你對容量計劃一無所知,不知道現有的軟硬件環境能夠支撐多少的訪問量,甚至更糟直到你已經交付并且在生產環境上部署產品后才意識到配置有問題時再進行變更可能為時已晚。此時只能增加硬件投入,增加硬盤容量甚至購買更好的服務器。如果事先做了容量計劃那么就不會搞的如此焦頭爛額了。

  我們這里只介紹與Tomcat相關的內容。

  首先為了確定Tomcat使用機器的容量計劃,你應該從一下列表項目種著手研究和計劃:

  1. 硬件

  采用什么樣的硬件體系?需要多少臺計算機?使用一個大型的,還是使用多臺小型機?每個計算機上使用幾個CPU?使用多少內存?使用什么樣的存儲設備, I/O的處理速度有什么要求?怎樣維護這些計算機?不同的JVM在這些硬件上運行的效果如何(比如IBM AIX系統只能在其設計的硬件系統上運行)?

  2. 網絡帶寬

  帶寬的使用極限是多少?web應用程序如何處理過多的請求?

  3. 服務端操作系統

  采用哪種操作系統作為站點服務器最好?在確定的操作系統上使用哪個JVM最好?例如,JVM在這種系統上是否支持本地多線程,對稱多處理?哪種系統可使web服務器更快、更穩定,并且更便宜。是否支持多CPU?
4. Tomcat容量計劃

  以下介紹針對Tomcat做容量計劃的步驟:

  1) 量化負載。如果站點已經建立并運行,可以使用前面介紹的工具模仿用戶訪問,確定資源的需求量。

  2) 針對測試結果或測試過程中進行分析。需要知道那些請求造成了負載過重或者使用過多的資源,并與其它請求做比較,這樣就確定了系統的瓶頸所在。例如:如果servlet在查詢數據庫的步驟上耗用較長的時間,那么就需要考慮使用緩沖池來降低響應時間。

  3)確定性能最低標準。例如,你不想讓用戶花20秒來等待結果頁面的返回,也就是說甚至在達到訪問量的極限時,用戶等待的時間也不能超過20秒種(從點擊鏈接到看到返第一條返回數據)。這個時間中包含了數據庫查詢時間和文件訪問時間。同類產品性能在不同的公司可能有不同的標準,一般最好采取同行中的最低標準或對這個標準做出評估。

  4)確定如何合理使用底層資源,并逐一進行測試。底層資源包括CPU、內存、存儲器、帶寬、操作系統、JVM等等。在各種生產環境上都按順序進行部署和測試,觀察是否符合需求。在測試Tomcat時盡量多采用幾種JVM,并且調整JVM使用內存和Tomcat線程池的大小進行測試。同時為了達到資源充分合理穩定地使用的效果,還需針對測試過程中出現的硬件系統瓶頸進行處理確定合理的資源配置。這個過程最為復雜,而且一般由于沒有可參考的值所以只能靠理論推斷和經驗總結。

  5) 如果通過第4步的反復測試如果達到了最優的組合,就可以在相同的生產環境上部署產品了。

  此外應牢記一定要文檔化你的測試過程和結果,因為此后可能還會進行測試,這樣就可以拿以前的測試結果做為參考。另外測試過程要反復多次進行,每次的條件可能都不一樣,因此只有記錄下來才能進行結果比較和最佳條件的選擇。

  這樣我們通過測試找到了最好的組合方式,各種資源得到了合理的配置,系統的性能得到了極大的提升。

六. 附加資料
 很顯然本文也很難全面而詳盡地闡述性能優化過程。如果你進行更多研究的話可能會把性能調優做的更好,比如Java程序的性能調整、操作系統的調整、各種復雜環境與應用系統和其它所有與應用程序相關的東西。在這里提供一些文中提到的一些資源、文中提到的相關內容的鏈接以及本文的一些參考資料。

  1. Web性能測試資料及工具

  1) Jmeter Wiki首頁,Jmeter為一個開源的100%Java開發的性能測試工具
  
http://wiki.apache.org/jakarta-jmeter/

  2) Apache Benchmark使用說明
  
http://httpd.apache.org/docs-2.0/programs/ab.html

  3) 一些Java相關測試工具的介紹,包含可以與Tomcat集成進行測試的工具
  
http://blog.csdn.net/wyingquan/

  4) LoadRunner? 是一種預測系統行為和性能的工業標準級負載測試工具。它通過模擬數據以千萬計用戶來實施并發負載來對整個企業架構進行測試,來幫助您更快的查找和發現問題。
  
http://www.mercury.com/us/products/performance-center/loadrunner/


  2. 文中介紹的相關內容的介紹

  1) Apache 2.x + Tomcat 4.x做負載均衡,描述了如何利用jk配置集群的負載均衡。
  
http://raibledesigns.com/tomcat/index.html

  2) 容量計劃的制定,收集了許多有關制定web站點容量計劃的例子:
  
http://www.capacityplanning.com/

  3) 評測Tomcat5負載平衡與集群,
  
http://www.javaresearch.org/article/showarticle.jsp?column=556&thread=19777

  4) Apache與Tomcat的安裝與整合之整合篇
  
http://www.javaresearch.org/article/showarticle.jsp?column=23&thread=18139

  5) 性能測試工具之研究,介紹了性能測試工具的原理與思路
  
http://www.51testing.com/emagzine/No2_2.htm

  6) Java的內存泄漏
  
http://www.matrix.org.cn/resource/article/409.html

  7) Web服務器和應用程序服務器有什么區別?
  
http://www.matrix.org.cn/resource/article/1429.html

  8) 詳細講解性能中數據庫集群的問題
  
http://www.theserverside.com/articles/article.tss?l=DB_Break 



蘇醄 2007-11-23 16:27 發表評論
]]>
SQL語句調優技巧http://www.tkk7.com/sutao/articles/162375.html蘇醄蘇醄Thu, 22 Nov 2007 06:37:00 GMThttp://www.tkk7.com/sutao/articles/162375.htmlhttp://www.tkk7.com/sutao/comments/162375.htmlhttp://www.tkk7.com/sutao/articles/162375.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162375.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162375.html閱讀全文

蘇醄 2007-11-22 14:37 發表評論
]]>
內存泄漏http://www.tkk7.com/sutao/articles/162368.html蘇醄蘇醄Thu, 22 Nov 2007 06:13:00 GMThttp://www.tkk7.com/sutao/articles/162368.htmlhttp://www.tkk7.com/sutao/comments/162368.htmlhttp://www.tkk7.com/sutao/articles/162368.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162368.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162368.html【轉自IBM】Java的內存泄漏

歐陽辰,
周欣,

2002 年 10 月 21 日

Java的一個重要優點就是通過垃圾收集器(Garbage Collection,GC)自動管理內存的回收,程序員不需要通過調用函數來釋放內存。因此,很多程序員認為Java不存在內存泄漏問題,或者認為即使有內存泄漏也不是程序的責任,而是GC或JVM的問題。其實,這種想法是不正確的,因為Java也存在內存泄露,但它的表現與C++不同。

問題的提出

Java 的一個重要優點就是通過垃圾收集器(Garbage Collection,GC)自動管理內存的回收,程序員不需要通過調用函數來釋放內存。因此,很多程序員認為Java不存在內存泄漏問題,或者認為即使有內存泄漏也不是程序的責任,而是GC或JVM的問題。其實,這種想法是不正確的,因為Java也存在內存泄露,但它的表現與C++不同。

隨著越來越多的服務器程序采用Java技術,例如JSP,Servlet, EJB等,服務器程序往往長期運行。另外,在很多嵌入式系統中,內存的總量非常有限。內存泄露問題也就變得十分關鍵,即使每次運行少量泄漏,長期運行之后,系統也是面臨崩潰的危險。








Java是如何管理內存

為了判斷Java中是否有內存泄露,我們首先必須了解Java是如何管理內存的。Java的內存管理就是對象的分配和釋放問題。在Java中,程序員需要通過關鍵字new為每個對象申請內存空間 (基本類型除外),所有的對象都在堆 (Heap)中分配空間。另外,對象的釋放是由GC決定和執行的。在Java中,內存的分配是由程序完成的,而內存的釋放是有GC完成的,這種收支兩條線的方法確實簡化了程序員的工作。但同時,它也加重了JVM的工作。這也是Java程序運行速度較慢的原因之一。因為,GC為了能夠正確釋放對象,GC必須監控每一個對象的運行狀態,包括對象的申請、引用、被引用、賦值等,GC都需要進行監控。

監視對象狀態是為了更加準確地、及時地釋放對象,而釋放對象的根本原則就是該對象不再被引用。

為了更好理解GC的工作原理,我們可以將對象考慮為有向圖的頂點,將引用關系考慮為圖的有向邊,有向邊從引用者指向被引對象。另外,每個線程對象可以作為一個圖的起始頂點,例如大多程序從main進程開始執行,那么該圖就是以main進程頂點開始的一棵根樹。在這個有向圖中,根頂點可達的對象都是有效對象, GC將不回收這些對象。如果某個對象 (連通子圖)與這個根頂點不可達(注意,該圖為有向圖),那么我們認為這個(這些)對象不再被引用,可以被GC回收。

以下,我們舉一個例子說明如何用有向圖表示內存管理。對于程序的每一個時刻,我們都有一個有向圖表示JVM的內存分配情況。以下右圖,就是左邊程序運行到第6行的示意圖。


圖1

Java 使用有向圖的方式進行內存管理,可以消除引用循環的問題,例如有三個對象,相互引用,只要它們和根進程不可達的,那么GC也是可以回收它們的。這種方式的優點是管理內存的精度很高,但是效率較低。另外一種常用的內存管理技術是使用計數器,例如COM模型采用計數器方式管理構件,它與有向圖相比,精度行低 (很難處理循環引用的問題),但執行效率很高。







什么是Java中的內存泄露

下面,我們就可以描述什么是內存泄漏。在Java中,內存泄漏就是存在一些被分配的對象,這些對象有下面兩個特點,首先,這些對象是可達的,即在有向圖中,存在通路可以與其相連;其次,這些對象是無用的,即程序以后不會再使用這些對象。如果對象滿足這兩個條件,這些對象就可以判定為Java中的內存泄漏,這些對象不會被GC所回收,然而它卻占用內存。

在C++中,內存泄漏的范圍更大一些。有些對象被分配了內存空間,然后卻不可達,由于C++中沒有GC,這些內存將永遠收不回來。在Java中,這些不可達的對象都由GC負責回收,因此程序員不需要考慮這部分的內存泄露。

通過分析,我們得知,對于C++,程序員需要自己管理邊和頂點,而對于Java程序員只需要管理邊就可以了(不需要管理頂點的釋放)。通過這種方式,Java提高了編程的效率。


圖2

因此,通過以上分析,我們知道在Java中也有內存泄漏,但范圍比C++要小一些。因為Java從語言上保證,任何對象都是可達的,所有的不可達對象都由GC管理。

對于程序員來說,GC基本是透明的,不可見的。雖然,我們只有幾個函數可以訪問GC,例如運行GC的函數System.gc(),但是根據Java語言規范定義,該函數不保證JVM的垃圾收集器一定會執行。因為,不同的JVM實現者可能使用不同的算法管理GC。通常,GC的線程的優先級別較低。JVM調用GC的策略也有很多種,有的是內存使用到達一定程度時,GC才開始工作,也有定時執行的,有的是平緩執行GC,有的是中斷式執行GC。但通常來說,我們不需要關心這些。除非在一些特定的場合,GC的執行影響應用程序的性能,例如對于基于Web的實時系統,如網絡游戲等,用戶不希望GC突然中斷應用程序執行而進行垃圾回收,那么我們需要調整GC的參數,讓GC能夠通過平緩的方式釋放內存,例如將垃圾回收分解為一系列的小步驟執行,Sun提供的HotSpot JVM就支持這一特性。

下面給出了一個簡單的內存泄露的例子。在這個例子中,我們循環申請Object對象,并將所申請的對象放入一個Vector中,如果我們僅僅釋放引用本身,那么Vector仍然引用該對象,所以這個對象對GC來說是不可回收的。因此,如果對象加入到Vector后,還必須從Vector中刪除,最簡單的方法就是將Vector對象設置為null。


Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
Object o=new Object();
v.add(o);
o=null;
}

//此時,所有的Object對象都沒有被釋放,因為變量v引用這些對象。






如何檢測內存泄漏

最后一個重要的問題,就是如何檢測Java的內存泄漏。目前,我們通常使用一些工具來檢查Java程序的內存泄漏問題。市場上已有幾種專業檢查Java內存泄漏的工具,它們的基本工作原理大同小異,都是通過監測Java程序運行時,所有對象的申請、釋放等動作,將內存管理的所有信息進行統計、分析、可視化。開發人員將根據這些信息判斷程序是否有內存泄漏問題。這些工具包括Optimizeit Profiler,JProbe Profiler,JinSight , Rational 公司的Purify等。

下面,我們將簡單介紹Optimizeit的基本功能和工作原理。

Optimizeit Profiler版本4.11支持Application,Applet,Servlet和Romote Application四類應用,并且可以支持大多數類型的JVM,包括SUN JDK系列,IBM的JDK系列,和Jbuilder的JVM等。并且,該軟件是由Java編寫,因此它支持多種操作系統。Optimizeit系列還包括Thread Debugger和Code Coverage兩個工具,分別用于監測運行時的線程狀態和代碼覆蓋面。

當設置好所有的參數了,我們就可以在OptimizeIt環境下運行被測程序,在程序運行過程中,Optimizeit可以監視內存的使用曲線(如下圖),包括JVM申請的堆(heap)的大小,和實際使用的內存大小。另外,在運行過程中,我們可以隨時暫停程序的運行,甚至強行調用GC,讓GC進行內存回收。通過內存使用曲線,我們可以整體了解程序使用內存的情況。這種監測對于長期運行的應用程序非常有必要,也很容易發現內存泄露。


圖3

在運行過程中,我們還可以從不同視角觀查內存的使用情況,Optimizeit提供了四種方式:

  • 堆視角。 這是一個全面的視角,我們可以了解堆中的所有的對象信息(數量和種類),并進行統計、排序,過濾。了解相關對象的變化情況。
  • 方法視角。通過方法視角,我們可以得知每一種類的對象,都分配在哪些方法中,以及它們的數量。
  • 對象視角。給定一個對象,通過對象視角,我們可以顯示它的所有出引用和入引用對象,我們可以了解這個對象的所有引用關系。
  • 引用圖。 給定一個根,通過引用圖,我們可以顯示從該頂點出發的所有出引用。

在運行過程中,我們可以隨時觀察內存的使用情況,通過這種方式,我們可以很快找到那些長期不被釋放,并且不再使用的對象。我們通過檢查這些對象的生存周期,確認其是否為內存泄露。在實踐當中,尋找內存泄露是一件非常麻煩的事情,它需要程序員對整個程序的代碼比較清楚,并且需要豐富的調試經驗,但是這個過程對于很多關鍵的Java程序都是十分重要的。

綜上所述,Java也存在內存泄露問題,其原因主要是一些對象雖然不再被使用,但它們仍然被引用。為了解決這些問題,我們可以通過軟件工具來檢查內存泄露,檢查的主要原理就是暴露出所有堆中的對象,讓程序員尋找那些無用但仍被引用的對象。



蘇醄 2007-11-22 14:13 發表評論
]]>
Heap http://www.tkk7.com/sutao/articles/162296.html蘇醄蘇醄Thu, 22 Nov 2007 02:30:00 GMThttp://www.tkk7.com/sutao/articles/162296.htmlhttp://www.tkk7.com/sutao/comments/162296.htmlhttp://www.tkk7.com/sutao/articles/162296.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162296.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162296.html閱讀全文

蘇醄 2007-11-22 10:30 發表評論
]]>
java heap詳細介紹http://www.tkk7.com/sutao/articles/162288.html蘇醄蘇醄Thu, 22 Nov 2007 02:20:00 GMThttp://www.tkk7.com/sutao/articles/162288.htmlhttp://www.tkk7.com/sutao/comments/162288.htmlhttp://www.tkk7.com/sutao/articles/162288.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/162288.htmlhttp://www.tkk7.com/sutao/services/trackbacks/162288.html

1、

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的時候。

改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

2、

在tomcat中redeploy時出現outofmemory的錯誤.

可以有以下幾個方面的原因:

1,使用了proxool,因為proxool內部包含了一個老版本的cglib.

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

3, 老版本的cglib,快點更新到最新版。

4,更新到最新的hibernate3.2

3、

這里以tomcat環境為例,其它WEB服務器如jboss,weblogic等是同一個道理。
一、java.lang.OutOfMemoryError: PermGen space

PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域,
這塊內存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space中,
它和存放類實例(Instance)的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對
PermGen space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現PermGen space錯誤,
這種錯誤常見在web服務器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar, 其大小
超過了jvm默認的大小(4M)那么就會產生此錯誤信息了。
解決方法: 手動設置MaxPermSize大小

修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建議:將相同的第三方jar文件移置到tomcat/shared/lib目錄下,這樣可以達到減少jar 文檔重復占用內存的目的。

二、java.lang.OutOfMemoryError: Java heap space
Heap size 設置
JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,
其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可
進行設置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
提示:在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候將拋出此異常信息。
提示:Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
解決方法:手動設置Heap size
修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m   -XX:MaxNewSize=256m"

三、實例,以下給出1G內存環境下java jvm 的參數設置參考:

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


三、相關資料

/show/3/7/20061112220131.htm

/show/3/7/20061112220054.htm

/show/3/7/20061112220201.htm

題外話:經常看到網友抱怨tomcat的性能不如...,不穩定等,其實根據筆者幾年的經驗,從"互聯星空“到現在的房產門戶網,我們
均使用tomcat作為WEB服務器,每天訪問量百萬多,tomcat仍然運行良好。建議大家有問題多從自己程序入手,多看看java的DOC文檔
并詳細了解JVM的知識。這樣開發的程序才會健壯。

延伸閱讀:

JVM 性能調整的一些基本概念

apache+Tomcat負載平衡設置詳解[轉]

java - the Java application launcher

JVM調優[轉]



蘇醄 2007-11-22 10:20 發表評論
]]>
詳細講解在Hibernate中檢索策略的應用http://www.tkk7.com/sutao/articles/161879.html蘇醄蘇醄Tue, 20 Nov 2007 07:59:00 GMThttp://www.tkk7.com/sutao/articles/161879.htmlhttp://www.tkk7.com/sutao/comments/161879.htmlhttp://www.tkk7.com/sutao/articles/161879.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161879.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161879.html詳細講解在Hibernate中檢索策略的應用
 

  Hibernate的檢索策略包括類級別檢索策略和關聯級別檢索策略。

  類級別檢索策略有立即檢索和延遲檢索,默認的檢索策略是立即檢索。在Hibernate映射文件中,通過在<不著class>上配置lazy屬性來確定檢索策略。對于Session的檢索方式,類級別檢索策略僅適用于load方法;也就說,對于get、 qurey檢索,持久化對象都會被立即加載而不管lazy是false還是true.一般來說,我們檢索對象就是要訪問它,因此立即檢索是通常的選擇。由于load方法在檢索不到對象時會拋出異常(立即檢索的情況下),因此我個人并不建議使用load檢索;而由于< class>中的lazy屬性還影響到多對一及一對一的檢索策略,因此使用load方法就更沒必要了。

  關聯級別檢索策略有立即檢索、延遲檢索和迫切左外連接檢索。對于關聯級別檢索,又可分為一對多和多對多、多對一和一對一兩種情況討論。

  一對多和多對多關聯關系一般使用< set>配置。< set>有lazy和outer-join屬性,它們的不同取值絕對了檢索策略。

  1)立即檢索:這是一對多默認的檢索策略,此時lazy=false,outer-join=false.盡管這是默認的檢索策略,但如果關聯的集合是無用的,那么就不要使用這種檢索方式。

  2)延遲檢索:此時lazy=true,outer-join=false(outer-join=true是無意義的),這是優先考慮的檢索方式。

  3)迫切左外連接檢索:此時 lazy=false,outer-join=true,這種檢索策略只適用于依靠id檢索方式(load、get),而不適用于query的集合檢索(它會采用立即檢索策略)。相比于立即檢索,這種檢索策略減少了一條sql語句,但在Hibernate中,只能有一個配置成 outer-join=true.

  多對一和一對一檢索策略一般使用< many-to-one>、< one-to-one>配置。< many-to-one>中需要配置的屬性是 outer-join,同時還需要配置one端關聯的< class>的lazy屬性(配置的可不是< many-to-one>中的lazy哦),它們的組合后的檢索策略如下:

  1) outer-join=auto:這是默認值,如果lazy=true為延遲檢索,如果lazy=false為迫切左外連接檢索。

  2) outer-join=true,無關于lazy,都為迫切左外連接檢索。

  3) outer-join=false,如果lazy=true為延遲檢索,否則為立即檢索。

  可以看到,在默認的情況下(outer-join=auto,lazy=false),對關聯的one端對象Hibernate采用的迫切左外連接檢索。依我看,很多情況下,我們并不需要加載one端關聯的對象(很可能我們需要的僅僅是關聯對象的id);另外,如果關聯對象也采用了迫切左外連接檢索,就會出現select語句中有多個外連接表,如果個數多的話會影響檢索性能,這也是為什么Hibernate通過 hibernate.max_fetch_depth屬性來控制外連接的深度。對于迫切左外連接檢索,query的集合檢索并不適用,它會采用立即檢索策略。

  對于檢索策略,需要根據實際情況進行選擇。對于立即檢索和延遲檢索,它們的優點在于select語句簡單(每張表一條語句)、查詢速度快,缺點在于關聯表時需要多條select語句,增加了訪問數據庫的頻率。因此在選擇即檢索和延遲檢索時,可以考慮使用批量檢索策略來減少select語句的數量(配置batch-size屬性)。對于切左外連接檢索,優點在于select較少,但缺點是select語句的復雜度提高,多表之間的關聯會是很耗時的操作。另外,配置文件是死的,但程序是活的,可以根據需要在程序里顯示的指定檢索策略(可能經常需要在程序中顯示指定迫切左外連接檢索)。為了清楚檢索策略的配置效果如何,可以配置show_sql屬性查看程序運行時Hibernate執行的sql語句。



蘇醄 2007-11-20 15:59 發表評論
]]>
詳細講解在Hibernate中檢索策略的應用http://www.tkk7.com/sutao/articles/161878.html蘇醄蘇醄Tue, 20 Nov 2007 07:59:00 GMThttp://www.tkk7.com/sutao/articles/161878.htmlhttp://www.tkk7.com/sutao/comments/161878.htmlhttp://www.tkk7.com/sutao/articles/161878.html#Feedback0http://www.tkk7.com/sutao/comments/commentRss/161878.htmlhttp://www.tkk7.com/sutao/services/trackbacks/161878.html詳細講解在Hibernate中檢索策略的應用
 

  Hibernate的檢索策略包括類級別檢索策略和關聯級別檢索策略。

  類級別檢索策略有立即檢索和延遲檢索,默認的檢索策略是立即檢索。在Hibernate映射文件中,通過在<不著class>上配置lazy屬性來確定檢索策略。對于Session的檢索方式,類級別檢索策略僅適用于load方法;也就說,對于get、 qurey檢索,持久化對象都會被立即加載而不管lazy是false還是true.一般來說,我們檢索對象就是要訪問它,因此立即檢索是通常的選擇。由于load方法在檢索不到對象時會拋出異常(立即檢索的情況下),因此我個人并不建議使用load檢索;而由于< class>中的lazy屬性還影響到多對一及一對一的檢索策略,因此使用load方法就更沒必要了。

  關聯級別檢索策略有立即檢索、延遲檢索和迫切左外連接檢索。對于關聯級別檢索,又可分為一對多和多對多、多對一和一對一兩種情況討論。

  一對多和多對多關聯關系一般使用< set>配置。< set>有lazy和outer-join屬性,它們的不同取值絕對了檢索策略。

  1)立即檢索:這是一對多默認的檢索策略,此時lazy=false,outer-join=false.盡管這是默認的檢索策略,但如果關聯的集合是無用的,那么就不要使用這種檢索方式。

  2)延遲檢索:此時lazy=true,outer-join=false(outer-join=true是無意義的),這是優先考慮的檢索方式。

  3)迫切左外連接檢索:此時 lazy=false,outer-join=true,這種檢索策略只適用于依靠id檢索方式(load、get),而不適用于query的集合檢索(它會采用立即檢索策略)。相比于立即檢索,這種檢索策略減少了一條sql語句,但在Hibernate中,只能有一個配置成 outer-join=true.

  多對一和一對一檢索策略一般使用< many-to-one>、< one-to-one>配置。< many-to-one>中需要配置的屬性是 outer-join,同時還需要配置one端關聯的< class>的lazy屬性(配置的可不是< many-to-one>中的lazy哦),它們的組合后的檢索策略如下:

  1) outer-join=auto:這是默認值,如果lazy=true為延遲檢索,如果lazy=false為迫切左外連接檢索。

  2) outer-join=true,無關于lazy,都為迫切左外連接檢索。

  3) outer-join=false,如果lazy=true為延遲檢索,否則為立即檢索。

  可以看到,在默認的情況下(outer-join=auto,lazy=false),對關聯的one端對象Hibernate采用的迫切左外連接檢索。依我看,很多情況下,我們并不需要加載one端關聯的對象(很可能我們需要的僅僅是關聯對象的id);另外,如果關聯對象也采用了迫切左外連接檢索,就會出現select語句中有多個外連接表,如果個數多的話會影響檢索性能,這也是為什么Hibernate通過 hibernate.max_fetch_depth屬性來控制外連接的深度。對于迫切左外連接檢索,query的集合檢索并不適用,它會采用立即檢索策略。

  對于檢索策略,需要根據實際情況進行選擇。對于立即檢索和延遲檢索,它們的優點在于select語句簡單(每張表一條語句)、查詢速度快,缺點在于關聯表時需要多條select語句,增加了訪問數據庫的頻率。因此在選擇即檢索和延遲檢索時,可以考慮使用批量檢索策略來減少select語句的數量(配置batch-size屬性)。對于切左外連接檢索,優點在于select較少,但缺點是select語句的復雜度提高,多表之間的關聯會是很耗時的操作。另外,配置文件是死的,但程序是活的,可以根據需要在程序里顯示的指定檢索策略(可能經常需要在程序中顯示指定迫切左外連接檢索)。為了清楚檢索策略的配置效果如何,可以配置show_sql屬性查看程序運行時Hibernate執行的sql語句。



蘇醄 2007-11-20 15:59 發表評論
]]>
主站蜘蛛池模板: 国产一卡2卡3卡4卡无卡免费视频 国产一卡二卡3卡四卡免费 | 日本久久久免费高清| 久久久久亚洲精品影视| 西西人体免费视频| 亚洲黄片毛片在线观看| 色婷婷精品免费视频| 亚洲 无码 在线 专区| 免费无码午夜福利片 | 亚洲视频免费在线观看| 亚洲成人免费电影| 亚洲精品综合久久中文字幕 | 特级一级毛片免费看| 亚洲AV中文无码乱人伦| 未满十八私人高清免费影院| 亚洲国产成人精品久久久国产成人一区二区三区综 | 国产免费小视频在线观看| 粉色视频在线观看www免费| 免费人成在线观看视频播放| 日韩电影免费在线观看网址 | 亚洲精品mv在线观看 | 亚洲国产成人VA在线观看| 国产视频精品免费视频| 久久国产亚洲精品麻豆| 蜜臀98精品国产免费观看| 亚洲精品国产首次亮相| 亚洲欧洲中文日韩av乱码| 日本亚洲欧洲免费天堂午夜看片女人员 | 特级做a爰片毛片免费看| 国产V亚洲V天堂无码| 精品香蕉在线观看免费| 亚洲妇女无套内射精| 久久亚洲国产成人影院网站| 99视频免费播放| 亚洲熟妇成人精品一区| 久久久久亚洲AV无码专区桃色| 久久国产免费一区二区三区| 香蕉大伊亚洲人在线观看| 亚洲成人影院在线观看| 1000部国产成人免费视频| 亚洲AV无码一区二区三区网址| 国产亚洲精品自在线观看|