1 kafka的常用操作命令
1.1 创建topic:
命令:kafka-topics.sh
--create //创建topic命令参数
--zookeeper hdp01:2181 //指定zookeeper地址来保存元数据相关信息
--replication-factor 1 //指定topic副本数量
--partitions 1 //指定topic分片数量
--topic order_topic //指定topic的名称
执行结果:Created topic "order_topic"
1.2 生产者发送消息
命令:kafka-console-producer.sh
--broker-list hdp01:9092 //指定broker
--topic order_topic//指定topic
1.3 消费者消费消息
命令:kafka-console-consumer.sh
--zookeeper hdp01:2181 //指定zookeeper的地址
--from-beginning//指定从什么地方开始消费数据
--topic order_topic//指定消费的topic
1.4 查看某个topic的详情
命令:kafka-topics.sh
--topic order_topic
--describe
--zookeeper hdp01:2181
执行结果:Topic:order_topic
PartitionCount:1
ReplicationFactor:1
Configs:Topic: order_topic
Partition: 0
Leader: 0
Replicas: 0
Isr: 0
1.5 查看当前服务器中所有的topic
命令:kafka-topics.sh
--list
--zookeeper hdp01:2181
执行结果:order_topic
1.6 删除topic
命令:kafka-topics.sh --delete --zookeeper hdp01:2181 --topic order_topic
注:需要将delete.topic.enable设置为true才真正删除
2 kafka的Java API操作
2.1Kafka生产者Java API
示例代码:
package com.kafka.simple;
import java.util.Properties;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
public class KafkaProducerSimple {
public static void main(String[] args) {
// 指定当前kafka producer生产数据的目的地
String topic = "order_topic";
// 读取配置文件
Properties props = new Properties();
// 指定序列化编码(key.serializer.class默认为serializer.class)
props.put("serializer.class", "kafka.serializer.StringEncoder");
// kafka broker对应的主机,格式为:host:port,host:port,host:port
props.put("metadata.broker.list", "hdp01:9092,hdp02:9092,hdp03:9092");
// request.required.acks,设置发送数据是否需要服务端的反馈,有三个值0,1,-1
// 0:意味着producer永远不会等待一个来自broker的ack,这就是0.7版本的行为。
// 这个选项提供了最低的延迟,但是持久化的保证是最弱的,当server挂掉的时候会丢失一些数据。
// 1:意味着在leader replica已经接收到数据后,producer会得到一个ack。
// 这个选项提供了更好的持久性,因为在server确认请求成功处理后,client才会返回。
// 如果刚写到leader上,还没来得及复制leader就挂了,那么消息才可能会丢失。
// -1:意味着在所有的ISR都接收到数据后,producer才得到一个ack。
// 这个选项提供了最好的持久性,只要还有一个replica存活,那么数据就不会丢失
props.put("request.required.acks", "1");
// 通过配置文件创建生产者
Producer<String, String> producer = new Producer<String, String>(new ProducerConfig(props));
// 通过for循环生成数据
int msgNo = 0;
while (true) {
String msg = "order-topic:"+System.currentTimeMillis();
// 5、调用producer的send方法发送数据
// 注意:这需要指定partitionKey,用来配合自定义的的partition进行数据分发
producer.send(new KeyedMessage<String, String>(topic, ++msgNo + "", msg));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.2 kafka消费者Java API
示例代码:
package com.kafka.simple;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import kafka.message.MessageAndMetadata;
public class KafkaConsumerSimple implements Runnable {
private String title;
private KafkaStream<byte[], byte[]> kafkaStream;
public KafkaConsumerSimple(String title, KafkaStream<byte[], byte[]> kafkaStream) {
super();
// 获取自己消费的编号以及要消费的kafkaStream
this.title = title;
this.kafkaStream = kafkaStream;
}
@Override
public void run() {
// 从kafkaStream中获取一个迭代器
ConsumerIterator<byte[], byte[]> it = kafkaStream.iterator();
// 不停地从stream读取新来的消息,在等待新的消息是,hashNext()会阻塞
while (it.hasNext()) {
MessageAndMetadata<byte[], byte[]> data = it.next();
String topic = data.topic();
int partition = data.partition();
long offset = data.offset();
String msg = new String(data.message());
System.out.println(String.format("Consumer: [%s], Topic: [%s],
PartitionId: [%d], Offset: [%d], msg: [%s]", title, topic, partition, offset, msg));
}
System.err.println(String.format("Consumer: [%s] exiting ...", title));
}
public static void main(String[] args) {
// 1、 准备一些配置参数
Properties props = new Properties();
props.put("group.id", "order_par3_topic");
props.put("consumer.id", "cj");
props.put("zookeeper.connect", "hdp01:2181,hdp02:2181,hdp03:2181");
props.put("auto.offset.reset", "largest");
props.put("auto.commit.interval.ms", "1000");
props.put("partition.assignment.strategy", "roundrobin");
ConsumerConfig config = new ConsumerConfig(props);
// 2、准备要消费的topic
String topic = "order_par3_topic";
// 3、创建一个consumer连接器,只要ConsumerConnector还在,consumer会一直等待新消息,不会自己退出
ConsumerConnector connect = Consumer.createJavaConsumerConnector(config);
// 创建topicCountMap
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(topic, 3);
// 4、获取每个topic对应的KafkaStream
Map<String, List<KafkaStream<byte[], byte[]>>> topicStreamsMap = //
connect.createMessageStreams(topicCountMap);
// 5、消费KafkaStream中的数据
List<KafkaStream<byte[], byte[]>> streams = topicStreamsMap.get(topic);
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < streams.size(); i++) {
executorService.execute(new KafkaConsumerSimple("消费者:" + i, streams.get(i)));
}
}
}