Java Spring LockRegistryLeaderInitiator在某些锁注册表实现中调用过多
我目前正在使用LockRegistryLeaderInitiator:Java Spring LockRegistryLeaderInitiator在某些锁注册表实现中调用过多,java,spring,spring-integration,Java,Spring,Spring Integration,我目前正在使用LockRegistryLeaderInitiator: org.springframework.integration.support.leader.LockRegistryLeaderInitiator 以及jdbclock注册表: org.springframework.integration.jdbc.lock.JdbcLockRegistry 我发现一个问题,非领导者节点每100毫秒调用一次数据库 我想我能看到发生了什么。当锁未保持时,先导启动器进入紧循环: while
org.springframework.integration.support.leader.LockRegistryLeaderInitiator
以及jdbclock注册表:
org.springframework.integration.jdbc.lock.JdbcLockRegistry
我发现一个问题,非领导者节点每100毫秒调用一次数据库
我想我能看到发生了什么。当锁未保持时,先导启动器进入紧循环:
while (isRunning()) {
...
// We always try to acquire the lock, in case it expired
boolean acquired = this.lock.tryLock(LockRegistryLeaderInitiator.this.heartBeatMillis,
TimeUnit.MILLISECONDS);
if (!this.locked) {
if (acquired) {
// Success: we are now leader
this.locked = true;
handleGranted();
}
else if (isPublishFailedEvents()) {
publishFailedToAcquire();
}
}
...
}
如果无法获得锁,tryLock(…)
调用的超时通过阻塞一个心跳周期来控制此代码循环的速度
问题发生在某些LockRegistry实现中tryLock的编写方式上。以JdbcLockRegistry为例:
while (true) {
try {
while (!(acquired = doLock()) && System.currentTimeMillis() < expire) { //NOSONAR
Thread.sleep(100); //NOSONAR
}
...
}
...
}
这种行为是设计的还是bug
编辑:
LockRegistryLeaderInitiator有两个配置属性来控制选择的响应:
/**
* Time in milliseconds to wait in between attempts to re-acquire the lock, once it is
* held. The heartbeat time has to be less than the remote lock expiry period, if
* there is one, otherwise other nodes can steal the lock while we are sleeping here.
* If the remote lock does not expire, or if you know it interrupts the current thread
* when it expires or is broken, then you can extend the heartbeat to Long.MAX_VALUE.
*/
private long heartBeatMillis = DEFAULT_HEART_BEAT_TIME;
/**
* Time in milliseconds to wait in between attempts to acquire the lock, if it is not
* held. The longer this is, the longer the system can be leaderless, if the leader
* dies. If a leader dies without releasing its lock, the system might still have to
* wait for the old lock to expire, but after that it should not have to wait longer
* than the busy wait time to get a new leader. If the remote lock does not expire, or
* if you know it interrupts the current thread when it expires or is broken, then you
* can reduce the busy wait to zero.
*/
private long busyWaitMillis = DEFAULT_BUSY_WAIT_TIME;
…当锁未被持有时,似乎应该涉及busyWaitMillis,但无法获取,但在这种情况下,似乎没有使用它。我可以看出,有一个理由支持配置它;但这是响应能力和数据库活动之间的权衡。如果延迟时间太长,您可能永远得不到锁 就个人而言,我不喜欢这种实现,尤其是JDBC 您可以随意打开一个窗口,使睡眠可配置 欢迎捐款
/**
* Time in milliseconds to wait in between attempts to re-acquire the lock, once it is
* held. The heartbeat time has to be less than the remote lock expiry period, if
* there is one, otherwise other nodes can steal the lock while we are sleeping here.
* If the remote lock does not expire, or if you know it interrupts the current thread
* when it expires or is broken, then you can extend the heartbeat to Long.MAX_VALUE.
*/
private long heartBeatMillis = DEFAULT_HEART_BEAT_TIME;
/**
* Time in milliseconds to wait in between attempts to acquire the lock, if it is not
* held. The longer this is, the longer the system can be leaderless, if the leader
* dies. If a leader dies without releasing its lock, the system might still have to
* wait for the old lock to expire, but after that it should not have to wait longer
* than the busy wait time to get a new leader. If the remote lock does not expire, or
* if you know it interrupts the current thread when it expires or is broken, then you
* can reduce the busy wait to zero.
*/
private long busyWaitMillis = DEFAULT_BUSY_WAIT_TIME;