KafkaProducer-kafka生产者Java客户端

KafkaProducer(org.apache.kafka.clients.producer.KafkaProducer)是一个用于向kafka集群发送数据的Java客户端。该Java客户端是线程安全的,多个线程可以共享同一个producer实例,而且这通常比在多个线程中每个线程创建一个实例速度要快些。本文介绍的内容来自于kafka官方文档,详情参见KafkaProducer
下文先给出一个简单的实例,而后对其中的参数进行说明。

package com.test.kafkaProducer;

import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.PartitionInfo;


public class TestProducer {

    public static void main(String[] args) {

        Properties props = new Properties();
        props.put("bootstrap.servers", "192.168.137.200:9092");
        props.put("acks", "all");
        props.put("retries", 0);
        props.put("batch.size", 16384);
        props.put("linger.ms", 1);
        props.put("buffer.memory", 33554432);
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        //生产者发送消息 
        String topic = "mytopic";
        Producer<String, String> procuder = new KafkaProducer<String,String>(props);
        for (int i = 1; i <= 10; i++) {
            String value = "value_" + i;
            ProducerRecord<String, String> msg = new ProducerRecord<String, String>(topic, value);
            procuder.send(msg);
        }
        //列出topic的相关信息
        List<PartitionInfo> partitions = new ArrayList<PartitionInfo>() ;
        partitions = procuder.partitionsFor(topic);
        for(PartitionInfo p:partitions)
        {
            System.out.println(p);
        }

        System.out.println("send message over.");
        procuder.close(100,TimeUnit.MILLISECONDS);
    }
}

producer包含一个用于保存待发送消息的缓冲池,缓冲池中消息是还没来得及传输到kafka集群的消息。位于底层的kafka I/O线程负责将缓冲池中的消息转换成请求发送到集群。如果在结束produce时,没有调用close()方法,那么这些资源会发生泄露。
用于建立消费者的相关参数说明及其默认值参见producerconfigs,此处对代码中用到的几个参数进行解释:
bootstrap.servers:用于初始化时建立链接到kafka集群,以host:port形式,多个以逗号分隔host1:port1,host2:port2;
acks:生产者需要server端在接收到消息后,进行反馈确认的尺度,主要用于消息的可靠性传输;acks=0表示生产者不需要来自server的确认;acks=1表示server端将消息保存后即可发送ack,而不必等到其他follower角色的都收到了该消息;acks=all(or acks=-1)意味着server端将等待所有的副本都被接收后才发送确认。
retries:生产者发送失败后,重试的次数
batch.size:当多条消息发送到同一个partition时,该值控制生产者批量发送消息的大小,批量发送可以减少生产者到服务端的请求数,有助于提高客户端和服务端的性能。
linger.ms:默认情况下缓冲区的消息会被立即发送到服务端,即使缓冲区的空间并没有被用完。可以将该值设置为大于0的值,这样发送者将等待一段时间后,再向服务端发送请求,以实现每次请求可以尽可能多的发送批量消息。
batch.size和linger.ms是两种实现让客户端每次请求尽可能多的发送消息的机制,它们可以并存使用,并不冲突。
buffer.memory:生产者缓冲区的大小,保存的是还未来得及发送到server端的消息,如果生产者的发送速度大于消息被提交到server端的速度,该缓冲区将被耗尽。
key.serializer,value.serializer说明了使用何种序列化方式将用户提供的key和vaule值序列化成字节。

kafka客户端的API
KafkaProducer对象实例化方法,可以使用map形式的键值对或者Properties对象来配置客户端的属性

/*
 *keySerializer:发送数据key值的序列化方法,该方法实现了Serializer接口
 *valueSerializer:发送数据value值的序列化方法,该方法实现了Serializer接口
 */
public KafkaProducer(Map<String,Object> configs);
public KafkaProducer(Map<String,Object> configs, Serializer<K> keySerializer,Serializer<V> valueSerializer);
public KafkaProducer(Properties properties);
public KafkaProducer(Properties properties, Serializer<K> keySerializer,Serializer<V> valueSerializer);

消息发送方法send()

/*
 *record:key-value形式的待发送数据
 *callback:到发送的消息被borker端确认后的回调函数
 */
public Future<RecordMetadata> send(ProducerRecord<K,V> record); // Equivalent to send(record, null)
public Future<RecordMetadata> send(ProducerRecord<K,V> record,Callback callback);

send方法负责将缓冲池中的消息异步的发送到broker的指定topic中。异步发送是指,方法将消息存储到底层待发送的I/O缓存后,将立即返回,这可以实现并行无阻塞的发送更多消息。send方法的返回值是RecordMetadata类型,它含有消息将被投递的partition信息,该条消息的offset,以及时间戳。
因为send返回的是Future对象,因此在该对象上调用get()方法将阻塞,直到相关的发送请求完成并返回元数据信息;或者在发送时抛出异常而退出。
阻塞发送的方法如下:

String key = "Key";
String value = "Value";
ProducerRecord<String, String> record = new ProducerRecord<String, String>(key, value);
producer.send(record).get();

可以充分利用回调函数和异步发送方式来确认消息发送的进度:

ProducerRecord<String,String> record = new ProducerRecord<String,String>("the-topic", key, value);
producer.send(myRecord, new Callback() {
                    public void onCompletion(RecordMetadata metadata, Exception e) {
                        if(e != null) {
                            e.printStackTrace();
                        } else {
                            System.out.println("The offset of the record we just sent is: " + metadata.offset());
                        }
                    }
                });

flush
立即发送缓存数据

public void flush();

调用该方法将使得缓冲区的所有消息被立即发送(即使linger.ms参数被设置为大于0),且会阻塞直到这些相关消息的发送请求完成。flush方法的前置条件是:之前发送的所有消息请求已经完成。一个请求被视为完成是指:根据acks参数配置项收到了相应的确认,或者发送中抛出异常失败了。
下面的例子展示了从一个topic消费后发到另一个topic,flush方法在此非常有用,它提供了一种方便的方法来确保之前发送的消息确实已经完成了:

for(ConsumerRecord<String, String> record: consumer.poll(100))
    producer.send(new ProducerRecord("my-topic", record.key(), record.value());
producer.flush();  //将缓冲区的消息立即发送
consumer.commit(); //消费者手动确认消费进度

partitionsFor

//获取指定topic的partition元数据信息
public List<PartitionInfo> partitionsFor(String topic);

close

//关闭producer,方法将被阻塞,直到之前的发送请求已经完成
public void close();//  equivalent to close(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
public void close(long timeout,TimeUnit timeUnit); //同上,方法将等待timeout时长,以让未完成的请求完成发送
展开阅读全文

Git 实用技巧

11-24
这几年越来越多的开发团队使用了Git,掌握Git的使用已经越来越重要,已经是一个开发者必备的一项技能;但很多人在刚开始学习Git的时候会遇到很多疑问,比如之前使用过SVN的开发者想不通Git提交代码为什么需要先commit然后再去push,而不是一条命令一次性搞定; 更多的开发者对Git已经入门,不过在遇到一些代码冲突、需要恢复Git代码时候就不知所措,这个时候哪些对 Git掌握得比较好的少数人,就像团队中的神一样,在队友遇到 Git 相关的问题的时候用各种流利的操作来帮助队友于水火。 我去年刚加入新团队,发现一些同事对Git的常规操作没太大问题,但对Git的理解还是比较生疏,比如说分支和分支之间的关联关系、合并代码时候的冲突解决、提交代码前未拉取新代码导致冲突问题的处理等,我在协助处理这些问题的时候也记录各种问题的解决办法,希望整理后通过教程帮助到更多对Git操作进阶的开发者。 本期教程学习方法分为“掌握基础——稳步进阶——熟悉协作”三个层次。从掌握基础的 Git的推送和拉取开始,以案例进行演示,分析每一个步骤的操作方式和原理,从理解Git 工具的操作到学会代码存储结构、演示不同场景下Git遇到问题的不同处理方案。循序渐进让同学们掌握Git工具在团队协作中的整体协作流程。 在教程中会通过大量案例进行分析,案例会模拟在工作中遇到的问题,从最基础的代码提交和拉取、代码冲突解决、代码仓库的数据维护、Git服务端搭建等。为了让同学们容易理解,对Git简单易懂,文章中详细记录了详细的操作步骤,提供大量演示截图和解析。在教程的最后部分,会从提升团队整体效率的角度对Git工具进行讲解,包括规范操作、Gitlab的搭建、钩子事件的应用等。 为了让同学们可以利用碎片化时间来灵活学习,在教程文章中大程度降低了上下文的依赖,让大家可以在工作之余进行学习与实战,并同时掌握里面涉及的Git不常见操作的相关知识,理解Git工具在工作遇到的问题解决思路和方法,相信一定会对大家的前端技能进阶大有帮助。
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值