在 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()应该找到持有真正锁的线程。

谢谢,

西比·马修