Producer的client端
示例代码
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("client.id", "DemoProducer");
props.put("key.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
producer = new KafkaProducer<Integer, String>(props);
this.topic = topic;
this.isAsync = isAsync;
String messageStr = "Message_";
long startTime = System.currentTimeMillis();
if (isAsync) {
异步处理,这个过程需要定义一个回调函数来监听发送的消息的响应结果
// Send asynchronously
producer.send(new ProducerRecord<byte[], byte[]>(topic,
messageNo.getBytes()/*key*/,
messageNo.getBytes()/*value*/),
/*异步处理,回调函数*/
new DemoCallBack(startTime, messageNo, messageStr));
} else {
同步处理,发送完成后,等待发送的响应结果。
// Send synchronously
try {
producer.send(new ProducerRecord<Integer, String>(topic,
messageNo.getBytes()/*key*/,
messageNo.getBytes()/*value*/)).get();
System.out.println("Sent message: (" + messageNo + ", " + messageStr + ")");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
关于异步处理的回调函数定义:
这个回调函数实现需要实现org.apache.kafka.clients.producer.Callback接口。
class DemoCallBack implements Callback
并实现接口中的函数:
public void onCompletion(RecordMetadata metadata, Exception exception) {
这里的startTime是发送这条消息时,生成回调函数时传入的消息发送的开始时间,
计算出来了这次发送这条消息共花的时间
long elapsedTime = System.currentTimeMillis() - startTime;
if (metadata != null) {
如果metadata信息不为空,表示消息添加成功,可以得到当前添加成功的消息的offset.
System.out.println(
"message(" + key + ", " + message + ") sent to partition("
+ metadata.partition() +
"), " +
"offset(" + metadata.offset() + ") in " + elapsedTime + " ms");
} else {
这种情况下,表示exception有值,也就是添加消息失败了,可以直接打印这个失败的消息的内容。
exception.printStackTrace();
}
}
Client端的生成与处理流程
生成KafkaProducer实例
1,首先看看KafkaProducer实例生成:
根据传入的properties配置信息,生成用于Producer的config实例。
this(new ProducerConfig(properties), null, null);
2,解析必要的配置项:
2,1,配置项client.id,用于标记client端的一个编码值,默认值为producer-1。在同一个进程内,多个client端时,如果没有指定,默认根据1这个值向后增加。
2,2,配置项partitioner.class,配置用于producer写入数据时用于计算这条数据对应的partition的分配算子实例,这个实例必须是的Partitioner实现。实例初始化时会调用configure函数把配置文件传入进去,用于实例生成时使用,默认情况下分区算子是DefaultPartitioner。这个默认算子根据当前的key值进行murmur2 hash并与对应的topic的个数于模,如果key为null时,根据一个自增的integer的值与partition的个数取模.
2,3,配置项retry.backoff.ms,用于在向broker发送数据失败后的重试间隔时间,默认值为100ms
2,4,配置项metadata.max.age.ms,用于配置每个producer端缓存topic的metadata的过期时间,默认值为5分钟。配置上面的2,3,与2,4的配置,生成一个Metadata实例。
2,5,配置项max.request.size,用于配置每次producer请求的最大的字节数,默认值为1MB。
2,6,配置项buffer.memory,用于配置producer端等待向server发送的数据的缓冲区的大小,默认值为32MB。
2,7,配置项compression.type,默认值none,用于配置数据的压缩算法,默认为不压缩,可配置的值为none,gzip,snappy,lz4。
2,8,配置项max.block.ms,用于配置send数据或partitionFor函数得到对应的leader时,最大的等待时间,默认值为60秒。
2,9,配置项request.timeout.ms,用于配置socket请求的最大超时时间,默认值为30秒。
3,生成record的累加器,这是一个用于对producer要发送的数据进行缓冲的实例:
this.accumulator = new RecordAccumulator(
config.getInt(ProducerConfig.BATCH_SIZE_CONFIG),
this.totalMemorySize,
this.compressionType,
config.getLong(ProducerConfig.LINGER_MS_CONFIG),
retryBackoffMs,
metrics,
time,
metricTags);
3,1,RecordAccumulator实例需要的配置:
3,1,1配置项batch.size,用于批量提交的batch字节大小,默认值为16384。
3,1,2配置项linger.ms,这个配置与3,1,1配合使用,用于配置数据缓存的最大延迟时间,默认值0.
3,1,3依赖的其它配置项:2,6 2,7 2,3。
4,根据配置项bootstrap.servers,多个配置使用逗号分开,
生成用于socket请求的InetSocketAddress实例集合。
4,1并根据配置的broker的连接地址集合,生成Cluster的实例。把cluster实例更新到metadata的实例中。
5,生成NetworkClient实例,这个实例用于与各个broker进行socket通信,生成用于进行数据发送的Sender实例,并生成用于数据发送的KafkaThread线程并启动。
6,根据配置项key.serializer/value.serializer,生成key与value的序列化实例,这实例必须是Serializer的实现。
KafkaThread线程初始化
生成NetworkClient实例需要的配置项:
1,配置项connections.max.idle.ms,默认值为9分钟,用于设置连接最大的空闲时间,
2,配置项max.in.flight.requests.per.connection,默认值5,用于设置每个连接最大的请求个数
3,配置