opensessioninview
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)
-----------------------------------------------
對於Spring的OpenSessionInViewFilter來說,雖然資料庫連線被保持了過長的時間,但是並沒有鎖定資料庫資源,特別是事務資源。
其實我認為資料庫連線被保持過長時間有時候會有很大的問題。尤其是對於採用資料連線池的情況,如果你的資料庫連線一直被保持,那麼這個資源就未被釋放。假設說這個資料連線池的最大連線數為15,我感覺很容易造成資料庫的連線不夠用。
不清楚底層的實現是如何做的,或許我的疑問有些多慮。
按道理來說,資料庫連線應該儘早被釋放,以緩解資料庫資源的壓力,延遲很久才釋放,確實會導致需要更多的資料庫連線。這個就只能擴大連線池數量,增加資料庫最大允許連線數來解決了。
此外,Session被延遲很久釋放,那麼Session佔用的一級快取也會佔用比較長時間,這意味著會無謂消耗更多的JVM記憶體。
因此,OpenSessionInView雖然確實方便,但是大家還是慎用吧。對於那些頁面渲染速度很慢,撥號連線使用者數量過多的網站就最好不要使用。
---------------------------
不過,如果不用OpenSessionInView,我還真一下子就找不到北叻,從學Hibernate開始就一直在OpenSessionInView的薰陶下長大。。。-_-b
Robbin有什麼好的辦法能夠在不使用OpenSessionInView的情況下比較好的處理頁面嗎?
在dao中對要render的集合強制初始化。
-----------------------------------
foo.getBars()
Hibernate.initialize(foo.getBars);