opensessioninview

handawei_5發表於2010-05-31

robbin:

我寫了一個簡單的webapp在Tomcat5.5.12上面做了一個小測試。在JSP頁面裡面迴圈1萬次輸出字串,程式在遠端伺服器上面執行,網路是ADSL寬頻,filter確實被阻塞了20秒左右。然後我另外開了一個flashget去下載伺服器上的大檔案,模擬網路速度比較慢的環境,filter被阻塞了50秒左右。分別做了三次測試。另外當頁面下載過程中直接點選瀏覽器stop按鈕,則JSP執行被打斷,filter立刻解除阻塞,被執行完畢。

結論證明,使用OpenSessionInView的時候,如果render的頁面資料量非常大,並且客戶端網路速度很慢的情況下,由於頁面的輸出時間過程很長,確實會造成filter被長時間阻塞。對於OpenSessionInViewFilter來說,就會造成資料庫連線被保持很長的時間,才能被關閉。

不過,對於Spring的OpenSessionInViewFilter來說,雖然資料庫連線被保持了過長的時間,但是並沒有鎖定資料庫資源,特別是事務資源。因為Spring的事務是通過TransactionInterceptor來實現的,在MVC結構中,當最後一個業務bean被呼叫結束以後,Transaction就已經被提交了。此後,雖然資料庫連線還保持中,但是資料庫資源沒有鎖定問題。

完整的呼叫示意圖:

request -> (OpenSessionInViewFilter開啟Session) ->  ServletDispatcher -> Action -> (開啟Connection,啟動事務) -> spring bean -> another spring bean -> (提交事務) -> bean執行完畢,返回Action -> render view(JSP/Template) -> (OpenSessionInViewFilter關閉Session和Connection)

 

 

 

-----------------------------------------------

downpour 寫道
robbin的分析很透徹,對於最後一點,我稍有疑問。

引用

對於Spring的OpenSessionInViewFilter來說,雖然資料庫連線被保持了過長的時間,但是並沒有鎖定資料庫資源,特別是事務資源。


其實我認為資料庫連線被保持過長時間有時候會有很大的問題。尤其是對於採用資料連線池的情況,如果你的資料庫連線一直被保持,那麼這個資源就未被釋放。假設說這個資料連線池的最大連線數為15,我感覺很容易造成資料庫的連線不夠用。

不清楚底層的實現是如何做的,或許我的疑問有些多慮。



按道理來說,資料庫連線應該儘早被釋放,以緩解資料庫資源的壓力,延遲很久才釋放,確實會導致需要更多的資料庫連線。這個就只能擴大連線池數量,增加資料庫最大允許連線數來解決了。

此外,Session被延遲很久釋放,那麼Session佔用的一級快取也會佔用比較長時間,這意味著會無謂消耗更多的JVM記憶體。

因此,OpenSessionInView雖然確實方便,但是大家還是慎用吧。對於那些頁面渲染速度很慢,撥號連線使用者數量過多的網站就最好不要使用。

---------------------------

hongliang 寫道
幾天沒來,居然變精華叻。。。本來我也想做一下robbin的那個測試,結果這幾天忙於其它事,一直沒時間。看來OpenSessionInView果然有這個問題,這也是我一直擔心的,看來真是應叻那句話,“如果一件事可能出錯,那它一定會出錯”。。。

不過,如果不用OpenSessionInView,我還真一下子就找不到北叻,從學Hibernate開始就一直在OpenSessionInView的薰陶下長大。。。-_-b

Robbin有什麼好的辦法能夠在不使用OpenSessionInView的情況下比較好的處理頁面嗎?



在dao中對要render的集合強制初始化。

-----------------------------------

hongliang 寫道
是不是像這樣?

foo.getBars()



Hibernate.initialize(foo.getBars);