当前位置:   article > 正文

springboot集成kafka的相关配置及自定义_spring kafka producer bootstrap-servers

spring kafka producer bootstrap-servers

之前的文章末尾,简单的实现了springboot集成kafka,完成了简单的测试,今天我们来扩展一下相关内容。

首先详解一下配置文件的内容:

  1. spring:
  2. kafka:
  3. # 指定 kafka 地址,我这里部署在的虚拟机,开发环境是Windows,kafkahost是虚拟机的地址, 若外网地址,注意修改为外网的IP( 集群部署需用逗号分隔)
  4. producer:
  5. bootstrap-servers: 124.223.205.125:9092
  6. # 发生错误后,消息重发的次数。
  7. retries: 3
  8. #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
  9. batch-size: 16384
  10. # 设置生产者内存缓冲区的大小。
  11. buffer-memory: 33554432
  12. # 指定消息key和消息体的序列化方式
  13. key-deserializer: org.apache.kafka.common.serialization.StringSerializer
  14. value-deserializer: org.apache.kafka.common.serialization.StringSerializer
  15. acks: all
  16. properties:
  17. # 自定义生产者拦截器
  18. interceptor.classes: com.volga.kafka.interceptor.ProducerPrefixInterceptor
  19. consumer:
  20. enable-auto-commit: false #手动提交
  21. bootstrap-servers: ${spring.kafka.producer.bootstrap-servers}
  22. # 指定 group_id
  23. group-id: group_id
  24. # Kafka中没有初始偏移或如果当前偏移在服务器上不再存在时,默认区最新 ,有三个选项 【latest, earliest, none】
  25. auto-offset-reset: earliest
  26. # 指定消息key和消息体的序列化方式
  27. key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
  28. value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
  29. properties:
  30. # 自定义消费者拦截器
  31. interceptor.classes: com.volga.kafka.interceptor.ConsumerPrefixInterceptor
  32. # 默认主题
  33. topic: my-topic
  34. listener:
  35. # 在侦听器容器中运行的线程数。
  36. concurrency: 5
  37. #listner负责ack,每调用一次,就立即commit
  38. ack-mode: manual_immediate
  39. missing-topics-fatal: false
  40. type: batch

以上的producer和consumer的相关配置也可以在java文件中实现:

如上图的实现,自己可以手动实现一下。

kafka内部自己实现分区、策略等一系列的逻辑,当然这些也可以自定义,这里有需要的可以自己研究一下,我这里就不需要了。

接下来,我介绍一个场景,是大家在实际的项目中可以用到。有这样一个场景,在项目中,我们搭建了kafka集群,然而在环境中,会有各种不同的消息,有一些消息不是我们需要的,有些消息是我们需要的,这时我们可以通过过滤器来进行控制和过滤。

在生产者端,我添加一个过滤器在消息前统一加上一个前缀。

 

  1. @Slf4j
  2. public class ProducerPrefixInterceptor implements ProducerInterceptor<String,String> {
  3. AtomicInteger success = new AtomicInteger(0);
  4. AtomicInteger fail = new AtomicInteger(0);
  5. @Override
  6. public ProducerRecord<String, String> onSend(ProducerRecord<String, String> producerRecord) {
  7. // 消息统一添加前缀
  8. String modifyValue = "prefix-"+producerRecord.value();
  9. return new ProducerRecord<>(producerRecord.topic(), producerRecord.partition(), producerRecord.timestamp(), producerRecord.key(), modifyValue, producerRecord.headers());
  10. }
  11. @Override
  12. public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
  13. if (Objects.nonNull(recordMetadata)){
  14. success.incrementAndGet();
  15. }else {
  16. fail.incrementAndGet();
  17. }
  18. }
  19. @Override
  20. public void close() {
  21. log.info("success:%d\nfail:%d\n",success.get(),fail.get());
  22. success.set(0);
  23. fail.set(0);
  24. }
  25. @Override
  26. public void configure(Map<String, ?> map) {
  27. }
  28. }

然后在消费者消费时,我遇到prefix前缀的消息时,就统一过滤掉,这不是我所需要的消息。

  1. @Slf4j
  2. public class ConsumerPrefixInterceptor implements ConsumerInterceptor<String,String> {
  3. /**
  4. * 过滤掉test开头的数据
  5. * @param consumerRecords
  6. * @return
  7. */
  8. @Override
  9. public ConsumerRecords<String, String> onConsume(ConsumerRecords<String, String> consumerRecords) {
  10. List<ConsumerRecord<String, String>> filterRecords = new ArrayList<>();
  11. Map<TopicPartition, List<ConsumerRecord<String, String>>> newRecords= new HashMap<>();
  12. Set<TopicPartition> partitions = consumerRecords.partitions();
  13. for(TopicPartition tp : partitions){
  14. List<ConsumerRecord<String, String>> records = consumerRecords.records(tp);
  15. for(ConsumerRecord<String, String> record: records){
  16. if(!record.value().startsWith("prefix")) {
  17. filterRecords.add(record);
  18. }
  19. }
  20. if(filterRecords.size() > 0){
  21. newRecords.put(tp, filterRecords);
  22. }
  23. }
  24. return new ConsumerRecords<>(newRecords);
  25. }
  26. @Override
  27. public void onCommit(Map<TopicPartition, OffsetAndMetadata> map) {
  28. map.forEach((k,v) -> log.info("tp:%s--offset:%s\n",k,v));
  29. }
  30. @Override
  31. public void close() {
  32. }
  33. @Override
  34. public void configure(Map<String, ?> map) {
  35. }
  36. }

相关的配置在上述的配置文件中也已经列出了,也可以在代码中加以配置。

props.put("properties.interceptor.classes","com.volga.kafka.interceptor.ProducerPrefixInterceptor");

这样就能实现过滤不需要的消息了。

翻看源码中,生产端主要是KafkaProducer<k,v>这个类中KafkaProducer方法:

消费端这边是对应的:KafkaConsumer<k,v>,这个类中KafkaConsumer方法:

源码里kafka实现的配置逻辑大家可以仔细研究一下。

我是空谷有来人,谢谢支持! 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/870308
推荐阅读
相关标签
  

闽ICP备14008679号