1

環境:Webphere 6,Solaris box,胖客戶端,Java Web應用程序。在這個多線程案例中使用線程池是否明智?

請求數可以在400-600之間。在對服務器的每個請求中,我創建了15個線程(使用Java ExecutorService)來同時請求15個不同的webservies,並將所有響應數據組合在一起併發回給用戶。 負載測試將近150-170位用戶失敗。在爲這些Web服務提供服務的DB中會看到CPU和內存尖峯,並且最終在很短的時間內,應用程序服務器崩潰。 網絡服務的響應時間最多10-12秒,最短4-6秒。 DB的連接池大小爲40.

我假設150個請求正在創建150 * 15 = 2250個線程,並且應用程序服務器資源正在被尖刺並因此崩潰。所以我想使用App服務器線程池並讓threadCount聲明爲100(可能不是很好的數字..)。有一件令我困擾的事情是,有100個線程,我可以處理前6個(6 * 15 = 90)請求和10個7次請求調用。接下來的請求必須等待10-15秒才能獲得線程,然後再等待10-15秒來完成自己的web服務調用。這種方法甚至好嗎?

另一個想法是在Websphere中提供的異步bean。哪一個適合我的要求。

請建議!!一個接一個地調用一個web服務總共需要15 *(可以說每個請求4秒)= 60秒,這真的很糟糕。所以一起調用webserices是我想要做的。

回答

1

不建議在管理應用程序服務器中的線程。如果您使用的是EJB,則規格爲disallows that

爲什麼不使用緩存解決方案來提高性能?前幾個請求會比較慢,但是一旦緩存很熱,一切都會非常快。

如果緩存數據不可行,那麼更改客戶端以向服務器發出多個請求,而不是在多個線程中拆分一個請求呢?您需要更改您的Web應用程序,以便每個方法都可以調用一個Web服務。客戶端會調用(並行)當前頁面所需的每種方法並彙總最終結果(如果願意,可能會顯示部分結果)。通過這樣做,你可以並行工作,不會違反規範。

我假設你有這樣的事情,在你的服務器:

public Result retriveData(Long id) { 
    Result myResult = new Result(); 
    //... 
    //do some stuff 
    myResult.setSomeData(slowWebService1.retriveSomeData(id)); 
    myResult.setSomeOtherData(slowWebService2.retriveSomeOtherData(id)); 
    myResult.setData(slowWebService3.retriveData(id)); 
    return myResult; 
} 

在您的客戶端:

Result result = webApplication.retriveData(10); 
//use the result 

我的建議,就是分裂在多個方法調用:

public SomeData retriveSomeData(Long id) { 
    //do some stuff 
    SomeData data = slowWebService1.retriveSomeData(id); 
    //do more stuff 
    return data; 
} 

public SomeOtherData retriveSomeOtherData(Long id) { 
    //do some stuff 
    SomeOtherData data = slowWebService2.retriveSomeOtherData(id); 
    //do more stuff 
    return data; 
} 

public Data retriveData(Long id) { 
    //do some stuff 
    Data data = slowWebService3.retriveData(id); 
    //do more stuff 
    return data; 
} 

在您的客戶端:

//Call these methods in parallel, if you were using Swing, this could be done with 
//SwingWorker (I have no idea how to it with Flash :)). 
//You can either wait for all methods to return or show partial results. 
callInBackground(webApplication.retriveSomeData(10), useDataWhenDone); 
callInBackground(webApplication.retriveSomeOtherData(10), useDataWhenDone); 
callInBackground(webApplication.retriveData(10), useDataWhenDone); 

通過這樣做,您只需調用您的Web應用程序,就像以前一樣,所以不應該存在任何安全問題。

我不熟悉Websphere,所以我不能說是否使用它的異步Bean比這更好,但是你應該避免手動啓動線程。

+0

謝謝你的回覆「iruediger」。你的意思是緩存從Web服務檢索到的數據?我們不能這樣做,因爲來自用戶的請求是唯一的(例如:輸入是SSN,並且輸出將是來自許多服務的所有醫療細節)。如果您的建議不是數據緩存,可以請您多解釋一下。謝謝 – user418836 2011-06-10 21:47:15

+0

是的,我正在考慮像[Ehcache](http://ehcache.org/)這樣的數據緩存。由於這對您的系統來說不可行,您可以更改客戶端以發出多個請求(查看我的答案)。 – iruediger 2011-06-10 22:36:46

+0

我的客戶端應用程序是一個Flash應用程序,所有Web服務都是外部第三方服務。 Flash播放器具有內部安全措施,不允許與託管服務器以外的其他服務器進行交互。唯一可能發生的情況是,所有這些第三方服務器都必須在其服務器上具有crossdomain.xml,才能訪問我們的服務器域。沒有服務提供商會同意。唯一的選擇是從我們的應用服務器調用這些服務。我們又回到原點了。 – user418836 2011-06-12 04:21:44