[英]Handling a timeout in EJB3 without using threads
我有以下情況。 我有一份工作:
我們當前的解決方案使用一個線程,該線程會在存在一定時間后拋出異常而不會被外部進程中斷,但是由於這顯然違反了 EJB 標准,我們正在嘗試通過其他方式解決它。
有任何想法嗎?
編輯添加:自然,超時的作業也需要刪除(或中斷)。
編輯添加2:這個問題似乎沒有任何解決方案,因為檢測死鎖似乎幾乎不可能堅持純EJB3標准。 由於 Enno Shioji 下面的評論反映了這一點,我將他的建議設置為正確答案。
使用 Bean Managed Transaction,可以使用 UserTransaction 接口指定特定事務的超時時間。
使用 begin 方法修改與當前線程啟動的事務關聯的超時值。
void setTransactionTimeout(int seconds) throws SystemException
通過一點點工作,它應該在給定的場景中工作正常。
編輯:也可以使用服務器特定的屬性來管理事務超時。
JBoss :可以在 class 或方法級別注釋@TransactionTimeout(100)
應用。
Weblogic :在 weblogic-ejb-jar.xml 中指定參數
<transaction-descriptor>
<trans-timeout-seconds>100</trans-timeout-seconds>
</transaction-descriptor>
GlassFish :在 sun-ejb-jar.xml 中使用可選的cmt-timeout-in-seconds
元素
這更像是一個澄清請求,但它太長了,不適合作為評論..
我不確定你現在是怎么做的,因為從你寫的內容來看,僅僅使用請求處理線程似乎是 go 的方式。 像這樣:
//Some webservice method (synchronous)
public Result process(Blah blah){
try{
return getResult(TimeUnit.SECONDS, 10);
}catch(InterruptedException e){
//No result within 10 seconds!
throw new ServiceUnavailableException("blah");
}
}
我不確定你為什么要創建線程。 如果您因為getResult
方法根本沒有超時而被迫使用線程,那么您將遇到線程泄漏。 如果它在較長時間后超時,因此您想“快捷地”回復用戶,那將是我考慮使用線程的唯一情況,就像我想象的那樣使用它。 這可能會導致線程在負載下堆積,我會努力避免這種情況。
也許您可以發布一些代碼,讓我們知道您為什么要在服務中創建?
另外,您的客戶端界面是什么? 聽起來像是一個同步網絡服務之類的?
HashedWheelTimer
作為 singleton ......這個機制應該很好地滿足你的要求( 這里是一個實現)。
然而,不幸的是,這似乎與 EJB 規范中對線程的禁令和對 singleton 的禁令相沖突。
實際上,如果您這樣做,確實沒有問題。
例如,請參閱此討論。
我們還在 EJB 應用程序中使用了 singleton 模式。
它使用了 JBoss。
但是,如果這不是一個可行的選擇,那么我可能會考慮通過定義新的 web 服務(並將其部署在 Web 容器或其他東西中)來隔離其自己的 JVM 中的處理,並從 EJB 應用程序調用該服務。
然而,這顯然會導致性能下降,現在您將擁有另一個全新的應用程序。
將進程及其超時線程插入帶有@WebService 注釋的 class 中,然后從 EJB 調用 WebService。
WAR 沒有 EJB 那樣的限制或遵循相同的契約,因此它們可以安全地運行線程。
是的,我認為這是一種“hack”,但它符合要求,並且是可移植的。
對於 EJB,有一個“容器管理事務”的概念。 通過在 bean 或特定方法上指定 @TransactionAttribute,容器將在調用方法時創建事務。 如果代碼的執行時間超過事務閾值,容器會拋出異常。 如果調用在事務閾值以下完成,它將照常返回。 您可以在調用代碼中捕獲異常並適當地處理它。
For more on container managed transactions, check out: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html and http://download.oracle.com/javaee/5/tutorial/ doc/bncij.html
您可以使用@TimeOut
。 就像是:
@Stateless
public class TimedBean {
@Resource
private TimerService timerService;
static private AtomicInteger counter = new AtomicInteger(0);
static private Map<Integer, AtomicBoolean> canIRunStore = new ...;
public void doSomething() {
Integer myId = counter.getAndIncrement();
AtomicBoolean canIRun = new AtomicBoolean(true);
canIRunStore.put(myId, canIRun);
timerService.createTimer(1000, 0, myId);
while (canIRun.get() /* && some other condition */) {
// do my work ... untill timeout ...
}
}
@Timeout
@PermitAll
public void timeout(Timer timer) {
Integer expiredId = (Integer) timer.getInfo();
AtomicBoolean canHeRun = canIRunStore.get(expiredId);
canIRunStore.remove(expiredId);
canHeRun.set(false);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.