kafka 代码、配置

代码示例

KafkaProducerDemo.class

public class KafkaProducerDemo extends Thread{
    private final KafkaProducer<Integer,String> producer;
    private final String topic;
    private final boolean isAysnc;

    public KafkaProducerDemo(String topic,boolean isAysnc){
       Properties properties=new Properties();
       properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"49.235.16.28:9092");		//kafka集群地址
       properties.put(ProducerConfig.CLIENT_ID_CONFIG,"KafkaConsumerDemo2");	//这是客户端ID
       properties.put(ProducerConfig.ACKS_CONFIG,"0"); 	//0:无需broker确认。1:m节点broker确认即可。All(-1):需要所有节点确认
       properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, 
        												 "org.apache.kafka.common.serialization.IntegerSerializer"); //设置key序列化
       properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, 
       													"org.apache.kafka.common.serialization.StringSerializer");	//设置value序列化
        producer=new KafkaProducer<Integer, String>(properties);
        this.topic=topic;
        this.isAysnc=isAysnc;
    }

    @Override
    public void run() {
        int num=0;
        while(num<10){
            String message="message_"+num;
            System.out.println("begin send message:"+message);
            if(isAysnc){//异步发送
     		 producer.send(new ProducerRecord<Integer, String>(topic, message), new Callback() {
                 @Override
          		 public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                        if(recordMetadata!=null){
								System.out.println("async-offset:"+recordMetadata.offset()+"->partition"+recordMetadata.partition());
                        }
                    }
                });
            }else{//同步发送  future/callable
                try {
        			RecordMetadata recordMetadata = producer.send(new ProducerRecord<Integer, String>(topic,message)).get();
                   System.out.println("sync-offset:"+recordMetadata.offset()+ "->partition"+recordMetadata.partition());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }

            }
            num++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new KafkaProducerDemo("test0815",true).start();
    }
}

KafkaConsumerDemo.class

public class KafkaConsumerDemo extends Thread {
   private final KafkaConsumer kafkaConsumer;
   public KafkaConsumerDemo(String topic) {
      Properties properties = new Properties();
      properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
"49.235.16.28:9092");		//kafka集群IP
      properties.put(ConsumerConfig.GROUP_ID_CONFIG, "KafkaConsumerDemo2");	//分组ID
      properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
      properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");			//间隔时间
      properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
 "org.apache.kafka.common.serialization.IntegerDeserializer"); //key反序列化
      properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
 "org.apache.kafka.common.serialization.StringDeserializer"); //value反序列
      properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
						//earliest 从头开始消费
      kafkaConsumer = new KafkaConsumer(properties);
      kafkaConsumer.subscribe(Collections.singletonList(topic));	 //订阅
   }

   @Override
   public void run() {
      while (true) {
         ConsumerRecords<Integer, String> consumerRecord = kafkaConsumer.poll(1000);
         for (ConsumerRecord record : consumerRecord) {
            System.out.println("message receive:" + record.value());
            kafkaConsumer.commitAsync();
         }
      }
   }

   public static void main(String[] args) {
      new KafkaConsumerDemo("test0815").start();
   }
}

配置分析

发送端配置

acks:对数据要求很高,用all(-1),其他用1。

	0 :写入的消息不需要等待副本确认。
	1 :写入的消息被leader副本记录则认为提交成功。
	all(-1) :写入的消息需要被复制到ISR的所有副本,才认为提交成功。性能低,最安全,但如果副本只有一个,副本宕机时有可能数据丢失

batch.size :以大小为单位,Producer把发送到同一个分区的消息封装进一个batch,在不考虑linger.ms的情况下,batch满了再统一发送。

	batch越小,吞吐量越低。越大,吞吐量越高。默认16KB。

linger.ms:以时间为单位,Producer将时间间隔内的所有请求进行一次聚合,再统一发送。

	默认0,表示不做停留,这样会导致大量的小batch被发送出去(导致batch.size不生效),给网络IO带来极大压力。
	假如设置linger.ms=5,表示producer的请求延迟5ms发送。

batch.size和linger.ms的作用是一样的,是kafka性能调优的关键参数。如果两个都配置了,只要满足其中一个,Producer就会发送请求。

compression.type (Producer压缩器):目前支持none(不压缩)、gzip、snappy、lz4(Lz4的效果最好)。

max.request.size (请求数据的最大字节数):默认1MB, 防止大的数据包影响吞吐量

buffer.memory (producer 缓冲区大小):指定producer缓存消息的缓冲区大小,默认33554432字节(32M)。

	Producer启动时在内存中创建一块缓冲区,用于存放消息,然后由专属线程sender负责从缓冲区拿消息,进行真正的发送。

	消息持续发送过程中,当缓冲区填满后,producer立即进入阻塞状态,直到缓冲区的内存释放出来。阻塞时间一旦超过max.block.ms设置的值,producer就会抛异常:TimeoutException。这种情况下就需要调高buffer.memory的值,增大缓冲区。

retries(失败后重试次数)

	max.in.flight.requests.per.connection设置如果大于1,重试可能会造成消息乱序。
	0.11.1.0版本已经支持“精确到一次语义”,重试不会造成消息重复发送。

消费端配置

Consumer.poll(1000):Consumer拿到足够多的数据就会返回一个ConsumerRecords,但如果阻塞了 1000ms,哪怕仍没有拿到足够多的数据,也依旧返回。

	1000:最长阻塞时间。

bootstrap.servers:设置broker地址:host1:port1;host2:port2…

heartbeat.interval.ms (心跳间隔):Consumer与coordinator之间的心跳,是为了确认consumer存活、加入或者退出groupd。

	这个值必须小于session.timeout.ms,如果心跳间隔时间超过session.timeout.ms,coordinator会认为该consumer退出,并由group内consumer重新rebalance。通常心跳间隔时间(3S)小于session.timeout.ms的1/3.

session.timeout.ms:Consumer session 过期时间。默认10S。

	这个值得设置必须在broker configuration中的group.min.session.timeout.ms 与 group.max.session.timeout.ms之间。

max.partition.fetch.bytes:fetch操作时,指定每个分区返回最大字节数,默认1M。

	这个值必须比broker能够接受的最大消息的配置(max.message.size)大,否则会引起消费者无法消费数据(出口>入口)。	
	max.partition.fetch.bytes设置不能过大,会导致consumer消费数据时间过长,没有及时再次poll而会话过期。

groupid:一个组内可以有多个消费者,并共用一个group id

	如果topic某个消息被组内某个consumer消费了,那么组内其他consumer不可再消费。
	各组之间消费互不影响。

在这里插入图片描述

enable.auto.commit (自动提交):默认值:true

	Consumer消费后自动提交offset+1。只有提交后,该消息才不会被再次接收。
	可以配合auto.commit.interval.ms 控制自动提交的频率(默认5S),当然也可以consumer.commitSync()的方式实现手动提交

自动提交与手动提交:自动提交其实在很多场景都不适用,因为自动提交是在kafka拉取到数据之后就直接提交,这样很容易丢失数据,尤其是在需要事物控制的时候。

auto.offfset.reset (消费)

	latest:	从topic最新的数据开始消费(默认)
	earliest:从topic最早的消息开始消
	none:	如果offset不存在,则抛异常

max.poll.records:每次调用poll()返回的消息数,减少poll间隔

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值