使用spring集成和Zookeeper,可以实现领导者执行诸如轮询之类的活动。
但是我们如何将领导者责任分配给集群中的所有节点以实现负载平衡?
给出以下代码,一旦应用程序启动,我就会看到同一节点正在维护领导者角色并获取事件。我想将此活动分配给群集中的每个节点,以实现更好的负载平衡。
有什么办法可以安排集群中的每个节点来获得领导权并以循环方式撤销?
@Bean
public LeaderInitiatorFactoryBean fooLeaderInitiator(CuratorFramework client) {
new LeaderInitiatorFactoryBean()
.setClient(client)
.setPath("/foofeed")
.setRole("foo");
}
@Bean
@InboundChannelAdapter(channel = "fooIncomingEvents", autoStartup = "false", poller = @Poller(fixedDelay = "5000"))
@Role("foo")
public FooTriggerMessageSource fooInboundChannelAdapter() {
new FooMessageSource("foo")
}
答案 0 :(得分:1)
我可以使用以下代码模拟负载平衡。不知道这是否是正确的方法。我只能一次从集群中的一个节点看到 fetching events 日志语句。该代码在获得领导和履行职责后才能产生领导作用。
@Bean
public LeaderInitiator fooLeaderInitiator(CuratorFramework client,
FooPollingCandidate fooPollingCandidate) {
LeaderInitiator leader = new LeaderInitiator(client, fooPollingCandidate, zooKeeperNamespace)
leader.start()
leader
}
@Component
class FooPollingCandidate extends DefaultCandidate {
final Logger log = LoggerFactory.getLogger(this.getClass());
FooPollingCandidate() {
super("fooPoller", "foo")
}
@Override
void onGranted(Context ctx) {
log.debug("Leadership granted {}", ctx)
pullEvents()
ctx.yield();
}
@Override
void onRevoked(Context ctx) {
log.debug("Leadership revoked")
}
@Override
void yieldLeadership() {
log.debug("yielding Leadership")
}
//pull events and drop them on any channel needed
void pullEvents() {
log.debug("fetching events")
//simulate delay
sleep(5000)
}
}
答案 1 :(得分:0)
您的建议是滥用领导者选举技术,该技术旨在在当前领导者发生故障时进行热故障切换,并在每个事件都是反模式之后手动放弃领导力
您可能想要的是竞争性轮询器,其中所有轮询器均处于活动状态,但使用共享存储来防止重复处理。
例如,如果要轮询共享目录以处理文件,则可以将FileSystemPersistentFileListFilter
与共享的MetadataStore
(例如zookeeper实现)一起使用,以防止多个实例对同一文件进行处理文件。
您可以对任何轮询的消息源使用相同的技术(共享元数据存储)。