Apache kafka 卡夫卡-并非所有消费者都收到订阅的消息

Apache kafka 卡夫卡-并非所有消费者都收到订阅的消息,apache-kafka,partition,consumer,Apache Kafka,Partition,Consumer,要使用Kafka发布消息,我将使用类名作为主题: kafkaProducer.send(new ProducerRecord(object.getClass().getName(), new DomainObjectAdapter(object).toJsonString())); 消费者订阅他们感兴趣的课程: for(Object sub:_subscriptions) topics.add(sub.getClass().getName()); _kafkaC

要使用Kafka发布消息,我将使用类名作为主题:

kafkaProducer.send(new ProducerRecord(object.getClass().getName(), new DomainObjectAdapter(object).toJsonString()));
消费者订阅他们感兴趣的课程:

    for(Object sub:_subscriptions)
        topics.add(sub.getClass().getName());
    _kafkaConsumer.subscribe(topics);
问题是,只有一个消费者曾经收到订阅的消息。我的理解是kafka将为每个订阅者分配一个唯一的分区(如果可用)。我目前只有2个订阅服务器,我的kafka server.properties指定了4个分区。似乎所有使用者都在从同一分区读取数据。也许卡夫卡是一个糟糕的选择服务巴士由于这种明显的限制。任何帮助都将不胜感激

卡夫卡消费物业:

    properties.put("bootstrap.servers", _settings.getEndpoint());
    properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("enable.auto.commit", "false");
    properties.put("group.id", "TestGroup");
    properties.put("auto.offset.reset","earliest");
    properties.put("bootstrap.servers",_settings.getEndpoint());
    properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
num.partitions=4
卡夫卡制作人酒店:

    properties.put("bootstrap.servers", _settings.getEndpoint());
    properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("enable.auto.commit", "false");
    properties.put("group.id", "TestGroup");
    properties.put("auto.offset.reset","earliest");
    properties.put("bootstrap.servers",_settings.getEndpoint());
    properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
num.partitions=4
服务器属性我唯一更改的是默认属性:

    properties.put("bootstrap.servers", _settings.getEndpoint());
    properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("enable.auto.commit", "false");
    properties.put("group.id", "TestGroup");
    properties.put("auto.offset.reset","earliest");
    properties.put("bootstrap.servers",_settings.getEndpoint());
    properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
num.partitions=4
注意:我还尝试了以下消费者设置:

    properties.put("bootstrap.servers", _settings.getEndpoint());
    properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    properties.put("auto.commit.interval.ms","1000");
    properties.put("enable.auto.commit", "true");
    properties.put("group.id", "testGroup");
    properties.put("auto.offset.reset","latest");
    properties.put("partition.assignment.strategy", "org.apache.kafka.clients.consumer.RoundRobinAssignor");
卡夫卡默认使用as分区分配策略,该策略具有以下特点:

范围赋值器以每个主题为基础工作。对于每个主题,我们都会 按数字顺序输出可用分区,并在中输出使用者 词典顺序。然后,我们将分区数除以 用于确定要访问的分区数的使用者总数 分配给每个消费者。如果它不能平均分配,那么第一个 很少有消费者会有一个额外的分区。例如,假设 有两个消费者C0和C1,两个主题t0和t1,每个主题 topic有3个分区,导致了分区t0p0、t0p1、t0p2, t1p0、t1p1和t1p2。作业将是:C0:[t0p0,t0p1,t1p0, t1p1]C1:[t0p2,t1p2]

如果希望为少量分区提供更均匀的分布,可以使用 通过设置partition.assignment.strategy

卡夫卡默认使用作为分区分配策略,具有以下特点:

范围赋值器以每个主题为基础工作。对于每个主题,我们都会 按数字顺序输出可用分区,并在中输出使用者 词典顺序。然后,我们将分区数除以 用于确定要访问的分区数的使用者总数 分配给每个消费者。如果它不能平均分配,那么第一个 很少有消费者会有一个额外的分区。例如,假设 有两个消费者C0和C1,两个主题t0和t1,每个主题 topic有3个分区,导致了分区t0p0、t0p1、t0p2, t1p0、t1p1和t1p2。作业将是:C0:[t0p0,t0p1,t1p0, t1p1]C1:[t0p2,t1p2]

如果希望为少量分区提供更均匀的分布,可以使用
通过设置partition.assignment.strategy

如果您的所有消费者都具有相同的消费者组group.id属性,则该组中只有一个消费者会收到消息。如果您希望所有消费者都能收到该消息,则他们需要具有不同的group.id

要检查哪些使用者绑定到主题的分区,可以使用以下命令

./bin/kafka-consumer-groups.sh --bootstrap-server yourhost:9092 --group testGroup --describe

如果您的所有消费者都具有相同的消费者组group.id属性,则该组中只有一个消费者将收到该消息。如果您希望所有消费者都能收到该消息,则他们需要具有不同的group.id

要检查哪些使用者绑定到主题的分区,可以使用以下命令

./bin/kafka-consumer-groups.sh --bootstrap-server yourhost:9092 --group testGroup --describe

RangeAssignor听起来像我想要的,但是,我将尝试使用RoundRobinAsignor。我将partition.assignment.strategy=org.apache.kafka.clients.consumer.RoundRobinAsignor添加到server.properties文件中,但它对我的问题没有影响。也就是说,只有一个订阅者收到发布的消息。为了让所有阅读本文的人都清楚,senseiwu建议的解决方案对我不起作用。partition.assignment.strategy=org.apache.kafka.clients.consumer.RoundRobinAssignor是一个消费者配置。不确定在server.properties中设置是否有效从未尝试过这种方法如果即使在将其用作使用者配置后也不起作用,请共享更多信息,例如实际中有多少主题-应该可以根据文档找出问题所在。在最坏的情况下,您也可以考虑StyKyAdvor或自定义分区器。RangeAddior听起来像我想要的,但是,我会尝试使用RooDoRunBealor。我添加了Sale.Dealial.Orth.Orj.KAFKA.clits.Cuffel.RooDoRunBoePoto到Server属性文件,它对我的问题没有影响。也就是说,只有一个订阅者收到发布的消息。为了让所有阅读本文的人都清楚,senseiwu建议的解决方案对我不起作用。partition.assignment.strategy=org.apache.kafka.clients.consumer.RoundRobinAssignor是一个消费者配置。不确定在server.properties中设置是否有效从未尝试过这种方法如果即使在将其用作使用者配置后也不起作用,请共享更多信息,例如实际中有多少主题-应该可以计算出接下来会发生什么
这是基于文件的。在最坏的情况下,你也可以考虑StyKyAdvor或自定义分区器。SunsiiWu提供的建议不起作用,如果其他人有任何其他建议,我将非常感激。也许Kafka不适合通用消息传递总线?您确定您有4个分区吗?你能描述一个主题来检查它吗:bin/kafka-topics.sh-descripe-bootstrap server localhost:9092-topic MY_topic_NAME?senseiwu提供的建议无效,如果其他人有任何其他建议,我将不胜感激!也许Kafka不适合通用消息传递总线?您确定您有4个分区吗?你能描述一个主题来检查它吗:bin/kafka-topics.sh-descripe-bootstrap服务器localhost:9092-topic MY_topic_NAME?这很有效!对于希望成为消息广播收件人的消费者,我确保组ID对于他们的订阅是唯一的。谢谢这成功了!对于希望成为消息广播收件人的消费者,我确保组ID对于他们的订阅是唯一的。谢谢