標籤:ejb cluster timer cluster 叢集
最近Customer Site報了一個錯誤,在Weblogic Cluster HA測試過程中,發生了Traffic叢集中有一個節點在重啟過程中仍然有請求資料送到該節點的問題。研究了相關的代碼,發現了一個非常有趣又普遍的問題。
由於Traffic分發系統沒有部署在Weblogic叢集中,又需要分發到Weblogic叢集中的Traffic節點,系統中使用了自己的load balancing機制。
代碼中負責traffic分發的loadbalancer從Cluster當中部署的ClusterWebApp應用去拿Cluster中當前活著的trafficList。
而ClusterWebApp中Serverlet的getTrafficList是一個Web Serivce介面,從叢集中部署的Stateless EJB擷取trafficList並通過JSON返回給loadbalancer。如所示:
ClusterEJB中getTrafficList的實現,由於每次都從Weblogic讀取traffic資訊耗時比較長,所以在ClusterEJB中引入了緩衝。
當ClusterWebApp調用ClusterEJB的getTrafficList方法時,返回的是ClusterEJB緩衝的running traffic list。
這個緩衝是通過Cluster EJB Timer來更新,每次timeout去Weblogic擷取最新的traffic server list.
系統HA出錯的日誌顯示是因為ClusterWebApp返回的trafficList偶爾會包含已經shutdown的節點。那麼第一時間點就懷疑緩衝失效。
查看ClusterEJB中timer的實現,使用的是Cluster EJB Timer,在weblogic部署描述符中指明了:<wls:timer-implementation>Clustered</wls:timer-implementation>
Cluster EJB Timer是用來處理聚群範圍內的全域任務,比如定時產生報表,發送郵件等任務,這些任務不需要同時在多個叢集節點同時執行,很顯然本例中ClusterEJB的緩衝
在於叢集中部署了ClusterEJB的每一個節點,期望行為是Timer可以在每個節點同時執行更新緩衝狀態。而使用Cluster EJB Timer只能保證每次逾時會在某一個節點上運行(取決
於叢集的預設load balance演算法或者部署描述符中指定的演算法),這樣叢集中很多節點就會很長時間沒有更新緩衝從而出現了緩衝失效的情況。
把Cluster EJB Timer改成Local就可以修複這個問題。
這是當初從非叢集環境遷移到叢集環境的時候直接使用了叢集EJB Timer來代替普通Java Timer,沒有仔細研究使用情境導致的錯誤。Timer或者類似的任務在叢集部署的時候都要小心到底是Local的還是叢集的。
Cluster EJB Timer 參考(英文)
實現
原理
weblogic-ejb-jar.xml Deployment Descriptor Reference