在 Liferay 集群中处理并发
Handling concurrency in Liferay Cluster
我在 LR 6.2 CE GA4 集群环境中工作。
2 个节点通过 portal-ext 集群配置共享同一个数据库和共享缓存。
我有一个调度程序,每 15 分钟调用一次方法 processMe(),用户单击页面时也可以调用该方法。
我的要求是限制对该方法的并发调用。
我知道由于不同的 JVM,同步块将无法工作。
我可以从 Liferay 中重用 OOTB 吗?
我可以重用 JGroups Unicast/Multicast 通信中的内容吗?
还有其他建议吗?
在 liferay 论坛上发表: https://web.liferay.com/community/forums/-/message_boards/message/74168121
谢谢,
西比·马修
参考方法后找到解决方案:com.liferay.portal.kernel.backgroundtask.SerialBackgroundTaskExecutor.acquireLock()
这是代码:
@Override
public BackgroundTaskResult execute(BackgroundTask backgroundTask)
throws Exception {
Lock lock = null;
String owner =
backgroundTask.getName() + StringPool.POUND +
backgroundTask.getBackgroundTaskId();
try {
if (isSerial()) {
lock = acquireLock(backgroundTask, owner);
}
BackgroundTaskExecutor backgroundTaskExecutor =
getBackgroundTaskExecutor();
return backgroundTaskExecutor.execute(backgroundTask);
}
finally {
if (lock != null) {
LockLocalServiceUtil.unlock(
BackgroundTaskExecutor.class.getName(),
backgroundTask.getTaskExecutorClassName(), owner);
}
}
}
protected Lock acquireLock(BackgroundTask backgroundTask, String owner)
throws DuplicateLockException {
Lock lock = null;
while (true) {
try {
lock = LockLocalServiceUtil.lock(
BackgroundTaskExecutor.class.getName(),
backgroundTask.getTaskExecutorClassName(), owner);
break;
}
catch (SystemException se) {
if (_log.isDebugEnabled()) {
_log.debug("Unable to acquire acquiring lock", se);
}
try {
Thread.sleep(50);
}
catch (InterruptedException ie) {
}
}
}
if (!lock.isNew()) {
throw new DuplicateLockException(lock);
}
return lock;
}
我的代码的主要变化是检查
if (!lock.isNew()) {
throw new DuplicateLockException(lock);
}
基本上,即使两个线程能够调用 lock() 方法(我通过同时触发两个调度程序进行测试),也只有一个线程会成功创建新对象,而另一个线程只会获取现有的锁对象。
因此lock.isNew()应该找到持有真正锁的线程。
谢谢,
西比·马修
我在 LR 6.2 CE GA4 集群环境中工作。 2 个节点通过 portal-ext 集群配置共享同一个数据库和共享缓存。
我有一个调度程序,每 15 分钟调用一次方法 processMe(),用户单击页面时也可以调用该方法。
我的要求是限制对该方法的并发调用。 我知道由于不同的 JVM,同步块将无法工作。
我可以从 Liferay 中重用 OOTB 吗? 我可以重用 JGroups Unicast/Multicast 通信中的内容吗?
还有其他建议吗?
在 liferay 论坛上发表: https://web.liferay.com/community/forums/-/message_boards/message/74168121
谢谢,
西比·马修
参考方法后找到解决方案:com.liferay.portal.kernel.backgroundtask.SerialBackgroundTaskExecutor.acquireLock()
这是代码:
@Override
public BackgroundTaskResult execute(BackgroundTask backgroundTask)
throws Exception {
Lock lock = null;
String owner =
backgroundTask.getName() + StringPool.POUND +
backgroundTask.getBackgroundTaskId();
try {
if (isSerial()) {
lock = acquireLock(backgroundTask, owner);
}
BackgroundTaskExecutor backgroundTaskExecutor =
getBackgroundTaskExecutor();
return backgroundTaskExecutor.execute(backgroundTask);
}
finally {
if (lock != null) {
LockLocalServiceUtil.unlock(
BackgroundTaskExecutor.class.getName(),
backgroundTask.getTaskExecutorClassName(), owner);
}
}
}
protected Lock acquireLock(BackgroundTask backgroundTask, String owner)
throws DuplicateLockException {
Lock lock = null;
while (true) {
try {
lock = LockLocalServiceUtil.lock(
BackgroundTaskExecutor.class.getName(),
backgroundTask.getTaskExecutorClassName(), owner);
break;
}
catch (SystemException se) {
if (_log.isDebugEnabled()) {
_log.debug("Unable to acquire acquiring lock", se);
}
try {
Thread.sleep(50);
}
catch (InterruptedException ie) {
}
}
}
if (!lock.isNew()) {
throw new DuplicateLockException(lock);
}
return lock;
}
我的代码的主要变化是检查
if (!lock.isNew()) {
throw new DuplicateLockException(lock);
}
基本上,即使两个线程能够调用 lock() 方法(我通过同时触发两个调度程序进行测试),也只有一个线程会成功创建新对象,而另一个线程只会获取现有的锁对象。
因此lock.isNew()应该找到持有真正锁的线程。
谢谢,
西比·马修