INT-4058: Add leader initiator for lock registry
JIRA: https://jira.spring.io/browse/INT-4058 If you hold the lock, you are the leader. This simple idea gets you a long way if there is no "native" leader initiator. E.g. you can use this with a RDBMS with JdbcLockRegistry. Add some docs on leader election under "endpoints" Make thread name for leader initiator unique In case there are multiple instances in the same context we would like to be able to spot them in the logs. INT-4058: Polishing * Code refactoring in the `LockRegistryLeaderInitiator`: SI use 120 line length * Add `Assert.notNull()` for required properties * Add `this.lock.unlock()` and `Thread.sleep(LockRegistryLeaderInitiator.this.busyWaitMillis)` into the `catch` block to let distributed elections to work. Otherwise there is a big chance that we will acquire the lock and become a leader again just after `yield()` * Change `LockContext.toString()` to use simple `String` concatenation which is optimized by compiler to the `StringBuilder`. That let to have some better micro-performance compared with with extra `Formatter` object in case of `String.format()` * Add `JdbcLockRegistryLeaderInitiatorTests` * Fix `yield()` logic based on the `Future.cancel(true)`. Since one `FutureTask.cancel(true)` makes it as `INTERRUPTED` any subsequent `yield()` does not make any effect, therefore our infinite selector loop isn't interrupted one more time. * Reschedule the `LeaderSelector` in the `yield()` after cancel(true). * Rework `catch` in the selector loop just to the `InterruptedException` and `return null;` to stop looping and let reschedule the selector. * Add one more `onRevoked` logic into the `final` of the selector loop to notify that we have lost leadership during `stop()` * Improve `JdbcLockRegistryLeaderInitiatorTests` to ensure that several `yield()` on the same initiator work well. * Add `What's New` note.
This commit is contained in:
@@ -37,7 +37,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Patrick Peralta
|
||||
* @author Janne Valkealahti
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class LeaderInitiator implements SmartLifecycle {
|
||||
|
||||
@@ -68,7 +68,7 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
private volatile boolean autoStartup = true;
|
||||
|
||||
/**
|
||||
* @See SmartLifecycle which is an extension of org.springframework.context.Phased
|
||||
* @see SmartLifecycle which is an extension of org.springframework.context.Phased
|
||||
*/
|
||||
private volatile int phase;
|
||||
|
||||
@@ -214,7 +214,7 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
/**
|
||||
* Implementation of Curator leadership election listener.
|
||||
*/
|
||||
class LeaderListener extends LeaderSelectorListenerAdapter {
|
||||
protected class LeaderListener extends LeaderSelectorListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void takeLeadership(CuratorFramework framework) throws Exception {
|
||||
@@ -223,7 +223,8 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
try {
|
||||
LeaderInitiator.this.candidate.onGranted(context);
|
||||
if (LeaderInitiator.this.leaderEventPublisher != null) {
|
||||
LeaderInitiator.this.leaderEventPublisher.publishOnGranted(LeaderInitiator.this, context, LeaderInitiator.this.candidate.getRole());
|
||||
LeaderInitiator.this.leaderEventPublisher.publishOnGranted(LeaderInitiator.this, context,
|
||||
LeaderInitiator.this.candidate.getRole());
|
||||
}
|
||||
|
||||
// when this method exits, the leadership will be revoked;
|
||||
@@ -239,7 +240,8 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
finally {
|
||||
LeaderInitiator.this.candidate.onRevoked(context);
|
||||
if (LeaderInitiator.this.leaderEventPublisher != null) {
|
||||
LeaderInitiator.this.leaderEventPublisher.publishOnRevoked(LeaderInitiator.this, context, LeaderInitiator.this.candidate.getRole());
|
||||
LeaderInitiator.this.leaderEventPublisher.publishOnRevoked(LeaderInitiator.this, context,
|
||||
LeaderInitiator.this.candidate.getRole());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,7 +250,7 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
/**
|
||||
* Implementation of leadership context backed by Curator.
|
||||
*/
|
||||
class CuratorContext implements Context {
|
||||
private class CuratorContext implements Context {
|
||||
|
||||
@Override
|
||||
public boolean isLeader() {
|
||||
@@ -262,8 +264,9 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("CuratorContext{role=%s, id=%s, isLeader=%s}",
|
||||
LeaderInitiator.this.candidate.getRole(), LeaderInitiator.this.candidate.getId(), isLeader());
|
||||
return "LockContext{role=" + LeaderInitiator.this.candidate.getRole() +
|
||||
", id=" + LeaderInitiator.this.candidate.getId() +
|
||||
", isLeader=" + isLeader() + "}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user