如何设置小于1秒的Geronimo事务超时时间?
如何在Geronimo事务管理器中实现小于1秒的事务超时?
问题分析
从TransactionTimer的实现代码来看,它通过后台线程每隔1秒更新一次currentTime值,这直接导致小于1秒的事务超时无法精确生效:
package org.apache.geronimo.transaction.manager; import java.security.AccessController; import java.security.PrivilegedAction; public class TransactionTimer { private static volatile long currentTime; public TransactionTimer() {} public static long getCurrentTime() { return currentTime; } static { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { TransactionTimer.CurrentTime tm = new TransactionTimer.CurrentTime(); tm.setDaemon(true); tm.start(); return null; } }); } private static class CurrentTime extends Thread { protected CurrentTime() { TransactionTimer.currentTime = System.currentTimeMillis(); this.setContextClassLoader((ClassLoader) null); } public void run() { while (true) { TransactionTimer.currentTime = System.currentTimeMillis(); try { Thread.sleep(1000L); } catch (InterruptedException var2) { ; } } } } }
再结合TransactionImpl的构造逻辑,事务超时时间是传入的毫秒数加上TransactionTimer.getCurrentTime(),由于currentTime每秒才更新一次,设置500毫秒这类短超时会失去精度,实际超时时间会被向上对齐到整秒级别。
TransactionImpl(Xid xid, TransactionManagerImpl txManager, long transactionTimeoutMilliseconds) throws SystemException { this.syncList = new ArrayList(5); this.interposedSyncList = new ArrayList(3); this.resourceManagers = new LinkedList(); this.activeXaResources = new IdentityHashMap(3); this.suspendedXaResources = new IdentityHashMap(3); this.status = 6; this.resources = new HashMap(); this.txManager = txManager; this.xid = xid; this.timeout = transactionTimeoutMilliseconds + TransactionTimer.getCurrentTime(); }
实现方案
要支持小于1秒的事务超时,需要从以下几个关键点修改:
1. 提升TransactionTimer的时间更新频率
修改后台线程的休眠间隔,将1秒改为更小的数值(比如10毫秒,可根据精度需求调整),让currentTime的更新足够频繁:
// 在CurrentTime线程的run方法中修改sleep时长 try { Thread.sleep(10L); // 改为10毫秒间隔更新时间 } catch (InterruptedException var2) { ; }
2. 移除超时设置的最小限制
检查事务管理器的超时设置入口(比如TransactionManagerImpl的setTransactionTimeout方法),如果存在"最小超时为1秒"的限制逻辑,直接移除:
public void setTransactionTimeout(int seconds) throws SystemException { if (seconds < 0) { throw new SystemException("Invalid timeout"); } // 移除原有的if (seconds < 1) seconds = 1; 判断 this.defaultTimeout = seconds * 1000L; }
或者新增一个直接支持毫秒级超时的方法:
public void setTransactionTimeoutMillis(long milliseconds) throws SystemException { if (milliseconds < 0) { throw new SystemException("Invalid timeout"); } this.defaultTimeout = milliseconds; }
3. 确保超时判断逻辑的一致性
检查事务管理器中所有判断超时的逻辑,确保它们统一依赖TransactionTimer.getCurrentTime(),避免部分逻辑直接使用System.currentTimeMillis()导致的时间偏差。
4. 平衡精度与性能
更小的时间更新间隔会带来一定的线程调度开销,需要根据业务场景选择合适的间隔——比如10毫秒的间隔既能满足大部分短超时需求,又不会带来过大的性能损耗。
内容的提问来源于stack exchange,提问作者Asif Ansari
相关产品推荐
相关产品推荐

