kafka学习笔记四

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)));
		}
	}
  }
posted @ 2018-04-11 15:37  我亦在  阅读(263)  评论(0编辑  收藏  举报