Kafka簡單測試demo

介紹


項目很簡單,就是對搭建好的kafka集羣【kafka_2.10-0.8.2.1】做了簡單的demo測試,調用了下high level接口。

源碼


pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.com.dimensoft.kafka</groupId>
  <artifactId>kafka-study</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>kafka-study</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.10</artifactId>
            <version>0.8.2.1</version>
        </dependency>

  </dependencies>
</project>

SampleProducer


SampleProducer是自定義的producer,用來生產消息並將消息push給broker:

/**
  * project:kafka-study
  * file:SampleProducer.java
  * author:zxh
  * time:2015年9月25日 下午4:05:51
  * description:
  */
package cn.com.dimensoft.kafka;

import java.util.Properties;

import cn.com.dimensoft.kafka.constant.Constant;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;

/**
 * class: SampleProducer
 * package: cn.com.dimensoft.kafka
 * author:zxh
 * time: 2015年9月25日 下午4:05:51
 * description: 
 *  step1 : 創建存放配置信息的properties
 *  step2 : 將properties封裝到ProducerConfig中
 *  step3 : 創建producer對象
 *  step4 : 發送數據流
 */
public class SampleProducer {

    public static void main(String[] args) throws InterruptedException {

        // step1 : 創建存放配置信息的properties
        Properties props = new Properties();

        // 指定broker集羣
        props.put("metadata.broker.list", "hadoop-pseudo.com.cn:9092");
        /** 
         * ack機制
         * 0 which means that the producer never waits for an acknowledgement from the broker
         * 1 which means that the producer gets an acknowledgement after the leader replica has received the data
         * -1 The producer gets an acknowledgement after all in-sync replicas have received the data
         */
        props.put("request.required.acks", "1");
        // 消息發送類型 同步/異步
        props.put("producer.type", "sync");
        // 指定message序列化類,默認kafka.serializer.DefaultEncoder
        props.put("serializer.class", "kafka.serializer.StringEncoder");
        // 設置自定義的partition,當topic有多個partition時如何對message進行分區
        props.put("partitioner.class", "cn.com.dimensoft.kafka.SamplePartition");

        // step2 : 將properties封裝到ProducerConfig中
        ProducerConfig config = new ProducerConfig(props);

        // step3 : 創建producer對象
        Producer<String, String> producer = new Producer<String, String>(config);

        for (int i = 1; i <= 50; i++) {
            // step4 : 發送數據流
            producer.send(new KeyedMessage<String, String>(Constant.TOPIC, //
                    i + "", //
                    String.valueOf("我是 " + i + " 號")));
            Thread.sleep(10);
        }
    }

}

SampleConsumer


SampleConsumer是自定義的consumer,用來從broker pull消息對處理:

/**
  * project:kafka-study
  * file:SampleConsumer.java
  * author:zxh
  * time:2015年9月25日 下午4:41:26
  * description:
  */
package cn.com.dimensoft.kafka;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

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;
import cn.com.dimensoft.kafka.constant.Constant;

/**
 * class: SampleConsumer
 * package: cn.com.dimensoft.kafka
 * author:zxh
 * time: 2015年9月25日 下午4:41:26
 * description: 
 *  step1 : 創建存放配置信息的properties
 *  step2 : 將properties封裝到ConsumerConfig中
 *  step3 : 調用Consumer的靜態方法創建ConsumerConnector
 *  step4 : 根據創建好的ConsumerConnector對象創建MessageStreams集合
 *  step5 : 根據具體的topic名稱得到數據流KafkaStream
 *  step6 : 調用KafkaStream的iterator拿到ConsumerIterator對應,然後就可以迭代獲得producer發送過來的消息了
 */
public class SampleConsumer {

    public static void main(String[] args) throws InterruptedException {

        // step1 : 創建存放配置信息的properties
        Properties props = new Properties();

        props.put("zookeeper.connect", "hadoop-pseudo.com.cn:2181");
        props.put("group.id", "1");
        // 下面這2個參數需要設置,否則consumer每次啓動都會從頭開始讀取數據
        props.put("auto.commit.enable", "true");
        props.put("auto.commit.interval.ms", "1000");

        // What to do when there is no initial offset in ZooKeeper or if an
        // offset is out of range
        props.put("auto.offset.reset", "smallest");

        // step2 : 將properties封裝到ConsumerConfig中
        ConsumerConfig config = new ConsumerConfig(props);

        // step3 : 調用Consumer的靜態方法創建ConsumerConnector
        ConsumerConnector connector = Consumer
                .createJavaConsumerConnector(config);

        // step4 : 根據創建好的ConsumerConnector對象創建MessageStreams集合
        Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
        // 將每個topic對應的線程數添加到map中,topicCountMap中的topic對應的value值一直沒測出實際效果
        topicCountMap.put(Constant.TOPIC, 1);
        // 根據填充好的map獲得streams集合
        // a map of (topic, list of KafkaStream) pairs
        Map<String, List<KafkaStream<byte[], byte[]>>> streams = connector
                .createMessageStreams(topicCountMap);

        // step5 : 根據具體的topic名稱得到數據流KafkaStream
        KafkaStream<byte[], byte[]> stream = streams.get(Constant.TOPIC).get(0);

        // step6 : 調用KafkaStream的iterator拿到ConsumerIterator
        // 然後就可以迭代獲得producer發送過來的消息了
        ConsumerIterator<byte[], byte[]> iterator = stream.iterator();

        MessageAndMetadata<byte[], byte[]> mm = null;
        while (iterator.hasNext()) {
            mm = iterator.next();
            System.out.println(//
                    " group " + props.get("group.id") + //
                    ", partition " + mm.partition() + ", " + //
                    new String(mm.message()));
            Thread.sleep(100);
        }
    }
}

SamplePartition


SamplePartition是自定義的partition,用來對消息進行分區:

/**
  * project:kafka-study
  * file:SamplePartition.java
  * author:zxh
  * time:2015年9月28日 下午5:37:19
  * description:
  */
package cn.com.dimensoft.kafka;

import kafka.producer.Partitioner;
import kafka.utils.VerifiableProperties;

/**
 * class: SamplePartition
 * package: cn.com.dimensoft.kafka
 * author:zxh
 * time: 2015年9月28日 下午5:37:19
 * description: 設置自定義的partition,指明當topic有多個partition時如何對message進行分區
 */
public class SamplePartition implements Partitioner {

    /**
     * constructor
     * author:zxh
     * @param verifiableProperties
     * description: 去除該構造方法後啓動producer報錯NoSuchMethodException
     */
    public SamplePartition(VerifiableProperties verifiableProperties) {

    }

    @Override
    /**
     * 這裏對message分區的依據只是簡單的讓key(這裏的key就是Producer[K,V]中的K)對partition的數量取模
     */
    public int partition(Object obj, int partitions) {

        // 對partitions數量取模
        return Integer.parseInt(obj.toString()) % partitions;
    }

}

Constant


Constant是常量類:

/**
  * project:kafka-study
  * file:Constant.java
  * author:zxh
  * time:2015年9月28日 上午10:29:50
  * description:
  */
package cn.com.dimensoft.kafka.constant;
/**
 * class: Constant
 * package: cn.com.dimensoft.kafka.constant
 * author:zxh
 * time: 2015年9月28日 上午10:29:50
 * description: 
 */
public class Constant {

    public static final String TOPIC = "topic-test";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章