【小白入坑kafka】

项目场景:

最近公司做了一个小服务,说的是需求能够支持2万人使用,然后并发的话我们这边要做到1000。有些地方就使用了kafka。


问题描述

项目集成了kafka,上了生产环境之后。我们在测并发的时候,运维反馈只有一个服务节点在打印这个日志(kafka消费数据的日志)。 环境是这样的kafka是集群三个节点,应用部署了三个节点,按照理想情况三个服务节点都应该在打印消费消息的日志。
下面是我集成kafka的配置和代码,除了下面的代码和pom项目里面就没有其他的代码了

配置如下

spring.kafka.bootstrap-servers=192.168.XXXX
#=============== provider  =========
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.acks=all
#=============== consumer  ========
spring.kafka.consumer.group-id=test-01
spring.kafka.consumer.enable-auto-commit=true
spring.kafka.consumer.auto-commit-interval=100
spring.kafka.listener.concurrency=10
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer

生产者代码


@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, 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());
    }
} 

各位铁汁看到这儿有没有看到啥问题捏!!!

原因分析:

然后我就按照以下几点依次做了分析(我也不熟悉kafka,但是也用过)

  1. 服务器有三个节点,按照我的惯性思维就有三个消费者,难道请求都打到一个生产上去了?
    在生产者上加了日志,发现三个服务节点都在生产消息,排除掉该问题

  2. 确认生产消息的时候是否只写到一个分区了。
    看了生产消息代码,发现没有传key,并且写入分区使用的也是默认分区,看一下写默认写入分区的策略:

      public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, 
      Cluster cluster, int numPartitions) {
    		return keyBytes == null ? this.stickyPartitionCache.partition(topic, cluster) :   
    		Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
    }
    
    

    可以确认默认的分区策略不是一直写入到同一个分区(前提是有多个分区)

  3. 是不是可利用的分区只有一个
    加了打印当前可利用的分区数量,发现只有一个分区。。。。。。。。。

  4. 代码问题,配置问题
    spring.kafka.bootstrap-servers=
    spring.kafka.producer.key-serializer= org.apache.kafka.common.serialization.StringSerializer
    spring.kafka.producer.value-serializer= org.apache.kafka.common.serialization.StringSerializer
    spring.kafka.producer.properties.partitioner.class = org.apache.kafka.clients.producer.internals.DefaultPartitioner
    spring.kafka.consumer.group-id= zhtj
    spring.kafka.consumer.enable-auto-commit= true
    spring.kafka.consumer.auto-commit-interval= 1000
    spring.kafka.consumer.key-deserializer= org.apache.kafka.common.serialization.StringDeserializer
    spring.kafka.consumer.value-deserializer= org.apache.kafka.common.serialization.StringDeserializer
    #当前节点消费者数量
    spring.kafka.listener.concurrency=10
    也没发现配置里面有配置分区的,然后就百度如何配置分区数量,代码如下

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

    再次测试各服务器节点的消费者就正常消费数据了


解决方案:设置了主题的分区数量,就生效了

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不务专业的程序员--阿飞

兄弟们能否给口饭吃

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值