WebLogic Server 性能調(diào)優(yōu)
發(fā)表時間:2024-06-17 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]任何在市場上成功的產(chǎn)品都擁有良好的性能。雖然成為象WebLogic Server這樣廣泛使用的產(chǎn)品需要具備很多特性,但性能絕對是必不可少的。 良好的編程習(xí)慣在幫助應(yīng)用運(yùn)行方面起了很大的作用,但是僅有它們還是不夠的。應(yīng)用服務(wù)器必須能夠在多種硬件和操作系統(tǒng)之間移植,必須具備通用性以便處理范圍更廣的應(yīng)用...
任何在市場上成功的產(chǎn)品都擁有良好的性能。雖然成為象WebLogic Server這樣廣泛使用的產(chǎn)品需要具備很多特性,但性能絕對是必不可少的。
良好的編程習(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)用程序。
本文針對WebLogic討論了其中的某些調(diào)試參數(shù),不過并未將所有可調(diào)整的屬性全部列出。此外,在將此處推薦的方法運(yùn)用到產(chǎn)品環(huán)境之前,建議您先在測試環(huán)境中對它們測試一番。
性能監(jiān)控及瓶頸發(fā)現(xiàn)
性能調(diào)試的第一步是孤立“危險區(qū)域”。性能瓶頸可以存在于整個系統(tǒng)的任一部分――網(wǎng)絡(luò)、數(shù)據(jù)庫、客戶端或應(yīng)用服務(wù)器。重要的是首先確定哪個系統(tǒng)組件引起了性能問題,調(diào)試錯了組件可能會使情況更糟。
WebLogic Server為系統(tǒng)管理員提供了管理控制臺和命令行工具兩種方式監(jiān)控系統(tǒng)性能。服務(wù)器端有叫作mbean的集合,用于搜集諸如線程消耗情況、資源剩余情況、緩存使用情況等信息?刂婆_和命令行管理器都可以從服務(wù)器將這些信息調(diào)用出來。圖1的屏幕快照就顯示了EJB容器中緩存的使用和剩余情況,這是控制臺提供的性能監(jiān)控的選項(xiàng)之一。
代碼分析器也是應(yīng)用代碼用以探測自身性能瓶頸的另一種有效的工具。有幾個很好的代碼分析器,如:Wily Introscope, Jprobe, Optimizelt。
EJB 容器
EJB容器中最昂貴的操作當(dāng)然是數(shù)據(jù)庫調(diào)用――裝載和存儲實(shí)體bean。容器也因此提供了各種各樣的參數(shù)以便減少數(shù)據(jù)庫的訪問次數(shù)。但不管怎樣,除非是在特殊情況下,否則在每個bean的每次交易中,至少都得有一次裝載操作和一次存儲操作。這些特殊情況是:
1. Bean是只讀的。此時,bean只需在第一次訪問時裝載一次,從來不需要存儲操作。當(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在交易中未被修改過,此時,容器會將存儲操作優(yōu)化掉。
如果不屬于上述任何一種情況,則code path中的每個實(shí)體bean在每次交易時,至少會被裝載和存儲一次。有些特征能夠減少數(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ù)據(jù)庫調(diào)用的,此時bean也被放在緩存中。如果緩存的空間太小,有些bean就被滯留在數(shù)據(jù)庫中。這樣,如果不考慮前面提到的前兩種特殊情況的話,這些bean在下次調(diào)用時就必須重新從數(shù)據(jù)庫裝載。從緩存調(diào)用bean也意味著此時不必調(diào)用setEntityContext()。如果bean的關(guān)鍵(主)鍵是組合域或者比較復(fù)雜,也能省卻設(shè)置它們的時間。
域分組:域分組是對于查找方法指定從數(shù)據(jù)庫加載的域。如果實(shí)體bean與一個較大的BLOB域(比方說,一幅圖像)相聯(lián)系,且很少被訪問,則可以定義一個將此域排除在外的域組,該域組與一個查找方法相關(guān)聯(lián),這樣查找時,BLOB域即不會被裝載。這種特征只對EJB2.0的bean 適用。
并發(fā)策略:在WebLogic Server 7.0中,容器提供了四種并發(fā)控制機(jī)制。它們是獨(dú)占式、數(shù)據(jù)庫式、積極式和只讀式。并發(fā)策略與交易進(jìn)行時的隔離級別緊密相關(guān)。并發(fā)控制并不是真正意義上的提高性能的措施,它的主要目的是確保實(shí)體bean所表示的數(shù)據(jù)的一致性,該一致性由bean的部署器所強(qiáng)制要求。無論如何,某些控制機(jī)制使得容器處理請求的速度比其它的要快一些,但這種快速是以犧牲數(shù)據(jù)的一致性為代價的。
最嚴(yán)格的并發(fā)策略是獨(dú)占式,利用特殊主鍵對bean的訪問是經(jīng)過系列化的,因此每次只能有一個交易對bean進(jìn)行訪問。這雖然在容器內(nèi)提供了很好的并發(fā)控制,但性能受到限制。在交易之間允許互為緩存的時候,這種方法很有用,但在集群環(huán)境中不能使用,此時,裝載操作被優(yōu)化掉,因此可能導(dǎo)致喪失并行性。
數(shù)據(jù)庫式的并發(fā)策略不同于數(shù)據(jù)庫的并發(fā)控制。實(shí)體bean在容器中并未被鎖定,允許多個交易對相同的實(shí)體bean并發(fā)操作,因此能夠提高性能。當(dāng)然,這樣對隔離的級別也許要求較高,以便確保數(shù)據(jù)的一致性。
積極式并發(fā)策略與數(shù)據(jù)庫的并發(fā)控制也不同。不同之處在于對數(shù)據(jù)一致性的檢查發(fā)生在對已設(shè)定的更新操作進(jìn)行存儲時而非在裝載時將整行鎖定。如果應(yīng)用內(nèi)對同一個bean訪問的沖突不是很激烈的情況下,本策略比數(shù)據(jù)庫式的策略要快一些,雖然兩個提供了相同的數(shù)據(jù)一致性保護(hù)級別。但是在有沖突發(fā)生的時候,本策略要求調(diào)用者要重新發(fā)起調(diào)用。 本特征也只對EJB 2.0 適用。
只讀式策略只能用于只讀bean。Bean只在應(yīng)用第一次訪問時或者超出參數(shù)read-timeout-seconds所指定的值時才被裝載。Bean從來不需要被存儲。當(dāng)基本數(shù)據(jù)改變時,也會通過read-mostly格式通知bean,從而引起重新裝載。
緊密關(guān)聯(lián)緩存: 如果兩個實(shí)體bean, bean A 和bean B 在CMR(容器關(guān)系管理)內(nèi)關(guān)聯(lián),兩個在同一個交易中被訪問,且由同樣的數(shù)據(jù)庫調(diào)用裝載,我們稱為緊密關(guān)聯(lián)緩存。這是WebLogic Server 7.0的新特征,同樣只適用于EJB2.0。
除了上面列出的通過優(yōu)化容器內(nèi)對數(shù)據(jù)庫的訪問從而達(dá)到性能增加的特征外,另有一些在容器之外,針對會話bean和實(shí)體bean的參數(shù)能夠幫助提升性能。
緩沖池和高速緩存是EJB容器為提高會話bean和實(shí)體bean性能所提供的主要特征。然而,這些方法并非對所有類型的bean適用。它們的消極面是對內(nèi)存要求較高,雖然這不是主要的問題。緩沖池適用于無狀態(tài)會話bean(SLSB),消息驅(qū)動bean(MDB)以及實(shí)體bean。一旦為SLSB和MDB設(shè)定了緩沖池的大小,這些bean的許多實(shí)例就會被創(chuàng)建并被放到緩沖池中,setSessionContext()/setMessageDriveContext()方法會被調(diào)用。為這些bean設(shè)置的緩沖池的大小不必超過所配置的執(zhí)行線程數(shù)(事實(shí)上,要求比此數(shù)要。。如果方法setSessionContext()要做任何開銷昂貴的操作的話,此時JNDI查詢已經(jīng)完成,使用緩沖池中的實(shí)例方法調(diào)用將會加快速度。對實(shí)體bean來說,在完成setEntityContext()方法調(diào)用之后,緩沖池與bean的匿名實(shí)例相連(沒有主鍵)。這些實(shí)例可以被查詢操作所使用,查詢方法從緩沖池中取出一個實(shí)例,為其指定一個主鍵,然后從數(shù)據(jù)庫中裝載相應(yīng)的bean。
高速緩存適用于有狀態(tài)會話bean(SFSB)和實(shí)體bean。實(shí)體bean已經(jīng)在前面討論過。對于SFSB,緩存能夠避免向硬盤串行化的操作。串行化到硬盤的操作非常昂貴,絕對應(yīng)該避免。用于SFSB的緩存大小可以比連接到服務(wù)器的并發(fā)客戶端數(shù)略微大些,這是由于僅當(dāng)緩存被占用了85%以后,容器才會設(shè)法將bean滯留在數(shù)據(jù)庫中待命。如果緩存大于實(shí)際所需,則容器不會通過緩存花費(fèi)時間將bean待命。
EJB容器提供了兩種方法進(jìn)行bean-to-bean 和 Web-tier-to-bean的調(diào)用操作:傳值調(diào)用和傳送地址調(diào)用。如果bean處在同一個應(yīng)用之中,則缺省情況下,用的是傳送地址的方法,這比傳值要快一些。傳送地址的方法一般不應(yīng)被禁止,除非有充足的理由要強(qiáng)制這樣做。強(qiáng)制使用傳送地址的另一種做法是使用本地接口。在WebLogic Server 7.0中引入了另一個特征是對有狀態(tài)服務(wù)使用激活(activation)。雖然這種做法在某種程度上影響了性能,但由于對內(nèi)存要求較低,因此極大地改進(jìn)了擴(kuò)展性。如果擴(kuò)展性不值得關(guān)注,可以將參數(shù)noObjectAction傳送給ejbc從而關(guān)閉激活(activation)。
JDBC
對數(shù)據(jù)庫的訪問來說,調(diào)試JDBC與調(diào)試EJB容器同樣重要。比方說設(shè)置連接池的大小――連接池應(yīng)大到足以容納所有線程對連接的要求。如果所有對數(shù)據(jù)庫的訪問能夠在缺省的執(zhí)行隊(duì)列中得以實(shí)現(xiàn),則連接數(shù)應(yīng)為執(zhí)行隊(duì)列中的線程數(shù),比讀取socket的線程(缺省執(zhí)行隊(duì)列中用來讀取進(jìn)入請求的線程)數(shù)要少。為了避免在運(yùn)行期間對連接進(jìn)行創(chuàng)建和刪除,可在初始時即將連接池設(shè)置為其最大容量。如果可能的話,應(yīng)確保參數(shù)TestConnectionsOnReserve被設(shè)置為假(false,這是缺省設(shè)置)。如果此參數(shù)設(shè)置為真(true),則在連接被分配給調(diào)用者之前,都要經(jīng)過測試,這會額外要求與數(shù)據(jù)庫的反復(fù)連接。
另一個重要的參數(shù)是PreparedStatementCacheSize。每個連接都為宏語句設(shè)一個靜態(tài)的緩存,大小由JDBC連接池配置時指定。緩存是靜態(tài)的,時刻牢記這一點(diǎn)非常重要。這意味著如果緩存的大小是n的話,則只有放在緩存中的前n條語句得到執(zhí)行。確保昂貴的SQL語句享受到緩存的方法是用一個啟動類將這些語句存放到緩存中。盡管緩存技術(shù)從很大程度上改進(jìn)了性能,但也不能盲目使用它。如果數(shù)據(jù)庫的格式有了變化,那么在不重新啟動服務(wù)器的情況下,無法使緩存中的語句失效或者是用新的進(jìn)行替換。當(dāng)然,緩存中的語句會使數(shù)據(jù)庫中的光標(biāo)得以保留。
對于WebLogic Server 7.0來說,由于jDriver性能的改進(jìn)已使其速度遠(yuǎn)遠(yuǎn)快于Oracle的廋驅(qū)動程序,尤其對于要完成大量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)既不會由于運(yùn)行在缺省或者其它執(zhí)行隊(duì)列中的應(yīng)用因爭奪資源而導(dǎo)致“營養(yǎng)匱乏”,反過來也不會搶奪其它應(yīng)用的資源。對JMS來說,大多數(shù)的調(diào)試參數(shù)都是在服務(wù)的質(zhì)量上進(jìn)行折衷處理。如,利用文件式持續(xù)性目的地(file-persistent destnation)禁止同步寫操作(通過設(shè)置特性: -Dweblogic.JMSFileStore.SynchronousWritesEnabled =false)以后會引起性能急劇提高,但同時也會冒著丟失消息或者重復(fù)接收消息的風(fēng)險。類似地,利用多點(diǎn)傳送發(fā)送消息會提升性能,同時也會有消息半途丟失的危險。
消息確認(rèn)間隔不應(yīng)設(shè)置得過短――發(fā)送確認(rèn)的比率越大,處理消息的速度可能會越慢。同時,如果設(shè)置得過大,則意味著系統(tǒng)發(fā)生故障時,消息會丟失或者被重復(fù)發(fā)送。
一般說來,應(yīng)在單個服務(wù)器上對多個JMS目的地進(jìn)行配置,而不是將它們分散在多個JMS服務(wù)器,除非不再需要擴(kuò)展。
關(guān)閉消息頁面調(diào)度(paging)可能會提高性能,但會影響可擴(kuò)展性。如果打開消息頁面調(diào)度(paging),則需要額外的I/O操作以便將消息串行化到硬盤,在必要的時候再讀進(jìn)來,但同時也降低了對內(nèi)存的要求。
一般來說,異步過程比同步過程更好操作,更易于調(diào)節(jié)。
Web容器
Web層在應(yīng)用中更多的是用來生成表達(dá)邏輯。廣泛使用的體系結(jié)構(gòu)是從應(yīng)用層讀取數(shù)據(jù),然后使用servlet和JSP生成動態(tài)內(nèi)容,其中應(yīng)用層一般由EJB組成。在這種結(jié)構(gòu)中,servlet 和JSP保留對EJB的引用,以防它們與數(shù)據(jù)庫或數(shù)據(jù)源直接對話。將這些引用保存起來是個不錯的主意。如果JSP和servlet沒有和EJB部署在同一臺應(yīng)用服務(wù)器上,則利用JNDI進(jìn)行查詢的費(fèi)用是很昂貴的。
JSP緩存標(biāo)記符可以用于存儲JSP頁面內(nèi)的數(shù)據(jù)。這些標(biāo)記符都支持對緩存的輸入和輸出。對緩存的輸出涉及到標(biāo)記符內(nèi)的代碼所生成的內(nèi)容,對緩存的輸入涉及到標(biāo)記符內(nèi)的代碼對變量的賦值。如果不希望Web層頻繁變化,則可以通過將ServletReloadCheckSecs 設(shè)置為-1,從而關(guān)閉自動裝載(auto-reloading)功能。使用這種方法以后,服務(wù)器將不再輪詢Web層是否有變化,如果JSP和servlet的數(shù)量很多,則效果是非常明顯的。
這里也建議不要在HTTP會話中儲存過多的信息。如果信息是必須的,可以考慮使用有狀態(tài)會話bean來替代。
JVM調(diào)試
如今的大多數(shù)JVM具有自主調(diào)節(jié)功能,因?yàn)樗鼈兡軌蛱綔y到代碼中的危險區(qū)域并對它們進(jìn)行優(yōu)化。開發(fā)和部署人員能夠考慮的調(diào)試參數(shù)大概就是堆設(shè)置了。設(shè)置這些并沒有一般的規(guī)則。JVM一般堆空間,按新空間或保留空間一般設(shè)置為整個堆空間的三分之一或一半組織。整個堆空間不能指定得過大以致于無法支持并發(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)試
除了由各個子系統(tǒng)提供的調(diào)試參數(shù)以外,還有適用于服務(wù)器的參數(shù)能夠幫助提升性能。其中最重要的是配置線程數(shù)和執(zhí)行隊(duì)列數(shù)。增加線程數(shù)并非總能奏效,僅當(dāng)下列情況成立時再考慮使用這種方法:預(yù)定的吞吐量沒有達(dá)到;等待隊(duì)列(未開始處理的請求)過長;CPU仍有剩余。當(dāng)然,這樣做并不一定能改善性能。CPU使用率低可能是由于對服務(wù)器的其它資源競爭所致,如,沒有足夠的JDBC連接。當(dāng)改變線程數(shù)時應(yīng)考慮到這些類似的因素。
在WebLogic Server 7.0中,提供了配置多個執(zhí)行隊(duì)列的功能,并且能夠在部署中定義處理特殊的EJB或JSP/servlet請求的執(zhí)行隊(duì)列。要做到這些,只要在運(yùn)行weblogic.ejbc時將標(biāo)志 -dispatchPolicy <隊(duì)列名稱> 傳送給bean 即可。對于JSP/servlet,可將設(shè)置Web應(yīng)用的weblogic部署描述符中初始化參數(shù)(init-param) wl-dispatch-policy的值設(shè)為執(zhí)行隊(duì)列的名字即可。有時應(yīng)用中的某些bean/JSP對操作的響應(yīng)時間比其它的要長,此時,可以對這些bean/JSP設(shè)置單獨(dú)的執(zhí)行隊(duì)列。至于隊(duì)列的大小,要達(dá)到最好的性能,還取決于經(jīng)驗(yàn)。
另一個比較大的問題是決定在何種情況下應(yīng)該使用WebLogic性能包(http://e-docs.bea.com/wls/docs70/perform/WLSTuning.html - 1112119)。如果socket數(shù)不太多(每個服務(wù)器上都有一個socket用于客戶端JVM的遠(yuǎn)程方法調(diào)用連接),而且總是忙于讀取從客戶端發(fā)送過來的請求數(shù)據(jù),那么此時使用性能包恐怕不會有明顯的改進(jìn)。也有可能不用性能包會導(dǎo)致相似或更好的結(jié)果,這取決于JVM在處理網(wǎng)絡(luò)I/O時的具體實(shí)現(xiàn)。
Socket讀取線程取自缺省執(zhí)行隊(duì)列。在Windows 環(huán)境下,每個CPU有兩個socket讀取線程,在solaris環(huán)境下,共有三個socket用于本地輸入輸出(native I/O)。對于Java 輸入輸出(I/O),讀取線程數(shù)由配置文件config.xml中的參數(shù)PercentSocketReaderThreads 進(jìn)行設(shè)置。它的缺省值是33%, 上限是50%,這是顯而易見的,因?yàn)槿绻麤]有線程用于處理請求,則同樣不會有更多的讀取線程啦。對于Java I/O,應(yīng)使讀取線程數(shù)盡量接近客戶端連接數(shù),因?yàn)樵诘却埱髸r,Java I/O會阻塞。這也是為什么當(dāng)客戶端的連接數(shù)增加時,線程數(shù)不能一直同等增加的原因。
結(jié)論
我們上面只討論了調(diào)試服務(wù)器的部分方法。需要記住的是,一個設(shè)計蹩腳,編寫欠佳的應(yīng)用,通常都不會有好的性能表現(xiàn),無論對服務(wù)器及其參數(shù)如何調(diào)試。貫穿應(yīng)用開發(fā)周期的各個階段――從設(shè)計到部署,性能始終應(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。