三个服务服务器,只有一个服务在消费kafka消息

99 阅读2分钟

问题描述:最近一个项目集成了kafka,今天上了生产环境,运维看了日志消息的消费日志只有一个服务在打印。 环境是这样的kafka是集群三个节点,应用部署了三个节点,按照理想情况三个服务节点都应该在消费消息。 u=3134620258,3551490673&fm=253&fmt=auto&app=138&f=PNG.webp
除了kafka配置,消费者和生产者代码如下

生产者:


@Component
public class KafkaPrducer {
    private static final Logger log = LoggerFactory.getLogger(KafkaPrducer.class);
    public static final String TOPIC_TEST = "tj_test_1";
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Autowired
    AdminClient adminClient;
    public void send(Object obj) {
        String obj2String = JSONObject.toJSONString(obj);
        log.info("准备发送消息为:{}", obj2String);
        //发送消息
        String key = UUID.randomUUID().toString();
        ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(TOPIC_TEST,null, obj2String);

        future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
            @Override
            public void onFailure(Throwable throwable) {
                //发送失败的处理
                log.info(TOPIC_TEST + " - 生产者 发送消息失败:" + throwable.getMessage());
            }

            @Override
            public void onSuccess(SendResult<String, String> stringObjectSendResult) {
                //成功的处理
                log.info(TOPIC_TEST + " - 生产者 发送消息成功:" + stringObjectSendResult.toString());
            }
        });
        DescribeTopicsResult describeTopicsResult = adminClient.describeTopics(Arrays.asList(TOPIC_TEST));
        System.out.println(describeTopicsResult);
    }


消费者:

public class KafkaConsumer {

    private static final Logger log = LoggerFactory.getLogger(KafkaConsumer.class);

    @KafkaListener(topics = "tj_test_1")
    public void consumerMsg(ConsumerRecord<String, String> record){
        log.info("key:{}",record.key());
        log.info("value:{}",record.value());
        String value = record.value();
        record.headers();
        Person p = JSONObject.parseObject(value, Person.class);
        record.partition();
        log.info(p.toString());
    }
} 

排查思路

  • 是不是生产消息只有一个服务节点在生产,接口的负载均衡有问题,接口全都映射到了一个节点
    在生产者主体加了日志,发现三个服务器均在生产日志,排除此问题。生产者写入分区策略关键代码
public interface Partitioner extends Configurable, Closeable {
  // 分区写入策略就是这个接口的实现类了。
  int partition(String var1, Object var2, byte[] var3, Object var4, byte[] var5, Cluster var6);

  void close();

  default void onNewBatch(String topic, Cluster cluster, int prevPartition) {
  }
  • 是不是可利用的分区只有一个
    在消费消费的时候打印了分区名称(record.partition()),发现都是读取的partion 0 ,并且确定了生产200条消息,也消费了200条消息,说明生产消息的时候,全是写到额一个分区

  • 代码写法问题,需要指定分区数量吗
    百度了好几篇文章终于找到了,配置topic时候需要指定分区数量,配置之后就好了

@Bean
public NewTopic topicinfo() {
  // 创建topic,需要指定创建的topic的"名称"、"分区数"、"副本数量(副本数数目的值要小于等于Broker数量)"
  return new NewTopic(KafkaPrducer.TOPIC_TEST.toString(), 3, (short) 1);
}