明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

WebLogic Server 性能調(diào)優(yōu)

[摘要]任何在市場(chǎng)上成功的產(chǎn)品都擁有良好的性能。雖然成為象WebLogic Server這樣廣泛使用的產(chǎn)品需要具備很多特性,但性能絕對(duì)是必不可少的。 良好的編程習(xí)慣在幫助應(yīng)用運(yùn)行方面起了很大的作用,但是僅有它們還是不夠的。應(yīng)用服務(wù)器必須能夠在多種硬件和操作系統(tǒng)之間移植,必須具備通用性以便處理范圍更廣的應(yīng)用...
任何在市場(chǎng)上成功的產(chǎn)品都擁有良好的性能。雖然成為象WebLogic Server這樣廣泛使用的產(chǎn)品需要具備很多特性,但性能絕對(duì)是必不可少的。
良好的編程習(xí)慣在幫助應(yīng)用運(yùn)行方面起了很大的作用,但是僅有它們還是不夠的。應(yīng)用服務(wù)器必須能夠在多種硬件和操作系統(tǒng)之間移植,必須具備通用性以便處理范圍更廣的應(yīng)用類型。這就是為什么應(yīng)用服務(wù)器都提供了豐富的調(diào)試“按鈕”的原因,通過調(diào)整這些“按鈕”,能夠使服務(wù)器更適合運(yùn)行環(huán)境以及應(yīng)用程序。

本文針對(duì)WebLogic討論了其中的某些調(diào)試參數(shù),不過并未將所有可調(diào)整的屬性全部列出。此外,在將此處推薦的方法運(yùn)用到產(chǎn)品環(huán)境之前,建議您先在測(cè)試環(huán)境中對(duì)它們測(cè)試一番。

性能監(jiān)控及瓶頸發(fā)現(xiàn)

性能調(diào)試的第一步是孤立“危險(xiǎn)區(qū)域”。性能瓶頸可以存在于整個(gè)系統(tǒng)的任一部分――網(wǎng)絡(luò)、數(shù)據(jù)庫、客戶端或應(yīng)用服務(wù)器。重要的是首先確定哪個(gè)系統(tǒng)組件引起了性能問題,調(diào)試錯(cuò)了組件可能會(huì)使情況更糟。

WebLogic Server為系統(tǒng)管理員提供了管理控制臺(tái)和命令行工具兩種方式監(jiān)控系統(tǒng)性能。服務(wù)器端有叫作mbean的集合,用于搜集諸如線程消耗情況、資源剩余情況、緩存使用情況等信息?刂婆_(tái)和命令行管理器都可以從服務(wù)器將這些信息調(diào)用出來。圖1的屏幕快照就顯示了EJB容器中緩存的使用和剩余情況,這是控制臺(tái)提供的性能監(jiān)控的選項(xiàng)之一。

代碼分析器也是應(yīng)用代碼用以探測(cè)自身性能瓶頸的另一種有效的工具。有幾個(gè)很好的代碼分析器,如:Wily Introscope, Jprobe, Optimizelt。

EJB 容器

EJB容器中最昂貴的操作當(dāng)然是數(shù)據(jù)庫調(diào)用――裝載和存儲(chǔ)實(shí)體bean。容器也因此提供了各種各樣的參數(shù)以便減少數(shù)據(jù)庫的訪問次數(shù)。但不管怎樣,除非是在特殊情況下,否則在每個(gè)bean的每次交易中,至少都得有一次裝載操作和一次存儲(chǔ)操作。這些特殊情況是:
1. Bean是只讀的。此時(shí),bean只需在第一次訪問時(shí)裝載一次,從來不需要存儲(chǔ)操作。當(dāng)然,如果超出參數(shù)read-timeout-seconds的設(shè)置,bean將被再次裝載。

2. Bean 有專門的或積極的并發(fā)策略,且參數(shù)db-is-shared 設(shè)置為假。此參數(shù)在WebLogic Server 7.0中被重新命名為cache-between-transactions。參數(shù)db-is-shared 設(shè)置為假相當(dāng)于參數(shù)cache-between-transactions設(shè)置為真。

3. Bean在交易中未被修改過,此時(shí),容器會(huì)將存儲(chǔ)操作優(yōu)化掉。

如果不屬于上述任何一種情況,則code path中的每個(gè)實(shí)體bean在每次交易時(shí),至少會(huì)被裝載和存儲(chǔ)一次。有些特征能夠減少數(shù)據(jù)庫的調(diào)用或者降低數(shù)據(jù)庫調(diào)用的開銷,如:高速緩存技術(shù)、域(field)分組、并發(fā)策略以及緊密關(guān)聯(lián)緩存(eager relationship caching)等,其中的某些特征是WebLogic Server 7.0新增的。




高速緩存:實(shí)體bean緩存空間的大小由weblogic-ejb-jar.xml中的參數(shù)max-beans-in-cache定義。容器在交易中第一次裝載bean時(shí)是從數(shù)據(jù)庫調(diào)用的,此時(shí)bean也被放在緩存中。如果緩存的空間太小,有些bean就被滯留在數(shù)據(jù)庫中。這樣,如果不考慮前面提到的前兩種特殊情況的話,這些bean在下次調(diào)用時(shí)就必須重新從數(shù)據(jù)庫裝載。從緩存調(diào)用bean也意味著此時(shí)不必調(diào)用setEntityContext()。如果bean的關(guān)鍵(主)鍵是組合域或者比較復(fù)雜,也能省卻設(shè)置它們的時(shí)間。

域分組:域分組是對(duì)于查找方法指定從數(shù)據(jù)庫加載的域。如果實(shí)體bean與一個(gè)較大的BLOB域(比方說,一幅圖像)相聯(lián)系,且很少被訪問,則可以定義一個(gè)將此域排除在外的域組,該域組與一個(gè)查找方法相關(guān)聯(lián),這樣查找時(shí),BLOB域即不會(huì)被裝載。這種特征只對(duì)EJB2.0的bean 適用。

并發(fā)策略:在WebLogic Server 7.0中,容器提供了四種并發(fā)控制機(jī)制。它們是獨(dú)占式、數(shù)據(jù)庫式、積極式和只讀式。并發(fā)策略與交易進(jìn)行時(shí)的隔離級(jí)別緊密相關(guān)。并發(fā)控制并不是真正意義上的提高性能的措施,它的主要目的是確保實(shí)體bean所表示的數(shù)據(jù)的一致性,該一致性由bean的部署器所強(qiáng)制要求。無論如何,某些控制機(jī)制使得容器處理請(qǐng)求的速度比其它的要快一些,但這種快速是以犧牲數(shù)據(jù)的一致性為代價(jià)的。
最嚴(yán)格的并發(fā)策略是獨(dú)占式,利用特殊主鍵對(duì)bean的訪問是經(jīng)過系列化的,因此每次只能有一個(gè)交易對(duì)bean進(jìn)行訪問。這雖然在容器內(nèi)提供了很好的并發(fā)控制,但性能受到限制。在交易之間允許互為緩存的時(shí)候,這種方法很有用,但在集群環(huán)境中不能使用,此時(shí),裝載操作被優(yōu)化掉,因此可能導(dǎo)致喪失并行性。

數(shù)據(jù)庫式的并發(fā)策略不同于數(shù)據(jù)庫的并發(fā)控制。實(shí)體bean在容器中并未被鎖定,允許多個(gè)交易對(duì)相同的實(shí)體bean并發(fā)操作,因此能夠提高性能。當(dāng)然,這樣對(duì)隔離的級(jí)別也許要求較高,以便確保數(shù)據(jù)的一致性。

積極式并發(fā)策略與數(shù)據(jù)庫的并發(fā)控制也不同。不同之處在于對(duì)數(shù)據(jù)一致性的檢查發(fā)生在對(duì)已設(shè)定的更新操作進(jìn)行存儲(chǔ)時(shí)而非在裝載時(shí)將整行鎖定。如果應(yīng)用內(nèi)對(duì)同一個(gè)bean訪問的沖突不是很激烈的情況下,本策略比數(shù)據(jù)庫式的策略要快一些,雖然兩個(gè)提供了相同的數(shù)據(jù)一致性保護(hù)級(jí)別。但是在有沖突發(fā)生的時(shí)候,本策略要求調(diào)用者要重新發(fā)起調(diào)用。 本特征也只對(duì)EJB 2.0 適用。

只讀式策略只能用于只讀bean。Bean只在應(yīng)用第一次訪問時(shí)或者超出參數(shù)read-timeout-seconds所指定的值時(shí)才被裝載。Bean從來不需要被存儲(chǔ)。當(dāng)基本數(shù)據(jù)改變時(shí),也會(huì)通過read-mostly格式通知bean,從而引起重新裝載。


緊密關(guān)聯(lián)緩存: 如果兩個(gè)實(shí)體bean, bean A 和bean B 在CMR(容器關(guān)系管理)內(nèi)關(guān)聯(lián),兩個(gè)在同一個(gè)交易中被訪問,且由同樣的數(shù)據(jù)庫調(diào)用裝載,我們稱為緊密關(guān)聯(lián)緩存。這是WebLogic Server 7.0的新特征,同樣只適用于EJB2.0。

除了上面列出的通過優(yōu)化容器內(nèi)對(duì)數(shù)據(jù)庫的訪問從而達(dá)到性能增加的特征外,另有一些在容器之外,針對(duì)會(huì)話bean和實(shí)體bean的參數(shù)能夠幫助提升性能。

緩沖池和高速緩存是EJB容器為提高會(huì)話bean和實(shí)體bean性能所提供的主要特征。然而,這些方法并非對(duì)所有類型的bean適用。它們的消極面是對(duì)內(nèi)存要求較高,雖然這不是主要的問題。緩沖池適用于無狀態(tài)會(huì)話bean(SLSB),消息驅(qū)動(dòng)bean(MDB)以及實(shí)體bean。一旦為SLSB和MDB設(shè)定了緩沖池的大小,這些bean的許多實(shí)例就會(huì)被創(chuàng)建并被放到緩沖池中,setSessionContext()/setMessageDriveContext()方法會(huì)被調(diào)用。為這些bean設(shè)置的緩沖池的大小不必超過所配置的執(zhí)行線程數(shù)(事實(shí)上,要求比此數(shù)要。。如果方法setSessionContext()要做任何開銷昂貴的操作的話,此時(shí)JNDI查詢已經(jīng)完成,使用緩沖池中的實(shí)例方法調(diào)用將會(huì)加快速度。對(duì)實(shí)體bean來說,在完成setEntityContext()方法調(diào)用之后,緩沖池與bean的匿名實(shí)例相連(沒有主鍵)。這些實(shí)例可以被查詢操作所使用,查詢方法從緩沖池中取出一個(gè)實(shí)例,為其指定一個(gè)主鍵,然后從數(shù)據(jù)庫中裝載相應(yīng)的bean。

高速緩存適用于有狀態(tài)會(huì)話bean(SFSB)和實(shí)體bean。實(shí)體bean已經(jīng)在前面討論過。對(duì)于SFSB,緩存能夠避免向硬盤串行化的操作。串行化到硬盤的操作非常昂貴,絕對(duì)應(yīng)該避免。用于SFSB的緩存大小可以比連接到服務(wù)器的并發(fā)客戶端數(shù)略微大些,這是由于僅當(dāng)緩存被占用了85%以后,容器才會(huì)設(shè)法將bean滯留在數(shù)據(jù)庫中待命。如果緩存大于實(shí)際所需,則容器不會(huì)通過緩存花費(fèi)時(shí)間將bean待命。

EJB容器提供了兩種方法進(jìn)行bean-to-bean 和 Web-tier-to-bean的調(diào)用操作:傳值調(diào)用和傳送地址調(diào)用。如果bean處在同一個(gè)應(yīng)用之中,則缺省情況下,用的是傳送地址的方法,這比傳值要快一些。傳送地址的方法一般不應(yīng)被禁止,除非有充足的理由要強(qiáng)制這樣做。強(qiáng)制使用傳送地址的另一種做法是使用本地接口。在WebLogic Server 7.0中引入了另一個(gè)特征是對(duì)有狀態(tài)服務(wù)使用激活(activation)。雖然這種做法在某種程度上影響了性能,但由于對(duì)內(nèi)存要求較低,因此極大地改進(jìn)了擴(kuò)展性。如果擴(kuò)展性不值得關(guān)注,可以將參數(shù)noObjectAction傳送給ejbc從而關(guān)閉激活(activation)。

JDBC

對(duì)數(shù)據(jù)庫的訪問來說,調(diào)試JDBC與調(diào)試EJB容器同樣重要。比方說設(shè)置連接池的大小――連接池應(yīng)大到足以容納所有線程對(duì)連接的要求。如果所有對(duì)數(shù)據(jù)庫的訪問能夠在缺省的執(zhí)行隊(duì)列中得以實(shí)現(xiàn),則連接數(shù)應(yīng)為執(zhí)行隊(duì)列中的線程數(shù),比讀取socket的線程(缺省執(zhí)行隊(duì)列中用來讀取進(jìn)入請(qǐng)求的線程)數(shù)要少。為了避免在運(yùn)行期間對(duì)連接進(jìn)行創(chuàng)建和刪除,可在初始時(shí)即將連接池設(shè)置為其最大容量。如果可能的話,應(yīng)確保參數(shù)TestConnectionsOnReserve被設(shè)置為假(false,這是缺省設(shè)置)。如果此參數(shù)設(shè)置為真(true),則在連接被分配給調(diào)用者之前,都要經(jīng)過測(cè)試,這會(huì)額外要求與數(shù)據(jù)庫的反復(fù)連接。

另一個(gè)重要的參數(shù)是PreparedStatementCacheSize。每個(gè)連接都為宏語句設(shè)一個(gè)靜態(tài)的緩存,大小由JDBC連接池配置時(shí)指定。緩存是靜態(tài)的,時(shí)刻牢記這一點(diǎn)非常重要。這意味著如果緩存的大小是n的話,則只有放在緩存中的前n條語句得到執(zhí)行。確保昂貴的SQL語句享受到緩存的方法是用一個(gè)啟動(dòng)類將這些語句存放到緩存中。盡管緩存技術(shù)從很大程度上改進(jìn)了性能,但也不能盲目使用它。如果數(shù)據(jù)庫的格式有了變化,那么在不重新啟動(dòng)服務(wù)器的情況下,無法使緩存中的語句失效或者是用新的進(jìn)行替換。當(dāng)然,緩存中的語句會(huì)使數(shù)據(jù)庫中的光標(biāo)得以保留。

對(duì)于WebLogic Server 7.0來說,由于jDriver性能的改進(jìn)已使其速度遠(yuǎn)遠(yuǎn)快于Oracle的廋驅(qū)動(dòng)程序,尤其對(duì)于要完成大量SELECT操作的應(yīng)用來說就更是如此。這可以從HP提交的利用WebLogic Server 7.0 Beta版的兩份Ecperf結(jié)果得到證明(http://ecperf.theserverside.com/ecperf/index.jsp?page=results/top_ten_price_performance)。

JMS

JMS子系統(tǒng)提供了很多的調(diào)試參數(shù)。JMS消息是由稱為JMSDispatcher的獨(dú)立執(zhí)行隊(duì)列處理的。因此,JMS子系統(tǒng)既不會(huì)由于運(yùn)行在缺省或者其它執(zhí)行隊(duì)列中的應(yīng)用因爭(zhēng)奪資源而導(dǎo)致“營養(yǎng)匱乏”,反過來也不會(huì)搶奪其它應(yīng)用的資源。對(duì)JMS來說,大多數(shù)的調(diào)試參數(shù)都是在服務(wù)的質(zhì)量上進(jìn)行折衷處理。如,利用文件式持續(xù)性目的地(file-persistent destnation)禁止同步寫操作(通過設(shè)置特性: -Dweblogic.JMSFileStore.SynchronousWritesEnabled =false)以后會(huì)引起性能急劇提高,但同時(shí)也會(huì)冒著丟失消息或者重復(fù)接收消息的風(fēng)險(xiǎn)。類似地,利用多點(diǎn)傳送發(fā)送消息會(huì)提升性能,同時(shí)也會(huì)有消息半途丟失的危險(xiǎn)。

消息確認(rèn)間隔不應(yīng)設(shè)置得過短――發(fā)送確認(rèn)的比率越大,處理消息的速度可能會(huì)越慢。同時(shí),如果設(shè)置得過大,則意味著系統(tǒng)發(fā)生故障時(shí),消息會(huì)丟失或者被重復(fù)發(fā)送。

一般說來,應(yīng)在單個(gè)服務(wù)器上對(duì)多個(gè)JMS目的地進(jìn)行配置,而不是將它們分散在多個(gè)JMS服務(wù)器,除非不再需要擴(kuò)展。

關(guān)閉消息頁面調(diào)度(paging)可能會(huì)提高性能,但會(huì)影響可擴(kuò)展性。如果打開消息頁面調(diào)度(paging),則需要額外的I/O操作以便將消息串行化到硬盤,在必要的時(shí)候再讀進(jìn)來,但同時(shí)也降低了對(duì)內(nèi)存的要求。

一般來說,異步過程比同步過程更好操作,更易于調(diào)節(jié)。

Web容器

Web層在應(yīng)用中更多的是用來生成表達(dá)邏輯。廣泛使用的體系結(jié)構(gòu)是從應(yīng)用層讀取數(shù)據(jù),然后使用servlet和JSP生成動(dòng)態(tài)內(nèi)容,其中應(yīng)用層一般由EJB組成。在這種結(jié)構(gòu)中,servlet 和JSP保留對(duì)EJB的引用,以防它們與數(shù)據(jù)庫或數(shù)據(jù)源直接對(duì)話。將這些引用保存起來是個(gè)不錯(cuò)的主意。如果JSP和servlet沒有和EJB部署在同一臺(tái)應(yīng)用服務(wù)器上,則利用JNDI進(jìn)行查詢的費(fèi)用是很昂貴的。

JSP緩存標(biāo)記符可以用于存儲(chǔ)JSP頁面內(nèi)的數(shù)據(jù)。這些標(biāo)記符都支持對(duì)緩存的輸入和輸出。對(duì)緩存的輸出涉及到標(biāo)記符內(nèi)的代碼所生成的內(nèi)容,對(duì)緩存的輸入涉及到標(biāo)記符內(nèi)的代碼對(duì)變量的賦值。如果不希望Web層頻繁變化,則可以通過將ServletReloadCheckSecs 設(shè)置為-1,從而關(guān)閉自動(dòng)裝載(auto-reloading)功能。使用這種方法以后,服務(wù)器將不再輪詢Web層是否有變化,如果JSP和servlet的數(shù)量很多,則效果是非常明顯的。

這里也建議不要在HTTP會(huì)話中儲(chǔ)存過多的信息。如果信息是必須的,可以考慮使用有狀態(tài)會(huì)話bean來替代。

JVM調(diào)試

如今的大多數(shù)JVM具有自主調(diào)節(jié)功能,因?yàn)樗鼈兡軌蛱綔y(cè)到代碼中的危險(xiǎn)區(qū)域并對(duì)它們進(jìn)行優(yōu)化。開發(fā)和部署人員能夠考慮的調(diào)試參數(shù)大概就是堆設(shè)置了。設(shè)置這些并沒有一般的規(guī)則。JVM一般堆空間,按新空間或保留空間一般設(shè)置為整個(gè)堆空間的三分之一或一半組織。整個(gè)堆空間不能指定得過大以致于無法支持并發(fā)的內(nèi)存垃圾回收(GC)處理。在這種設(shè)置環(huán)境中,如果堆太大的話,垃圾回收的間隔應(yīng)設(shè)為一分鐘或更長。最后,需要引起注意的是這些設(shè)置在很大程度上依賴于部署在服務(wù)器上的應(yīng)用使用內(nèi)存的模式。有關(guān)調(diào)試JVM的其它信息可以參考:

http://edocs.bea.com/wls/docs70/perform/JVMTuning.html1104200。

服務(wù)器調(diào)試

除了由各個(gè)子系統(tǒng)提供的調(diào)試參數(shù)以外,還有適用于服務(wù)器的參數(shù)能夠幫助提升性能。其中最重要的是配置線程數(shù)和執(zhí)行隊(duì)列數(shù)。增加線程數(shù)并非總能奏效,僅當(dāng)下列情況成立時(shí)再考慮使用這種方法:預(yù)定的吞吐量沒有達(dá)到;等待隊(duì)列(未開始處理的請(qǐng)求)過長;CPU仍有剩余。當(dāng)然,這樣做并不一定能改善性能。CPU使用率低可能是由于對(duì)服務(wù)器的其它資源競(jìng)爭(zhēng)所致,如,沒有足夠的JDBC連接。當(dāng)改變線程數(shù)時(shí)應(yīng)考慮到這些類似的因素。

在WebLogic Server 7.0中,提供了配置多個(gè)執(zhí)行隊(duì)列的功能,并且能夠在部署中定義處理特殊的EJB或JSP/servlet請(qǐng)求的執(zhí)行隊(duì)列。要做到這些,只要在運(yùn)行weblogic.ejbc時(shí)將標(biāo)志 -dispatchPolicy <隊(duì)列名稱> 傳送給bean 即可。對(duì)于JSP/servlet,可將設(shè)置Web應(yīng)用的weblogic部署描述符中初始化參數(shù)(init-param) wl-dispatch-policy的值設(shè)為執(zhí)行隊(duì)列的名字即可。有時(shí)應(yīng)用中的某些bean/JSP對(duì)操作的響應(yīng)時(shí)間比其它的要長,此時(shí),可以對(duì)這些bean/JSP設(shè)置單獨(dú)的執(zhí)行隊(duì)列。至于隊(duì)列的大小,要達(dá)到最好的性能,還取決于經(jīng)驗(yàn)。

另一個(gè)比較大的問題是決定在何種情況下應(yīng)該使用WebLogic性能包(http://e-docs.bea.com/wls/docs70/perform/WLSTuning.html - 1112119)。如果socket數(shù)不太多(每個(gè)服務(wù)器上都有一個(gè)socket用于客戶端JVM的遠(yuǎn)程方法調(diào)用連接),而且總是忙于讀取從客戶端發(fā)送過來的請(qǐng)求數(shù)據(jù),那么此時(shí)使用性能包恐怕不會(huì)有明顯的改進(jìn)。也有可能不用性能包會(huì)導(dǎo)致相似或更好的結(jié)果,這取決于JVM在處理網(wǎng)絡(luò)I/O時(shí)的具體實(shí)現(xiàn)。

Socket讀取線程取自缺省執(zhí)行隊(duì)列。在Windows 環(huán)境下,每個(gè)CPU有兩個(gè)socket讀取線程,在solaris環(huán)境下,共有三個(gè)socket用于本地輸入輸出(native I/O)。對(duì)于Java 輸入輸出(I/O),讀取線程數(shù)由配置文件config.xml中的參數(shù)PercentSocketReaderThreads 進(jìn)行設(shè)置。它的缺省值是33%, 上限是50%,這是顯而易見的,因?yàn)槿绻麤]有線程用于處理請(qǐng)求,則同樣不會(huì)有更多的讀取線程啦。對(duì)于Java I/O,應(yīng)使讀取線程數(shù)盡量接近客戶端連接數(shù),因?yàn)樵诘却?qǐng)求時(shí),Java I/O會(huì)阻塞。這也是為什么當(dāng)客戶端的連接數(shù)增加時(shí),線程數(shù)不能一直同等增加的原因。

結(jié)論

我們上面只討論了調(diào)試服務(wù)器的部分方法。需要記住的是,一個(gè)設(shè)計(jì)蹩腳,編寫欠佳的應(yīng)用,通常都不會(huì)有好的性能表現(xiàn),無論對(duì)服務(wù)器及其參數(shù)如何調(diào)試。貫穿應(yīng)用開發(fā)周期的各個(gè)階段――從設(shè)計(jì)到部署,性能始終應(yīng)該是考慮的關(guān)鍵因素。經(jīng)常發(fā)生的情況是性能被放在了功能之后,等到發(fā)現(xiàn)了問題再去修改,已經(jīng)很困難了。有關(guān)WebLogic Server 性能調(diào)試的其它信息可以參考:http://e-docs.bea.com/wls/docs70/perform/index.html。