繁体   English   中英

为什么我的具有相同组ID的Kafka消费者没有得到平衡?

[英]Why my Kafka consumers with same group id are not being balanced?

我正在编写一个概念证明应用程序,以使用来自Apache Kafka 0.9.0.0的消息,并查看由于Kafka提供的好处,我是否可以代替普通的JMS消息代理来使用它。 这是我的基本代码,使用新的使用者API:

public class Main implements Runnable {

    public static final long DEFAULT_POLL_TIME = 300;
    public static final String DEFAULT_GROUP_ID = "ltmjTest";

    volatile boolean keepRunning = true;
    private KafkaConsumer<String, Object> consumer;
    private String servers;
    private String groupId = DEFAULT_GROUP_ID;
    private long pollTime = DEFAULT_POLL_TIME;
    private String[] topics;

    public Main() {
    }

    //getters and setters...

    public void createConsumer() {
        Map<String, Object> configs = new HashMap<>();
        configs.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
        configs.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);

        configs.put("enable.auto.commit", "true");
        configs.put("auto.commit.interval.ms", "1000");
        configs.put("session.timeout.ms", "30000");

        configs.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        configs.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        consumer = new KafkaConsumer<>(configs);
        consumer.subscribe(asList(topics));
    }

    public static void main(String[] args) {
        Main main = new Main();
        if (args != null && args.length > 0) {
            for (String arg : args) {
                String[] realArg = arg.trim().split("=", 2);
                String argKey = realArg[0].toLowerCase();
                String argValue = realArg[1];
                switch (argKey) {
                case "polltime":
                    main.setPollTime(Long.parseLong(argValue));
                    break;
                case "groupid":
                    main.setGroupId(argValue);
                    break;
                case "servers":
                    main.setServers(argValue);
                    break;
                case "topics":
                    main.setTopics(argValue.split(","));
                    break;
            }
        }
        main.createConsumer();
        new Thread(main).start();
        try (Scanner scanner = new Scanner(System.in)) {
            while(true) {
                String line = scanner.nextLine();
                if (line.equals("stop")) {
                    main.setKeepRunning(false);
                    break;
                }
            }
        }
    }
}

我已经使用默认设置启动了一个kafka服务器,并使用了shell工具kafka-console-producer.sh启动了一个kafka生产者,以将消息写入我的主题。 然后,我使用此代码与两个使用者进行连接,发送适当的服务器进行连接并进行主题订阅,其他所有内容均具有默认值,这意味着两个使用者都具有相同的组ID。 我注意到, 只有我的一个消费者使用了所有数据。 官方教程中 ,我已经读到默认行为应该是消费者必须由服务器平衡:

如果所有使用者实例都具有相同的使用者组,则这就像在使用者上使用传统队列平衡负载一样。

如何修复使用者的行为使其类似于默认行为? 还是我想念什么?

有一个特征kafka.consumer.PartitionAssignor,它说明应如何为每个使用者分配分区。 它有两个实现:RoundRobinAssignor和RangeAssignor。 默认值是RangeAssignor。

可以通过设置参数“ partition.assignment.strategy”来更改。

Round Robin文档:

循环分配器对所有可用分区和所有可用使用者进行布局。 然后,它继续进行从分区到使用者的循环分配。 如果所有使用者实例的订阅都相同,则分区将均匀分布。 (即,分区拥有者计数将在所有使用者中的一个增量之内。)例如,假设有两个使用者C0和C1,两个主题t0和t1,并且每个主题都有3个分区,从而得出分区t0p0, t0p1,t0p2,t1p0,t1p1和t1p2。 分配为:C0:[t0p0,t0p2,t1p1] C1:[t0p1,t1p0,t1p2]

范围分配器文档

范围分配器基于每个主题工作。 对于每个主题,我们以数字顺序排列可用分区,并以字典顺序排列使用者。 然后,我们将分区数除以使用者总数,以确定分配给每个使用者的分区数。 如果它没有均匀划分,那么前几个消费者将有一个额外的划分。 例如,假设有两个使用者C0和C1,两个主题t0和t1,并且每个主题都有3个分区,从而得出分区t0p0,t0p1,t0p2,t1p0,t1p1和t1p2。 分配为:C0:[t0p0,t0p1,t1p0,t1p1] C1:[t0p2,t1p2]

因此,如果我们所有主题都只有一个分区,那么只有一个使用者可以工作

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM