1. 程式人生 > >Trouble Shooting -- WebSphere 連線池不夠使用的問題

Trouble Shooting -- WebSphere 連線池不夠使用的問題

之前公司有個把新建立的ABS產品傳送到外部媒體驗證的小專案(需要在專案中記錄驗證狀態資訊,儲存在資料庫中,使用openjpa做持久層實現)。花了個把月的時間搞定了,產品上線執行之後(部署Websphere),爆出了一次資料庫連線池不夠用的問題,出現以下異常:
com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException: Connection not available, Timed out waiting for 180007
我們的連線池配置了最大10個連線,最大等待時間是預設的180s。出現這個問題讓我感到很意外,系統最開始設計的時候需求裡寫明的是10分鐘內最多7-8個請求(10分鐘是因為一個請求處理需要5~10分鐘,涉及到4次資料庫寫+n次資料庫讀+n次smb讀+1次smb寫)。在系統整合測試的時候(部署tomcat)試過同樣的連線池配置同時處理30個請求都沒有問題。趕緊查詢了一下出問題的時候系統狀態,顯示只是同時有12個請求,這就讓我感覺很奇怪了,為什麼會出現連線池都用光了的情況。因為一個請求存在的時間比較長,資料庫連線的獲取和釋放都做了小心處理。程式碼中的連線池獲取和釋放都是交給了Spring transaction,每次資料庫讀寫都是單獨的事務,沒有理由會出現連線池不釋放的情況,在測試環境中JavaSimon的監控資料也顯示了資料連線池最長佔用時間不過2秒多。
因為對websphere不夠熟悉,只好趕緊去檢視websphere的文件,發現了可疑之處,在web.xml中寫resource reference的時候連線池我使用了預設的shareable模式,而在

websphere的文件中寫明shareable代表這在應用和連線池中間又加多了一層connection維護者,shareable資源在短請求多次使用連線的時候很有用,對我這種長請求間隔使用幾次資料庫連線反而引起嚴重副作用,連線被佔住不釋放,將連線池資源使用方式改成unshareable之後,問題得到解決。
* *

One key point regarding this behavior is that when the application
closes a shareable connection, the connection is not truly closed, nor
is it returned to the Free pool. Rather, it remains in the Shared
connection pool, ready for another request within the same LTC for a
connection to the same resource

**

Note:在調查過程中,有人查詢openjpa的connection usage文件建議把entitymanager改成使用單個connection,顯然是對entitymanager的容器管理理解不夠,entitymanager不是執行緒安全的,spring注入的是執行緒安全的例項(threadlocal)。