Spring LockRegistryLeaderInitiator如何获取Leader角色信息?
获取LockRegistryLeaderInitiator上下文的角色信息(Spring Integration 5.0.5.RELEASE)
我理解你当前的场景:基于LockRegistryLeaderInitiator实现了多角色的Leader集群(scheduling1和scheduling2),但Spring Integration 5.0.5.RELEASE的LeaderContext接口并没有提供获取候选者角色的方法,没法直接通过leaderInitiator.getContext().getRole()拿到角色信息。下面是一个无需升级版本就能解决问题的自定义扩展方案:
解决方案:自定义带角色的LeaderContext和LeaderInitiator
1. 创建RoleAwareLeaderContext包装类
这个类会包装原生的LeaderContext,同时携带候选者的角色信息:
import org.springframework.integration.support.leader.LeaderContext; public class RoleAwareLeaderContext implements LeaderContext { private final LeaderContext delegate; private final String role; public RoleAwareLeaderContext(LeaderContext delegate, String role) { this.delegate = delegate; this.role = role; } @Override public void yield() { delegate.yield(); } @Override public boolean isLeader() { return delegate.isLeader(); } // 新增获取角色的方法 public String getRole() { return this.role; } }
2. 扩展LockRegistryLeaderInitiator
自定义一个子类,在创建上下文时替换为我们的RoleAwareLeaderContext,并在构造时保存候选者的角色:
import org.springframework.integration.support.leader.Candidate; import org.springframework.integration.support.leader.LockRegistry; import org.springframework.integration.support.leader.LockRegistryLeaderInitiator; public class RoleAwareLockRegistryLeaderInitiator extends LockRegistryLeaderInitiator { private final String role; public RoleAwareLockRegistryLeaderInitiator(LockRegistry locks, Candidate candidate) { super(locks, candidate); this.role = candidate.getRole(); } @Override protected LeaderContext createLeaderContext() { // 包装原生上下文,添加角色信息 LeaderContext originalContext = super.createLeaderContext(); return new RoleAwareLeaderContext(originalContext, this.role); } @Override public RoleAwareLeaderContext getContext() { // 强制转换为自定义上下文类型 return (RoleAwareLeaderContext) super.getContext(); } }
3. 修改XML配置
将原来的LockRegistryLeaderInitiator替换为我们自定义的实现类:
<bean id="scheduling1LeaderInitiator" class="com.yourpackage.RoleAwareLockRegistryLeaderInitiator"> <constructor-arg name="locks" ref="jdbcLockRegistry"/> <constructor-arg name="candidate" ref="scheduling1LeaderCandidate"/> </bean> <bean id="scheduling1LeaderCandidate" class="org.springframework.integration.leader.DefaultCandidate"> <constructor-arg name="id" value="#{T(java.util.UUID).randomUUID().toString()}"/> <constructor-arg name="role" value="scheduling1"/> </bean> <bean id="scheduling2LeaderInitiator" class="com.yourpackage.RoleAwareLockRegistryLeaderInitiator"> <constructor-arg name="locks" ref="jdbcLockRegistry"/> <constructor-arg name="candidate" ref="scheduling2LeaderCandidate"/> </bean> <bean id="scheduling2LeaderCandidate" class="org.springframework.integration.leader.DefaultCandidate"> <constructor-arg name="id" value="#{T(java.util.UUID).randomUUID().toString()}"/> <constructor-arg name="role" value="scheduling2"/> </bean>
4. 使用自定义上下文获取角色
现在你就可以像期望的那样获取角色信息了:
if (leaderInitiator.getContext().isLeader()) { String role = leaderInitiator.getContext().getRole(); // 根据角色执行对应的调度任务逻辑 }
补充说明
如果后续有机会升级Spring Integration版本,可以检查更高版本(比如5.1及以上)是否已经原生支持从LeaderContext获取角色信息,但在5.0.5.RELEASE这个版本,上述自定义扩展是最直接的解决方案。
内容的提问来源于stack exchange,提问作者Pantelis Papapoulias
相关产品推荐
相关产品推荐

