Kafka 1:生产者发送并忘记

生产者发送消息的基本流程

  • 从创建一个 ProducerRecord 对象开始, Producer Record 对象需要包含目标主题和要发送的内容。我们还可以指定键或分区。在发送 ProducerReco rd 对象时,生产者要先把键和值对象序列化成字节数组,这样它们才能够在网络上传输。
  • 接下来,数据被传给分区器。如果之前在 Producer Record 对象里指定了分区,那么分区器就不会再做任何事情,直接把指定的分区返回。如果没有 指定分区,那么分区器会根据 Producer Record 对象的键来选择一个分区。选好分区以后,生产者就知道该往哪个主题和分区发送这条记录了。紧接着, 这条记录被添加到一个记录批次里(双端队列,尾部写入),这个批次里的所有消息会被发送到相同的主题和分区上。有一个独立的线程负责把这些记 录批次发送到相应的 broker 上。
  • 服务器在收到这些消息时会返回一个响应。如果消息成功写入 Kafka ,就返回一个 RecordMetaData 对象,它包含了主题和分区信息,以及记录在分 区里的偏移量。如果写入失败, 则会返回一个错误。生产者在收到错误之后会尝试重新发送消息,几次之后如果还是失败,就返回错误信息。
  • 生产者发送消息一般会发生两类错误: 一类是可重试错误,比如连接错误(可通过再次建立连接解决)、无主 no leader(可通过分区重新选举首领解决)。 另一类是无法通过重试解决,比如“消息太大”异常,具体见 message.max.bytes,这类消息不会进行任何重试,直接抛出异常
  • message.max.bytes 表示一个服务器能够接收处理的消息的最大字节数,注意这个值 producer 和 consumer 必须设置一致,且不要大于 fetch.message.max.bytes 属性的值 (消费者能读取的最大消息,这个值应该大于或等于 message.max.bytes)。该值默认是 1000000 字节,大概 900KB~1MB。如果启动压缩,判断压缩后的值。 这个值的大小对性能影响很大,值越大,网络和 IO 的时间越长,还会增加磁盘写入的大小。 Kafka 设计的初衷是迅速处理短小的消息,一般 10K 大小的消息吞吐性能最好(LinkedIn 的 kafka 性能测试)

在这里插入图片描述

发送并忘记: 忽略 send 方法的返回值,不做任何处理。大多数情况下,消息会正常到达,而且生产者会自动重试,但有时会丢失消息。效率最高,但不保证消息的可靠性。

1.创建主题"./kafka-topics.sh --zookeeper localhost:2181 --create --topic hello-kafka --replication-factor 1 --partitions 4"

主题名hello-kafka,一个副本,4个分区

2.创建一个maven工程,引入依赖

在这里插入图片描述

  <dependencies>
    <dependency>
      <groupId>org.apache.kafka</groupId>
      <artifactId>kafka-clients</artifactId>
      <version>2.3.0</version>
    </dependency>
  </dependencies>
3.创建一个常量类BusiConst,定义一个主题名称
package org.example.config;

public class BusiConst {
    public static final String HELLO_TOPIC  = "hello-kafka";
}
4.创建一个生产者HelloKafkaProducer
package org.example.helloKafka;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import org.example.config.BusiConst;

import java.util.Properties;

public class HelloKafkaProducer {
    public static void main(String[] args) {
        //生产者必须指定3个属性(broker地址清单,key和value的序列化器)
        Properties properties = new Properties();
        properties.put("bootstrap.servers", "192.168.42.111:9092");
        properties.put("key.serializer", StringSerializer.class);
        properties.put("value.serializer", StringSerializer.class);
        KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
        try {
            ProducerRecord<String, String> record;
            for (int i = 0; i < 4; i++) {
                record = new ProducerRecord<String, String>(BusiConst.HELLO_TOPIC,
                        String.valueOf(i), "Fisher");
                //发送并忘记
                producer.send(record);
                System.out.println(i + ", message is sent.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            producer.close();
        }
    }
}
5.创建消费者HelloKafkaConsumer
package org.example.helloKafka;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.example.config.BusiConst;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

public class HelloKafkaConsumer {
    public static void main(String[] args) {
        //消费者必须指定3个属性(broker地址清单,key和value的反序列化器)
        Properties properties = new Properties();
        properties.put("bootstrap.servers", "192.168.42.111:9092");
        properties.put("key.deserializer", StringDeserializer.class);
        properties.put("value.deserializer", StringDeserializer.class);
        //群组并非必须
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "test1");
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
        //订阅主题(可以多个)
        consumer.subscribe(Collections.singletonList(BusiConst.HELLO_TOPIC));
        try {
            while (true) {
                ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(500));
                for (ConsumerRecord<String, String> record : records) {
                    System.out.println("主题:"+record.topic()+",分区:"+record.partition()+",偏移量:"+record.offset()+
                            ",key:"+record.key()+",value:"+record.value());
                }
            }
        } finally {
            consumer.close();
        }
    }
}
6.先启动消费者,再启动生产者,生产了4条消息

在这里插入图片描述

7.查看消费者打印,只有分区0和分区3写入了消息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值