springboot集成kafka

1.pom.xml中增加依赖包

    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>

2.application.yml中引入kafka相关配置

  spring:
    kafka:
      # 服务器地址
      bootstrap-servers: 192.168.146.128:9092
      producer:
        # 发生错误后,消息重发的次数。
        retries: 0
        #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
        batch-size: 16384
        # 设置生产者内存缓冲区的大小。
        buffer-memory: 33554432
        # 键的序列化方式
        key-serializer: org.apache.kafka.common.serialization.StringSerializer
        # 值的序列化方式
        value-serializer: org.apache.kafka.common.serialization.StringSerializer
        # acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
        # acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
        # acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
        acks: 1
      consumer:
          # 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D
        auto-commit-interval: 1S
          # 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理:
          # latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录)
          # earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录
        auto-offset-reset: earliest
          # 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量
        enable-auto-commit: false
          # 键的反序列化方式
        key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
          # 值的反序列化方式
        value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      listener:
          # 在侦听器容器中运行的线程数。
        concurrency: 5
          #listner负责ack,每调用一次,就立即commit
        ack-mode: manual_immediate
        missing-topics-fatal: false

创建生产者

  @RestController
  public class KafkaController {

      @Autowired
      private KafkaTemplate<String,Object> kafkaTemplate;


      @GetMapping("send")
      public boolean send(@RequestParam String message){
          kafkaTemplate.send("test",message);
          return true;
      }

创建消费者

  @Component
  public class ConsumerListener {

      @KafkaListener(topics = "test",groupId ="test-consumer-group")
      public void onMessage(String message){
          //insertIntoDb(buffer);//这里为插入数据库代码
          System.out.println(message);
      }

  }

此时并没有消费kafka队列中的消息,仅仅是将消息取出来,需要返回offset才算真正的消费了,因此具体消费的代码如下:

  @RestController
  public class ConsumerController {



      private static Consumer<String, String> createConsumer() {
          final Properties props = new Properties();
          props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.146.128:9092");
          props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-consumer-group");
          props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class.getName());
          props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());

          final Consumer<String, String> consumer = new KafkaConsumer<>(props);

          return consumer;
      }


      @GetMapping("/consumer")
      public boolean consumer(){
          Consumer<String, String> consumer = createConsumer();
          consumer.subscribe(Collections.singletonList("test"));
          final int giveUp = 100; int noRecordsCount = 0;
          while(true){
              final ConsumerRecords<String, String> consumerRecords = consumer.poll(1000);
              if(consumerRecords.count()==0){
                  noRecordsCount++;
                  if(noRecordsCount > giveUp) break;
                  else continue;
              }
              consumerRecords.forEach(record -> {
                  System.out.printf("Consumer Record:(%d, %s, %d, %d)\n",
                          record.key(), record.value(),
                          record.partition(), record.offset());
              });
              consumer.commitAsync();
          }
          return true;
      }
  }
posted @ 2020-12-01 19:36  怀念ぅ风锍  阅读(109)  评论(0)    收藏  举报