門戶中的資源掛起線程應(yīng)急解決方案
業(yè)務(wù)任務(wù)
您的門戶出現(xiàn)用戶請求在資源中掛起情況的頻率是多高?我希望這種情況不經(jīng)常發(fā)生。然而,如果出現(xiàn)了這種情況,而且資源不斷掛起用戶請求,則門戶會面臨耗盡所有已配置的并發(fā)用戶請求并最終崩潰的致命風(fēng)險。這將是一場災(zāi)難。我碰到過幾次這樣的情況,并決定保護我的門戶不再受類似情況的影響。
我們需要讓門戶包含幾個具有登錄控件(通過用于每個Portlet的備份文件提供)的Portlet。對于每個請求,創(chuàng)建一個備份文件,備份文件在用戶請求方面是線程安全的。在登錄控件中,備份文件的init()方法(或preRender()方法)調(diào)用獨立的安全服務(wù)(資源)API以獲得資源訪問授權(quán)。對于業(yè)務(wù)處理,Portlet也通過其他API調(diào)用將用戶請求委托到業(yè)務(wù)層。一切都運行正常,直到一個對資源的調(diào)用未返回到Portlet,即,由于某種原因,它在某處掛起了。以下是一個具體示例。
我們假定WebLogic Portal使用EJB作為業(yè)務(wù)層和/或安全服務(wù)中的資源。此EJB操作其他資源,并通過使用JMS發(fā)送消息的方式報告處理狀態(tài)。此EJB與其他應(yīng)用程序一起部署在集群中。門戶部署在另一個物理機器上。如果共同部署的一個應(yīng)用程序引發(fā)了內(nèi)存錯誤,則整個集群(包括EJB)都會掛起,即它不返回請求也不拋出異常。事實上,討論如此顯著的失效是沒有必要的:從門戶的角度來說,“掛起”模式僅是門戶的動態(tài)并發(fā)生命周期中的一種返回得過慢、延遲過久以至于不能接受的響應(yīng)。例如,延遲可能由于服務(wù)器過載或數(shù)據(jù)庫出現(xiàn)問題引起,但這是不相干的——備份文件中的線程運行時間超出了正常門戶工作的允許范圍,達到了門戶中的“最大并發(fā)用戶數(shù)”。此門戶完全停止接受用戶請求——這就成了問題。
解決方案設(shè)計
我首先想到的是,在Portlet用于訪問其資源的RMI客戶端(即EJB客戶端)上設(shè)置超時(遠程-客戶端-超時)。然而,關(guān)于使用RMI超時的WebLogic指導(dǎo)原則列出了關(guān)于此類超時的幾條限制,其中包括“在調(diào)用中不涉及JMS資源。”這就是說,不能對EJB資源使用超時。我提及這種情況只是為了說明存在門戶可能未被保護以不受掛起的資源線程影響的情況。即使沒有關(guān)于超時的限制,如果請求掛起的速度快于超時釋放相關(guān)線程的速度,問題就依然存在。
我想介紹一種針對此問題的可能解決方案。此解決方案在下面的條件下有效:門戶具有一些獨立于可能會掛起的資源的內(nèi)容或功能。就是說,門戶可以運行部分功能。
此解決方案包括3個組件:監(jiān)控、決策規(guī)則和規(guī)則實施方法。此解決方案的原理很簡單:門戶監(jiān)控運行中的資源調(diào)用,從而監(jiān)控被調(diào)用的資源線程,對運行過久的資源線程的數(shù)量進行計數(shù)(riskCounterValue),然后應(yīng)用決策規(guī)則,如“如果riskCounterValue達到或超出預(yù)定義的閾值(riskThreshold),則所有傳入的對此資源的調(diào)用均被拒絕,直到riskCounterValue小于riskThreshold。”使用此規(guī)則可以限制可能“掛起”的資源線程數(shù)量,而且可能使用簡化功能處理用戶請求。例如,如果門戶包含4個Portlet,用于一個Portlet的某些資源線程被認為“存在掛起的風(fēng)險”,則門戶可以跳過存在風(fēng)險的Portlet而僅對用戶顯示3個Portlet。
規(guī)則實施方法的實現(xiàn)非常重要。如果此規(guī)則在每個調(diào)用的范圍內(nèi)執(zhí)行,我們可以預(yù)見性能會降低,但是可以輕松地控制可能“掛起”的資源線程。如果此規(guī)則在調(diào)用以外執(zhí)行,我們可以保持性能,但是對此類控制的調(diào)整是需要技巧的。我們將詳細討論后一種情況。圖1的圖描述了這種情況。
如圖所示,在第一步中,門戶初始化一個Helper對象,而此Helper對象則初始化一個CallRegistry對象。后者可作為java.util.HashMap實現(xiàn),并用于注冊所有對資源API的調(diào)用。然后Helper啟動一個watchdog線程。例如,如果使用Struts,則此線程就在模型中啟動。watchdog線程定期檢查CallRegistry中的記錄,對運行時間過長的調(diào)用數(shù)量進行計數(shù),并將其設(shè)置為Helper中的riskCounterValue變量。
假定我們大概知道API調(diào)用的正常執(zhí)行時間。該值(最長持續(xù)時間)可以用于所有的API,或者每個API可以具有其單獨的執(zhí)行時間。因此,當調(diào)用一個API方法時,我們可以計算此API在正常情況下預(yù)期完成的時間,例如:
java.lang.System.currentTimeMillis()
long apiExecutionTime = ...;// property
long timeToComplete =
java.lang.System.currentTimeMillis() + apiExecutionTim
當調(diào)用Helper的方法時,它將一條新記錄添加進CallRegistry。此記錄包括一個惟一的調(diào)用ID(用作java.util.HashMap中的鍵)和用于API的預(yù)期完成時間(timeToComplete)(用作java.util.HashMap中的值)。如果此方法成功完成,它會從CallRegistry移除其記錄。
讓我們來看一下用戶請求是如何處理的。接到用戶請求后,Portlet的備份文件將其委托給Helper API方法(后者調(diào)用資源API)。首先,此Helper API方法檢查其是否可以執(zhí)行。如果接到請求的時候尚未達到riskThreshold,則此Helper API方法繼續(xù)運行。否則,它會拋出一個異常,門戶會繼續(xù)下一項功能或下一個API調(diào)用。
僅在運行時間過長的資源線程數(shù)量(riskCounterValue)小于riskThreshold的情況下才可以賦予執(zhí)行的權(quán)限。通過配置屬性設(shè)置riskThreshold。例如,如果將并發(fā)用戶請求最大值配置為25,則riskThreshold可以設(shè)置為10。這就是說,門戶處理并發(fā)用戶請求的能力僅存在一半風(fēng)險,它在資源線程開始掛起的情況下仍然可以運行。
請注意我們不對運行時間過長的API調(diào)用進行任何操作。它們中的一些最終可以成功完成,Helper API方法會將其記錄從CallRegistry移除,即下一次計數(shù)可能會低于riskThreshold,下一次針對資源的用戶請求可能不會被拒絕(通過拋出異常的方式)。
門戶無法知道網(wǎng)絡(luò)中是否存在意外延遲或者資源線程是否確實掛起。因此,推薦在幾個順序控制周期中達到或超出riskThreshold時給操作團隊發(fā)送一個通知(例如,通過電子郵件)。收到的通知允許操作團隊迅速分析日志,及時找到并解決運行時間過長的調(diào)用的原因。
分析和調(diào)整
對“掛起”的資源線程的控制具有很大的動態(tài)性,要對其進行調(diào)整并不是一件簡單的事。其效果是基于對以下3個參數(shù)的權(quán)衡:
- 用戶請求之間的平均時間(TUR)與watchdog線程控制周期(風(fēng)險控制周期)之間的時間(TRC)的比率:R = TUR / TRC
- 用于特定資源的風(fēng)險閥值(riskThreshold)
- 資源API調(diào)用的預(yù)期執(zhí)行時間
對控件的研究和測試得出的結(jié)論是,參數(shù)調(diào)整取決于特定的門戶實現(xiàn),但具有共同的趨勢。圖2中的圖表展示了用于調(diào)整的準則。在測試中,比率被設(shè)為R = 95%,TUR為95[ms],TRC被設(shè)為100[ms]。通常,可靠的比率是90%或更高。
此圖表顯示“掛起”的API調(diào)用數(shù)(在控件中計數(shù))是如何取決于調(diào)用執(zhí)行時間的。圖表中的點代表風(fēng)險控制周期之間掛起的用戶請求的最大數(shù)量,即在針對給定調(diào)用執(zhí)行時間而進行的一系列測試中的riskCounterValue最大值。請記住,在實施決策規(guī)則時,一些用戶請求被拒絕,而“掛起”的資源線程數(shù)量不會增加。
圖2中的水平紅線標記門戶中所允許的最大并發(fā)用戶數(shù)量。控件的目的是將最大riskCounterValue嚴格保持在紅線以下。圖表中的點越接近紅線,就越可能達到或超出riskThreshold。
我們可以看到,控制的行為不明顯。對于某些調(diào)用執(zhí)行時間值(從3250ms到1500ms),控件生成用戶請求,“掛起”的資源線程數(shù)量接近并超出門戶允許的并發(fā)用戶最大值。在此間隔期間,控制在給定條件下是無效的。同時,控制在從100ms到1000ms和從3500ms到4000ms的2個間隔中是有效的:具有特定riskThreshold的決策規(guī)則可靠地保護門戶不受“掛起”的API調(diào)用的影響,并保留足夠的并發(fā)請求線程以服務(wù)其他用戶請求。
此圖表還顯示較小的riskThreshold可提供較好的保護。但是,如果將一個資源的riskThreshold設(shè)置得過低,資源可能僅僅由于網(wǎng)絡(luò)延遲的輕微波動就在大多數(shù)用戶會話中不可用。這是另一個主題了:平衡和調(diào)整。
結(jié)束語
這套關(guān)于“掛起”的資源調(diào)用的運行時控制的推薦解決方案允許門戶隔離有問題的資源,并使用余下的資源繼續(xù)運行,從而最大程度地減小對性能的影響。此解決方案的效果取決于以下幾個調(diào)整參數(shù):請求頻率和風(fēng)險控制周期頻率的比率、風(fēng)險閥值的值和預(yù)期的調(diào)用執(zhí)行時間。
這種情況下的調(diào)整不是一件容易的事——它需要密集的測試。此外,本文中給出的數(shù)字是特定于我的測試門戶的,即使您發(fā)現(xiàn)了相關(guān)性,在您的門戶上進行的測試中使用的應(yīng)該是其他值。另一方面,如果某種程度的性能降低是可以接受的,則推薦在每個API調(diào)用的范圍內(nèi)執(zhí)行風(fēng)險控制周期,以顯著簡化解決方案參數(shù)的調(diào)整。
參考資料
- WebLogic RMI特性和指導(dǎo)原則:關(guān)于使用RMI超時的指導(dǎo)原則http://e-docs.bea.com/wls/docs81/rmi/rmi_api.html
- Nyberg, G.、Patrick, R.、Bauerschmidt, P.、McDaniel, J.以及Mukherjee, R.所著的“Mastering BEA WebLogic Server: Best Practices for Building and Deploying J2EE Applications”,Wiley E-Book,2004年3月出版。ISBN: 0-471-48090-8。
原文出處:
http://wldj.sys-con.com/read/185309.htm
?作者簡介 |
|
Michael Poulin 是一位技術(shù)架構(gòu)師,現(xiàn)供職于華爾街一家大型公司。他是Sun認證的Java技術(shù)架構(gòu)師。過去數(shù)年來,他專攻分布式計算、應(yīng)用程序安全性和SOA。 |