1

使用 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")
    }
4

2 回答 2

1

我可以使用下面的代码模拟负载平衡。不确定这是否是正确的方法。我可以看到一次只能从集群中的一个节点获取事件日志语句。此代码在获得领导权并完成其工作后产生领导力。

@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)
    }
}
于 2018-12-22T06:37:20.457 回答
0

您的建议是滥用领导选举技术,该技术旨在在当前领导失败时进行热故障转移,在每个事件后手动让出领导是一种反模式

您可能想要的是所有轮询器都处于活动状态的竞争轮询器,但使用共享存储来防止重复处理。

例如,如果您正在轮询共享目录以获取要处理的文件,您将使用 a FileSystemPersistentFileListFilterwith a shared MetadataStore(例如 zookeeper 实现)来防止多个实例处理同一个文件。

您可以对任何轮询消息源使用相同的技术(共享元数据存储)。

于 2018-12-22T16:51:16.870 回答