我有一個默認standalone.xml配置,其中有一個最大的20個連接的是活躍在到數據庫連接池的同時。我想,有很好的理由。我們運行一個Oracle數據庫。的Java-EE數據庫連接池耗盡了最大
有數據庫流量的合理量有第三方API的流量,例如我正在開發的企業應用程序中的SOAP和HTTP調用。
我們經常做類似如下:
@PersistenceContext(unitName = "some-pu")
private EntityManager em;
public void someBusinessMethod() {
someEntity = em.findSomeEntity();
soap.callEndPoint(someEntity.getSomeProperty()); // may take up to 1 minute
em.update(someEntity);
cdiEvent.fire(finishedBusinessEvent);
}
然而,在這種情況下,當實體獲取和更新(實際上當整個交易完成)後,被釋放的數據庫連接收購。關於交易,一切都是容器管理的,沒有額外的註釋。我知道你不應該「持有」數據庫連接超過必要的時間,這正是我想要解決的問題。對於一個我不知道如何以編程方式釋放連接我也不認爲這是一個好主意,因爲你仍然希望能夠回滾整個事務。
那麼,如何攻擊這個問題?有多種選擇我想:
選項1,使用ManagedExecutorService
:
@Resource
private ManagedExecutorService mes;
public void someBusinessMethod() {
someEntity = em.findSomeEntity();
this.mes.submit(() -> {
soap.callEndPoint(someEntity.getSomeProperty()); // may take up to 1 minute
em.update(someEntity);
cdiEvent.fire(finishedBusinessEvent);
});
}
選項2,使用@Asynchronous
:
@Inject
private AsyncBean asyncBean;
public void someBusinessMethod() {
someEntity = em.findSomeEntity();
this.asyncBean.process(someEntity);
}
public class AsyncBean {
@Asynchronous
public void process() {
soap.callEndPoint(someEntity.getSomeProperty()); // may take up to 1 minute
em.update(someEntity);
cdiEvent.fire(finishedBusinessEvent);
}
}
這實際上解決了數據庫連接池的問題,例如該連接在soap.callEndPoint
發生時立即釋放。但它感覺不太穩定(不能指出這裏的問題)。當然,一旦你進入a-sync處理,交易就完成了,所以在肥皂調用過程中出現問題時,沒有任何回滾。
結束了... 我要長時間運行的IO任務(SOAP和HTTP調用)移動到通過隊列的卸載應用程序的一個單獨的部分,並通過隊列的一次是在應用餵養結果返回再次。在這種情況下,所有事情都是通過交易完成的,並且沒有任何連接被阻止但是這是一個很大的開銷,因此在這之前我想聽聽你的意見/最佳實踐如何解決這個問題!
有多少併發web請求正常執行並處於高峯? –
大約在50到100之間,峯值在200.蜻蜓配置爲等待大約30秒,然後才從池中獲取連接。沒有重試。 – Velth
處理同一實體的併發更改的策略是什麼? –