生产者程序开发
- 创建连接
- bootstrap.servers:Kafka的服务器地址
- acks:表示当生产者生产数据到Kafka中,Kafka中会以什么样的策略返回
- key.serializer:Kafka中的消息是以key、value键值对存储的,而且生产者生产的消息是需要在网络上传到的,这里指定的是StringSerializer方式,就是以字符串方式发送(将来还可以使用其他的一些序列化框架:Google ProtoBuf、Avro)
- value.serializer:同上
- 创建一个生产者对象KafkaProducer
- 调用send方法发送消息(ProducerRecor,封装是key-value键值对)
- 调用Future.get表示等带服务端的响应
- 关闭生产者
public class KafkaProducerTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Properties props = new Properties();
props.put("bootstrap.servers", "node1.itcast.cn:9092");
props.put("acks", "all");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(props);
for(int i = 0; i < 100; ++i) {
ProducerRecord<String, String> producerRecord = new ProducerRecord<>("test", null, i + "");
Future<RecordMetadata> future = kafkaProducer.send(producerRecord);
future.get();
System.out.println("第" + i + "条消息写入成功!");
}
kafkaProducer.close();
}
}
消费者程序开发
- group.id:消费者组的概念,可以在一个消费组中包含多个消费者。如果若干个消费者的group.id是一样的,表示它们就在一个组中,一个组中的消费者是共同消费Kafka中topic的数据。
- Kafka是一种拉消息模式的消息队列,在消费者中会有一个offset,表示从哪条消息开始拉取数据
- kafkaConsumer.poll:Kafka的消费者API是一批一批数据的拉取
public class KafkaConsumerTest {
public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("bootstrap.servers", "node1.itcast.cn:9092");
props.setProperty("group.id", "test");
props.setProperty("enable.auto.commit", "true");
props.setProperty("auto.commit.interval.ms", "1000");
props.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(props);
kafkaConsumer.subscribe(Arrays.asList("test"));
while(true) {
ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(Duration.ofSeconds(5));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
String topic = consumerRecord.topic();
long offset = consumerRecord.offset();
String key = consumerRecord.key();
String value = consumerRecord.value();
System.out.println("topic: " + topic + " offset:" + offset + " key:" + key + " value:" + value);
}
}
}
}
生产者使用异步方式生产消息
- 使用匿名内部类实现Callback接口,该接口中表示Kafka服务器响应给客户端,会自动调用onCompletion方法
- metadata:消息的元数据(属于哪个topic、属于哪个partition、对应的offset是什么)
- exception:这个对象Kafka生产消息封装了出现的异常,如果为null,表示发送成功,如果不为null,表示出现异常。
ProducerRecord<String, String> producerRecord = new ProducerRecord<>("test", null, i + "");
kafkaProducer.send(producerRecord, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if(exception == null) {
String topic = metadata.topic();
int partition = metadata.partition();
long offset = metadata.offset();
System.out.println("topic:" + topic + " 分区id:" + partition + " 偏移量:" + offset);
}
else {
System.out.println("生产消息出现异常!");
System.out.println(exception.getMessage());
System.out.println(exception.getStackTrace());
}
}
});