如何解决获取 Infinispan 锁持有人线程
我们的集群服务器应用程序具有相当古老的 Hibernate 和 Infinispan 依赖项:
org.hibernate:hibernate-core:4.3.8.Final
org.hibernate:hibernate-infinispan:4.3.8.Final
org.infinispan:infinispan-embedded:7.2.3.Final
不幸的是,我们在客户端请求线程上遇到了以下异常:
org.infinispan.util.concurrent.TimeoutException: ISPN000299: Unable to acquire lock after 180 seconds for key <myKey> and requestor GlobalTransaction:<cluster-main1-60783>:4480123069:local. Lock is held by GlobalTransaction:<cluster-main1-60783>:4479604524:local,while request came from local
at org.infinispan.util.concurrent.locks.LockManagerImpl.lock(LockManagerImpl.java:198)
at org.infinispan.util.concurrent.locks.LockManagerImpl.acquireLock(LockManagerImpl.java:171)
at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.lockKeyAndCheckOwnership(AbstractTxLockingInterceptor.java:183)
at org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.lockAndRegisterBackupLock(AbstractTxLockingInterceptor.java:116)
at org.infinispan.interceptors.locking.OptimisticLockingInterceptor.acquireAllLocks(OptimisticLockingInterceptor.java:253)
at org.infinispan.interceptors.locking.OptimisticLockingInterceptor.visitPrepareCommand(OptimisticLockingInterceptor.java:88)
at org.infinispan.commands.tx.PrepareCommand.acceptVisitor(PrepareCommand.java:123)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:97)
at org.infinispan.interceptors.NotificationInterceptor.visitPrepareCommand(NotificationInterceptor.java:36)
at org.infinispan.commands.tx.PrepareCommand.acceptVisitor(PrepareCommand.java:123)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:97)
at org.infinispan.interceptors.TxInterceptor.invokeNextInterceptorAndVerifyTransaction(TxInterceptor.java:138)
at org.infinispan.interceptors.TxInterceptor.visitPrepareCommand(TxInterceptor.java:125)
at org.infinispan.commands.tx.PrepareCommand.acceptVisitor(PrepareCommand.java:123)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:97)
at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:111)
at org.infinispan.commands.AbstractVisitor.visitPrepareCommand(AbstractVisitor.java:123)
at org.infinispan.commands.tx.PrepareCommand.acceptVisitor(PrepareCommand.java:123)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:97)
at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:102)
at org.infinispan.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:71)
at org.infinispan.commands.AbstractVisitor.visitPrepareCommand(AbstractVisitor.java:123)
at org.infinispan.commands.tx.PrepareCommand.acceptVisitor(PrepareCommand.java:123)
at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:336)
at org.infinispan.transaction.impl.TransactionCoordinator.prepare(TransactionCoordinator.java:121)
at org.infinispan.transaction.impl.TransactionCoordinator.prepare(TransactionCoordinator.java:104)
at org.infinispan.transaction.synchronization.SynchronizationAdapter.beforeCompletion(SynchronizationAdapter.java:44)
at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:543)
at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:241)
at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:183)
at org.hibernate.engine.transaction.internal.jta.JtaTransaction.doCommit(JtaTransaction.java:152)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
...
有没有办法找出哪个线程持有获取的锁?
解决方法
Infinispan 锁应该在事务的发起者是远程节点时工作,或者当应用程序挂起事务并在另一个线程上恢复它时,所以锁与事务相关联,而不是与线程相关联。
因此,查找哪个线程启动了持有特定密钥的事务的唯一方法是提前启用跟踪日志记录,例如org.infinispan.util.concurrent.locks.LockManagerImpl
。
除了 Dan 的回答之外,我们还使用了类似于以下代码的内容来确定异常消息中的关键是什么以及我们应该寻找哪个缓存:
import org.infinispan.Cache;
import org.infinispan.cache.impl.CacheImpl;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.util.concurrent.locks.LockManager;
import java.util.Set;
import java.util.TreeSet;
EmbeddedCacheManager cacheManager = ...
setAccessibility(true);
StringBuilder result = new StringBuilder();
Set cacheNames = new TreeSet(cacheManager.getCacheNames());
for (String cacheName: cacheNames) {
boolean createIfAbsent = false;
Cache cache = cacheManager.getCache(cacheName,createIfAbsent);
if (cache instanceof CacheImpl) {
CacheImpl cacheImpl = (CacheImpl) cache;
LockManager lockManager = cacheImpl.getLockManager();
if (lockManager.getNumberOfLocksHeld() == 0) {
continue;
}
result.append("cache: ").append(cacheName).append("\n");
result.append(" held: ").append(lockManager.getNumberOfLocksHeld()).append("\n");
result.append(" available: ").append(lockManager.getNumberOfLocksAvailable()).append("\n");
result.append(" concurrency level: ").append(lockManager.getConcurrencyLevel()).append("\n");
result.append(" lock container: ").append(lockManager.lockContainer.getClass()).append("\n");
result.append(" ").append(lockManager.printLockInfo());
result.append("\n\n");
} else {
result.append("cache: ").append(cacheName).append("\n");
result.append(" unknown cache type (template?): ").append(cache).append("\n");
result.append("\n\n");
}
}
return result.toString();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。